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