]> Dogcows Code - chaz/openbox/blob - src/frame.cc
readd titlebar buttons. but they dont press yet
[chaz/openbox] / src / frame.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "config.h"
4
5 extern "C" {
6 #ifdef SHAPE
7 #include <X11/extensions/shape.h>
8 #endif // SHAPE
9 }
10
11 #include "frame.hh"
12 #include "client.hh"
13 #include "openbox.hh"
14 #include "otk/display.hh"
15 #include "otk/surface.hh"
16
17 #include <string>
18 #include <cassert>
19
20 namespace ob {
21
22 const long Frame::event_mask;
23
24 Window createWindow(const otk::ScreenInfo *info, Window parent,
25 unsigned long mask, XSetWindowAttributes *attrib)
26 {
27 return XCreateWindow(**otk::display, parent, 0, 0, 1, 1, 0,
28 info->depth(), InputOutput, info->visual(),
29 mask, attrib);
30
31 }
32
33 Frame::Frame(Client *client)
34 : _client(client),
35 _visible(false),
36 _plate(0),
37 _title(0),
38 _label(0),
39 _handle(0),
40 _lgrip(0),
41 _rgrip(0),
42 _max(0),
43 _desk(0),
44 _iconify(0),
45 _icon(0),
46 _close(0),
47 _frame_sur(0),
48 _title_sur(0),
49 _label_sur(0),
50 _handle_sur(0),
51 _grip_sur(0),
52 _max_sur(0),
53 _desk_sur(0),
54 _iconify_sur(0),
55 _icon_sur(0),
56 _close_sur(0),
57 _max_press(false),
58 _desk_press(false),
59 _iconify_press(false),
60 _icon_press(false),
61 _close_press(false)
62 {
63 assert(client);
64
65 XSetWindowAttributes attrib;
66 unsigned long mask;
67 const otk::ScreenInfo *info = otk::display->screenInfo(client->screen());
68
69 // create all of the decor windows (except title bar buttons)
70 mask = CWOverrideRedirect | CWEventMask;
71 attrib.event_mask = Frame::event_mask;
72 attrib.override_redirect = true;
73 _frame = createWindow(info, info->rootWindow(), mask, &attrib);
74
75 mask = 0;
76 _plate = createWindow(info, _frame, mask, &attrib);
77 mask = CWEventMask;
78 attrib.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
79 ExposureMask);
80 _title = createWindow(info, _frame, mask, &attrib);
81 _label = createWindow(info, _title, mask, &attrib);
82 _max = createWindow(info, _title, mask, &attrib);
83 _close = createWindow(info, _title, mask, &attrib);
84 _desk = createWindow(info, _title, mask, &attrib);
85 _icon = createWindow(info, _title, mask, &attrib);
86 _iconify = createWindow(info, _title, mask, &attrib);
87 _handle = createWindow(info, _frame, mask, &attrib);
88 mask |= CWCursor;
89 attrib.cursor = openbox->cursors().ll_angle;
90 _lgrip = createWindow(info, _handle, mask, &attrib);
91 attrib.cursor = openbox->cursors().lr_angle;
92 _rgrip = createWindow(info, _handle, mask, &attrib);
93
94 // the other stuff is shown based on decor settings
95 XMapWindow(**otk::display, _plate);
96 XMapWindow(**otk::display, _lgrip);
97 XMapWindow(**otk::display, _rgrip);
98 XMapWindow(**otk::display, _label);
99
100 applyStyle(*otk::RenderStyle::style(_client->screen()));
101
102 _layout = "NDITMC";
103
104 // register all of the windows with the event dispatcher
105 Window *w = allWindows();
106 for (unsigned int i = 0; w[i]; ++i)
107 openbox->registerHandler(w[i], this);
108 delete [] w;
109 }
110
111 Frame::~Frame()
112 {
113 // unregister all of the windows with the event dispatcher
114 Window *w = allWindows();
115 for (unsigned int i = 0; w[i]; ++i)
116 openbox->clearHandler(w[i]);
117 delete [] w;
118
119 XDestroyWindow(**otk::display, _rgrip);
120 XDestroyWindow(**otk::display, _lgrip);
121 XDestroyWindow(**otk::display, _handle);
122 XDestroyWindow(**otk::display, _max);
123 XDestroyWindow(**otk::display, _icon);
124 XDestroyWindow(**otk::display, _iconify);
125 XDestroyWindow(**otk::display, _desk);
126 XDestroyWindow(**otk::display, _close);
127 XDestroyWindow(**otk::display, _label);
128 XDestroyWindow(**otk::display, _title);
129 XDestroyWindow(**otk::display, _frame);
130
131 if (_frame_sur) delete _frame_sur;
132 if (_title_sur) delete _title_sur;
133 if (_label_sur) delete _label_sur;
134 if (_handle_sur) delete _handle_sur;
135 if (_grip_sur) delete _grip_sur;
136 if (_max_sur) delete _max_sur;
137 if (_desk_sur) delete _desk_sur;
138 if (_iconify_sur) delete _iconify_sur;
139 if (_icon_sur) delete _icon_sur;
140 if (_close_sur) delete _close_sur;
141 }
142
143 void Frame::show()
144 {
145 if (!_visible) {
146 _visible = true;
147 XMapWindow(**otk::display, _frame);
148 }
149 }
150
151 void Frame::hide()
152 {
153 if (_visible) {
154 _visible = false;
155 XUnmapWindow(**otk::display, _frame);
156 }
157 }
158
159 MouseContext::MC Frame::mouseContext(Window win) const
160 {
161 if (win == _frame) return MouseContext::Frame;
162 if (win == _title ||
163 win == _label) return MouseContext::Titlebar;
164 if (win == _handle) return MouseContext::Handle;
165 if (win == _plate) return MouseContext::Window;
166 if (win == _lgrip ||
167 win == _rgrip) return MouseContext::Grip;
168 if (win == _max) return MouseContext::MaximizeButton;
169 if (win == _close) return MouseContext::CloseButton;
170 if (win == _desk) return MouseContext::AllDesktopsButton;
171 if (win == _iconify)return MouseContext::IconifyButton;
172 if (win == _icon) return MouseContext::IconButton;
173 return (MouseContext::MC) -1;
174 }
175
176 Window *Frame::allWindows() const
177 {
178 Window *w = new Window[12 + 1];
179 unsigned int i = 0;
180 w[i++] = _frame;
181 w[i++] = _plate;
182 w[i++] = _title;
183 w[i++] = _label;
184 w[i++] = _handle;
185 w[i++] = _lgrip;
186 w[i++] = _rgrip;
187 w[i++] = _max;
188 w[i++] = _desk;
189 w[i++] = _close;
190 w[i++] = _icon;
191 w[i++] = _iconify;
192 w[i] = 0;
193 return w;
194 }
195
196 void Frame::applyStyle(const otk::RenderStyle &style)
197 {
198 // set static border colors
199 XSetWindowBorder(**otk::display, _frame, style.frameBorderColor()->pixel());
200 XSetWindowBorder(**otk::display, _title, style.frameBorderColor()->pixel());
201 XSetWindowBorder(**otk::display, _handle, style.frameBorderColor()->pixel());
202 XSetWindowBorder(**otk::display, _lgrip, style.frameBorderColor()->pixel());
203 XSetWindowBorder(**otk::display, _rgrip, style.frameBorderColor()->pixel());
204
205 // size all the fixed-size elements
206 geom.font_height = style.labelFont()->height();
207 if (geom.font_height < 1) geom.font_height = 1;
208 geom.button_size = geom.font_height - 2;
209 if (geom.button_size < 1) geom.button_size = 1;
210 geom.handle_height = style.handleWidth();
211 if (geom.handle_height < 1) geom.handle_height = 1;
212 geom.bevel = style.bevelWidth();
213
214 XResizeWindow(**otk::display, _lgrip, geom.grip_width(), geom.handle_height);
215 XResizeWindow(**otk::display, _rgrip, geom.grip_width(), geom.handle_height);
216
217 XResizeWindow(**otk::display, _max, geom.button_size, geom.button_size);
218 XResizeWindow(**otk::display, _close, geom.button_size, geom.button_size);
219 XResizeWindow(**otk::display, _desk, geom.button_size, geom.button_size);
220 XResizeWindow(**otk::display, _iconify, geom.button_size, geom.button_size);
221 XResizeWindow(**otk::display, _icon, geom.button_size, geom.button_size);
222 }
223
224 void Frame::styleChanged(const otk::RenderStyle &style)
225 {
226 applyStyle(style);
227
228 // size/position everything
229 adjustSize();
230 adjustPosition();
231 }
232
233 void Frame::adjustFocus()
234 {
235 // XXX optimizations later...
236 adjustSize();
237 }
238
239 void Frame::adjustTitle()
240 {
241 // XXX optimizations later...
242 adjustSize();
243 }
244
245 static void render(int screen, const otk::Size &size, Window win,
246 otk::Surface **surface,
247 const otk::RenderTexture &texture, bool freedata=true)
248 {
249 otk::Surface *s = new otk::Surface(screen, size);
250 otk::display->renderControl(screen)->drawBackground(*s, texture);
251 XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap());
252 XClearWindow(**otk::display, win);
253 if (*surface) delete *surface;
254 if (freedata) s->freePixelData();
255 *surface = s;
256 }
257
258 void Frame::adjustSize()
259 {
260 Client::DecorationFlags decorations = _client->decorations();
261 const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
262
263 if (decorations & Client::Decor_Border) {
264 geom.bwidth = style->frameBorderWidth();
265 geom.cbwidth = style->clientBorderWidth();
266 } else {
267 geom.bwidth = geom.cbwidth = 0;
268 }
269 _innersize.left = _innersize.top = _innersize.bottom = _innersize.right =
270 geom.cbwidth;
271 geom.width = _client->area().width() + geom.cbwidth * 2;
272 assert(geom.width > 0);
273
274 // set border widths
275 XSetWindowBorderWidth(**otk::display, _plate, geom.cbwidth);
276 XSetWindowBorderWidth(**otk::display, _frame, geom.bwidth);
277 XSetWindowBorderWidth(**otk::display, _title, geom.bwidth);
278 XSetWindowBorderWidth(**otk::display, _handle, geom.bwidth);
279 XSetWindowBorderWidth(**otk::display, _lgrip, geom.bwidth);
280 XSetWindowBorderWidth(**otk::display, _rgrip, geom.bwidth);
281
282 // position/size and map/unmap all the windows
283
284 if (decorations & Client::Decor_Titlebar) {
285 XMoveResizeWindow(**otk::display, _title, -geom.bwidth, -geom.bwidth,
286 geom.width, geom.title_height());
287 _innersize.top += geom.title_height() + geom.bwidth;
288 XMapWindow(**otk::display, _title);
289
290 // layout the title bar elements
291 layoutTitle();
292 } else
293 XUnmapWindow(**otk::display, _title);
294
295 if (decorations & Client::Decor_Handle) {
296 geom.handle_y = _innersize.top + _client->area().height() + geom.cbwidth;
297 XMoveResizeWindow(**otk::display, _handle, -geom.bwidth, geom.handle_y,
298 geom.width, geom.handle_height);
299 XMoveWindow(**otk::display, _lgrip, -geom.bwidth, -geom.bwidth);
300 XMoveWindow(**otk::display, _rgrip,
301 -geom.bwidth + geom.width - geom.grip_width(),
302 -geom.bwidth);
303 _innersize.bottom += geom.handle_height + geom.bwidth;
304 XMapWindow(**otk::display, _handle);
305 } else
306 XUnmapWindow(**otk::display, _handle);
307
308 XResizeWindow(**otk::display, _frame, geom.width,
309 (_client->shaded() ? geom.title_height() :
310 _innersize.top + _innersize.bottom +
311 _client->area().height()));
312
313 // do this in two steps because clients whose gravity is set to
314 // 'Static' don't end up getting moved at all with an XMoveResizeWindow
315 XMoveWindow(**otk::display, _plate, _innersize.left - geom.cbwidth,
316 _innersize.top - geom.cbwidth);
317 XResizeWindow(**otk::display, _plate, _client->area().width(),
318 _client->area().height());
319
320 _size.left = _innersize.left + geom.bwidth;
321 _size.right = _innersize.right + geom.bwidth;
322 _size.top = _innersize.top + geom.bwidth;
323 _size.bottom = _innersize.bottom + geom.bwidth;
324
325 _area = otk::Rect(_area.position(), otk::Size(_client->area().width() +
326 _size.left + _size.right,
327 _client->area().height() +
328 _size.top + _size.bottom));
329
330 // render all the elements
331 int screen = _client->screen();
332 bool focus = _client->focused();
333 if (decorations & Client::Decor_Titlebar) {
334 render(screen, otk::Size(geom.width, geom.title_height()), _title,
335 &_title_sur, *(focus ? style->titlebarFocusBackground() :
336 style->titlebarUnfocusBackground()), false);
337
338 renderLabel();
339 renderMax();
340 renderDesk();
341 renderIconify();
342 renderIcon();
343 renderClose();
344 }
345
346 if (decorations & Client::Decor_Handle) {
347 render(screen, otk::Size(geom.width, geom.handle_height), _handle,
348 &_handle_sur, *(focus ? style->handleFocusBackground() :
349 style->handleUnfocusBackground()));
350 render(screen, otk::Size(geom.grip_width(), geom.handle_height), _lgrip,
351 &_grip_sur, *(focus ? style->gripFocusBackground() :
352 style->gripUnfocusBackground()));
353 XSetWindowBackgroundPixmap(**otk::display, _rgrip, _grip_sur->pixmap());
354 XClearWindow(**otk::display, _rgrip);
355 }
356
357 XSetWindowBorder(**otk::display, _plate,
358 focus ? style->clientBorderFocusColor()->pixel() :
359 style->clientBorderUnfocusColor()->pixel());
360
361 adjustShape();
362 }
363
364 void Frame::renderLabel()
365 {
366 const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
367 const otk::RenderControl *control =
368 otk::display->renderControl(_client->screen());
369 const otk::Font *font = style->labelFont();
370
371 otk::Surface *s = new otk::Surface(_client->screen(),
372 otk::Size(geom.label_width,
373 geom.label_height()));
374 control->drawBackground(*s, *(_client->focused() ?
375 style->labelFocusBackground() :
376 style->labelUnfocusBackground()));
377
378 otk::ustring t = _client->title(); // the actual text to draw
379 int x = geom.bevel; // x coord for the text
380
381 if (x * 2 > geom.label_width) return; // no room at all
382
383 // find a string that will fit inside the area for text
384 otk::ustring::size_type text_len = t.size();
385 int length;
386 int maxsize = geom.label_width - geom.bevel * 2;
387
388 do {
389 t.resize(text_len);
390 length = font->measureString(t); // this returns an unsigned, so check < 0
391 if (length < 0) length = maxsize; // if the string's that long just adjust
392 } while (length > maxsize && text_len-- > 0);
393
394 if (text_len <= 0) return; // won't fit anything
395
396 // justify the text
397 switch (style->labelTextJustify()) {
398 case otk::RenderStyle::RightBottomJustify:
399 x += maxsize - length;
400 break;
401 case otk::RenderStyle::CenterJustify:
402 x += (maxsize - length) / 2;
403 break;
404 case otk::RenderStyle::LeftTopJustify:
405 break;
406 }
407
408 control->drawString(*s, *font, x, 0,
409 *(_client->focused() ? style->textFocusColor() :
410 style->textUnfocusColor()), t);
411
412 XSetWindowBackgroundPixmap(**otk::display, _label, s->pixmap());
413 XClearWindow(**otk::display, _label);
414 if (_label_sur) delete _label_sur;
415 s->freePixelData();
416 _label_sur = s;
417 }
418
419 static void renderButton(int screen, bool focus, bool press, Window win,
420 otk::Surface **sur, int butsize,
421 const otk::PixmapMask *mask)
422 {
423 const otk::RenderStyle *style = otk::RenderStyle::style(screen);
424 const otk::RenderControl *control = otk::display->renderControl(screen);
425 otk::Surface *s = new otk::Surface(screen, otk::Size(butsize, butsize));
426
427 const otk::RenderTexture *tx = (focus ?
428 (press ?
429 style->buttonPressFocusBackground() :
430 style->buttonUnpressFocusBackground()) :
431 (press ?
432 style->buttonPressUnfocusBackground() :
433 style->buttonUnpressUnfocusBackground()));
434 const otk::RenderColor *maskcolor = (focus ?
435 style->buttonFocusColor() :
436 style->buttonUnfocusColor());
437 control->drawBackground(*s, *tx);
438 control->drawMask(*s, *maskcolor, *mask);
439
440 XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap());
441 XClearWindow(**otk::display, win);
442 if (*sur) delete *sur;
443 *sur = s;
444 }
445
446 void Frame::renderMax()
447 {
448 renderButton(_client->screen(), _client->focused(), _max_press, _max,
449 &_max_sur, geom.button_size,
450 otk::RenderStyle::style(_client->screen())->maximizeMask());
451 }
452
453 void Frame::renderDesk()
454 {
455 renderButton(_client->screen(), _client->focused(), _desk_press, _desk,
456 &_desk_sur, geom.button_size,
457 otk::RenderStyle::style(_client->screen())->alldesktopsMask());
458 }
459
460 void Frame::renderIconify()
461 {
462 renderButton(_client->screen(), _client->focused(), _iconify_press, _iconify,
463 &_iconify_sur, geom.button_size,
464 otk::RenderStyle::style(_client->screen())->iconifyMask());
465 }
466
467 void Frame::renderClose()
468 {
469 renderButton(_client->screen(), _client->focused(), _close_press, _close,
470 &_close_sur, geom.button_size,
471 otk::RenderStyle::style(_client->screen())->closeMask());
472 }
473
474 void Frame::renderIcon()
475 {
476 const int screen = _client->screen();
477 const otk::RenderControl *control = otk::display->renderControl(screen);
478
479 otk::Surface *s = new otk::Surface(screen, otk::Size(geom.button_size,
480 geom.button_size));
481 otk::pixel32 *dest = s->pixelData(), *src;
482 int w = _title_sur->size().width();
483
484 src = _title_sur->pixelData() + w * (geom.bevel + 1) + geom.icon_x;
485
486 // get the background under the icon button
487 for (int y = 0; y < geom.button_size; ++y, src += w - geom.button_size)
488 for (int x = 0; x < geom.button_size; ++x, ++dest, ++src)
489 *dest = *src;
490 control->drawImage(*s, 0, 0, 0);
491
492 XSetWindowBackgroundPixmap(**otk::display, _icon, s->pixmap());
493 XClearWindow(**otk::display, _icon);
494 if (_icon_sur) delete _icon_sur;
495 _icon_sur = s;
496 }
497
498 void Frame::layoutTitle()
499 {
500 geom.label_width = geom.width - geom.bevel * 2 -
501 (geom.button_size + geom.bevel) * (_layout.size() - 1);
502 if (geom.label_width < 1) geom.label_width = 1;
503
504 XResizeWindow(**otk::display, _label, geom.label_width, geom.font_height);
505
506 int x = geom.bevel;
507 bool n, d, i, l, m ,c;
508 n = d = i = l = m = c = false;
509 for (const char *lc = _layout.c_str(); *lc; ++lc) {
510 switch (*lc) {
511 case 'n':
512 case 'N':
513 geom.icon_x = x;
514 XMapWindow(**otk::display, _icon);
515 XMoveWindow(**otk::display, _icon, x, geom.bevel + 1);
516 n = true;
517 x += geom.button_size;
518 break;
519 case 'd':
520 case 'D':
521 XMapWindow(**otk::display, _desk);
522 XMoveWindow(**otk::display, _desk, x, geom.bevel + 1);
523 d = true;
524 x += geom.button_size;
525 break;
526 case 'i':
527 case 'I':
528 XMapWindow(**otk::display, _iconify);
529 XMoveWindow(**otk::display, _iconify, x, geom.bevel + 1);
530 i = true;
531 x += geom.button_size;
532 break;
533 case 't':
534 case 'T':
535 XMapWindow(**otk::display, _label);
536 XMoveWindow(**otk::display, _label, x, geom.bevel);
537 l = true;
538 x += geom.label_width;
539 break;
540 case 'm':
541 case 'M':
542 XMapWindow(**otk::display, _max);
543 XMoveWindow(**otk::display, _max, x, geom.bevel + 1);
544 m = true;
545 x += geom.button_size;
546 break;
547 case 'c':
548 case 'C':
549 XMapWindow(**otk::display, _close);
550 XMoveWindow(**otk::display, _close, x, geom.bevel + 1);
551 c = true;
552 x += geom.button_size;
553 break;
554 }
555 x += geom.bevel;
556 }
557 if (!n) XUnmapWindow(**otk::display, _icon);
558 if (!d) XUnmapWindow(**otk::display, _desk);
559 if (!i) XUnmapWindow(**otk::display, _iconify);
560 if (!l) XUnmapWindow(**otk::display, _label);
561 if (!m) XUnmapWindow(**otk::display, _max);
562 if (!c) XUnmapWindow(**otk::display, _close);
563 }
564
565 void Frame::adjustPosition()
566 {
567 int x, y;
568 x = _client->area().x();
569 y = _client->area().y();
570 clientGravity(x, y);
571 XMoveWindow(**otk::display, _frame, x, y);
572 _area = otk::Rect(otk::Point(x, y), _area.size());
573 }
574
575
576 void Frame::adjustShape()
577 {
578 #ifdef SHAPE
579 Client::DecorationFlags decorations = _client->decorations();
580
581 if (!_client->shaped()) {
582 // clear the shape on the frame window
583 XShapeCombineMask(**otk::display, _frame, ShapeBounding,
584 _innersize.left,
585 _innersize.top,
586 None, ShapeSet);
587 } else {
588 // make the frame's shape match the clients
589 XShapeCombineShape(**otk::display, _frame, ShapeBounding,
590 _innersize.left,
591 _innersize.top,
592 _client->window(), ShapeBounding, ShapeSet);
593
594 int num = 0;
595 XRectangle xrect[2];
596
597 if (decorations & Client::Decor_Titlebar) {
598 xrect[0].x = -geom.bevel;
599 xrect[0].y = -geom.bevel;
600 xrect[0].width = geom.width + geom.bwidth * 2;
601 xrect[0].height = geom.title_height() + geom.bwidth * 2;
602 ++num;
603 }
604
605 if (decorations & Client::Decor_Handle) {
606 xrect[1].x = -geom.bevel;
607 xrect[1].y = geom.handle_y;
608 xrect[1].width = geom.width + geom.bwidth * 2;
609 xrect[1].height = geom.handle_height + geom.bwidth * 2;
610 ++num;
611 }
612
613 XShapeCombineRectangles(**otk::display, _frame,
614 ShapeBounding, 0, 0, xrect, num,
615 ShapeUnion, Unsorted);
616 }
617 #endif // SHAPE
618 }
619
620
621 void Frame::adjustState()
622 {
623 // XXX _button_alldesk.update();
624 // XXX _button_max.update();
625 }
626
627
628 void Frame::grabClient()
629 {
630 // reparent the client to the frame
631 XReparentWindow(**otk::display, _client->window(), _plate, 0, 0);
632 /*
633 When reparenting the client window, it is usually not mapped yet, since
634 this occurs from a MapRequest. However, in the case where Openbox is
635 starting up, the window is already mapped, so we'll see unmap events for
636 it. There are 2 unmap events generated that we see, one with the 'event'
637 member set the root window, and one set to the client, but both get handled
638 and need to be ignored.
639 */
640 if (openbox->state() == Openbox::State_Starting)
641 _client->ignore_unmaps += 2;
642
643 // select the event mask on the client's parent (to receive config/map req's)
644 XSelectInput(**otk::display, _plate, SubstructureRedirectMask);
645
646 // map the client so it maps when the frame does
647 XMapWindow(**otk::display, _client->window());
648
649 adjustSize();
650 adjustPosition();
651 }
652
653
654 void Frame::releaseClient()
655 {
656 XEvent ev;
657
658 // check if the app has already reparented its window away
659 if (XCheckTypedWindowEvent(**otk::display, _client->window(),
660 ReparentNotify, &ev)) {
661 XPutBackEvent(**otk::display, &ev);
662 // re-map the window since the unmanaging process unmaps it
663 XMapWindow(**otk::display, _client->window());
664 } else {
665 // according to the ICCCM - if the client doesn't reparent itself, then we
666 // will reparent the window to root for them
667 XReparentWindow(**otk::display, _client->window(),
668 otk::display->screenInfo(_client->screen())->rootWindow(),
669 _client->area().x(), _client->area().y());
670 }
671 }
672
673
674 void Frame::clientGravity(int &x, int &y)
675 {
676 // horizontal
677 switch (_client->gravity()) {
678 default:
679 case NorthWestGravity:
680 case SouthWestGravity:
681 case WestGravity:
682 break;
683
684 case NorthGravity:
685 case SouthGravity:
686 case CenterGravity:
687 x -= (_size.left + _size.right) / 2;
688 break;
689
690 case NorthEastGravity:
691 case SouthEastGravity:
692 case EastGravity:
693 x -= _size.left + _size.right;
694 break;
695
696 case ForgetGravity:
697 case StaticGravity:
698 x -= _size.left;
699 break;
700 }
701
702 // vertical
703 switch (_client->gravity()) {
704 default:
705 case NorthWestGravity:
706 case NorthEastGravity:
707 case NorthGravity:
708 break;
709
710 case CenterGravity:
711 case EastGravity:
712 case WestGravity:
713 y -= (_size.top + _size.bottom) / 2;
714 break;
715
716 case SouthWestGravity:
717 case SouthEastGravity:
718 case SouthGravity:
719 y -= _size.top + _size.bottom;
720 break;
721
722 case ForgetGravity:
723 case StaticGravity:
724 y -= _size.top;
725 break;
726 }
727 }
728
729
730 void Frame::frameGravity(int &x, int &y)
731 {
732 // horizontal
733 switch (_client->gravity()) {
734 default:
735 case NorthWestGravity:
736 case WestGravity:
737 case SouthWestGravity:
738 break;
739 case NorthGravity:
740 case CenterGravity:
741 case SouthGravity:
742 x += (_size.left + _size.right) / 2;
743 break;
744 case NorthEastGravity:
745 case EastGravity:
746 case SouthEastGravity:
747 x += _size.left + _size.right;
748 break;
749 case StaticGravity:
750 case ForgetGravity:
751 x += _size.left;
752 break;
753 }
754
755 // vertical
756 switch (_client->gravity()) {
757 default:
758 case NorthWestGravity:
759 case WestGravity:
760 case SouthWestGravity:
761 break;
762 case NorthGravity:
763 case CenterGravity:
764 case SouthGravity:
765 y += (_size.top + _size.bottom) / 2;
766 break;
767 case NorthEastGravity:
768 case EastGravity:
769 case SouthEastGravity:
770 y += _size.top + _size.bottom;
771 break;
772 case StaticGravity:
773 case ForgetGravity:
774 y += _size.top;
775 break;
776 }
777 }
778
779
780 }
This page took 0.067868 seconds and 4 git commands to generate.