1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
7 #include <X11/extensions/shape.h>
13 #include "otk/display.hh"
14 #include "otk/surface.hh"
21 const long Frame::event_mask
;
23 Window
createWindow(const otk::ScreenInfo
*info
, Window parent
,
24 unsigned long mask
, XSetWindowAttributes
*attrib
)
26 return XCreateWindow(**otk::display
, parent
, 0, 0, 1, 1, 0,
27 info
->depth(), InputOutput
, info
->visual(),
32 Frame::Frame(Client
*client
)
58 _iconify_press(false),
65 XSetWindowAttributes attrib
;
67 const otk::ScreenInfo
*info
= otk::display
->screenInfo(client
->screen());
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
);
76 _plate
= createWindow(info
, _frame
, mask
, &attrib
);
78 attrib
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
|
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
);
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
);
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
);
100 applyStyle(*otk::RenderStyle::style(_client
->screen()));
102 _layout
= openbox
->screen(_client
->screen())->config().titlebar_layout
;
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);
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
]);
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
);
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
;
147 XMapWindow(**otk::display
, _frame
);
155 XUnmapWindow(**otk::display
, _frame
);
159 void Frame::buttonPressHandler(const XButtonEvent
&e
)
161 if (_press_button
) return;
162 _press_button
= e
.button
;
164 if (e
.window
== _max
) {
168 if (e
.window
== _close
) {
172 if (e
.window
== _desk
) {
176 if (e
.window
== _iconify
) {
177 _iconify_press
= true;
180 if (e
.window
== _icon
) {
186 void Frame::buttonReleaseHandler(const XButtonEvent
&e
)
188 if (e
.button
!= _press_button
) return;
191 if (e
.window
== _max
) {
195 if (e
.window
== _close
) {
196 _close_press
= false;
199 if (e
.window
== _desk
) {
203 if (e
.window
== _iconify
) {
204 _iconify_press
= false;
207 if (e
.window
== _icon
) {
213 MouseContext::MC
Frame::mouseContext(Window win
) const
215 if (win
== _frame
) return MouseContext::Frame
;
217 win
== _label
) return MouseContext::Titlebar
;
218 if (win
== _handle
) return MouseContext::Handle
;
219 if (win
== _plate
) return MouseContext::Window
;
221 win
== _rgrip
) return MouseContext::Grip
;
222 if (win
== _max
) return MouseContext::MaximizeButton
;
223 if (win
== _close
) return MouseContext::CloseButton
;
224 if (win
== _desk
) return MouseContext::AllDesktopsButton
;
225 if (win
== _iconify
)return MouseContext::IconifyButton
;
226 if (win
== _icon
) return MouseContext::IconButton
;
227 return (MouseContext::MC
) -1;
230 Window
*Frame::allWindows() const
232 Window
*w
= new Window
[12 + 1];
250 void Frame::applyStyle(const otk::RenderStyle
&style
)
252 // set static border colors
253 XSetWindowBorder(**otk::display
, _frame
, style
.frameBorderColor()->pixel());
254 XSetWindowBorder(**otk::display
, _title
, style
.frameBorderColor()->pixel());
255 XSetWindowBorder(**otk::display
, _handle
, style
.frameBorderColor()->pixel());
256 XSetWindowBorder(**otk::display
, _lgrip
, style
.frameBorderColor()->pixel());
257 XSetWindowBorder(**otk::display
, _rgrip
, style
.frameBorderColor()->pixel());
259 // size all the fixed-size elements
260 geom
.font_height
= style
.labelFont()->height();
261 if (geom
.font_height
< 1) geom
.font_height
= 1;
262 geom
.button_size
= geom
.font_height
- 2;
263 if (geom
.button_size
< 1) geom
.button_size
= 1;
264 geom
.handle_height
= style
.handleWidth();
265 if (geom
.handle_height
< 1) geom
.handle_height
= 1;
266 geom
.bevel
= style
.bevelWidth();
268 XResizeWindow(**otk::display
, _lgrip
, geom
.grip_width(), geom
.handle_height
);
269 XResizeWindow(**otk::display
, _rgrip
, geom
.grip_width(), geom
.handle_height
);
271 XResizeWindow(**otk::display
, _max
, geom
.button_size
, geom
.button_size
);
272 XResizeWindow(**otk::display
, _close
, geom
.button_size
, geom
.button_size
);
273 XResizeWindow(**otk::display
, _desk
, geom
.button_size
, geom
.button_size
);
274 XResizeWindow(**otk::display
, _iconify
, geom
.button_size
, geom
.button_size
);
275 XResizeWindow(**otk::display
, _icon
, geom
.button_size
, geom
.button_size
);
278 void Frame::styleChanged(const otk::RenderStyle
&style
)
282 // size/position everything
287 void Frame::adjustFocus()
289 // XXX optimizations later...
293 void Frame::adjustTitle()
295 // XXX optimizations later...
299 static void render(int screen
, const otk::Size
&size
, Window win
,
300 otk::Surface
**surface
,
301 const otk::RenderTexture
&texture
, bool freedata
=true)
303 otk::Surface
*s
= new otk::Surface(screen
, size
);
304 otk::display
->renderControl(screen
)->drawBackground(*s
, texture
);
305 XSetWindowBackgroundPixmap(**otk::display
, win
, s
->pixmap());
306 XClearWindow(**otk::display
, win
);
307 if (*surface
) delete *surface
;
308 if (freedata
) s
->freePixelData();
312 void Frame::adjustSize()
314 _decorations
= _client
->decorations();
315 const otk::RenderStyle
*style
= otk::RenderStyle::style(_client
->screen());
317 if (_decorations
& Client::Decor_Border
) {
318 geom
.bwidth
= style
->frameBorderWidth();
319 geom
.cbwidth
= style
->clientBorderWidth();
321 geom
.bwidth
= geom
.cbwidth
= 0;
323 _innersize
.left
= _innersize
.top
= _innersize
.bottom
= _innersize
.right
=
325 geom
.width
= _client
->area().width() + geom
.cbwidth
* 2;
326 assert(geom
.width
> 0);
329 XSetWindowBorderWidth(**otk::display
, _plate
, geom
.cbwidth
);
330 XSetWindowBorderWidth(**otk::display
, _frame
, geom
.bwidth
);
331 XSetWindowBorderWidth(**otk::display
, _title
, geom
.bwidth
);
332 XSetWindowBorderWidth(**otk::display
, _handle
, geom
.bwidth
);
333 XSetWindowBorderWidth(**otk::display
, _lgrip
, geom
.bwidth
);
334 XSetWindowBorderWidth(**otk::display
, _rgrip
, geom
.bwidth
);
336 // position/size and map/unmap all the windows
338 if (_decorations
& Client::Decor_Titlebar
) {
339 XMoveResizeWindow(**otk::display
, _title
, -geom
.bwidth
, -geom
.bwidth
,
340 geom
.width
, geom
.title_height());
341 _innersize
.top
+= geom
.title_height() + geom
.bwidth
;
342 XMapWindow(**otk::display
, _title
);
344 // layout the title bar elements
347 XUnmapWindow(**otk::display
, _title
);
348 // make all the titlebar stuff not render
349 _decorations
&= ~(Client::Decor_Icon
| Client::Decor_Iconify
|
350 Client::Decor_Maximize
| Client::Decor_Close
|
351 Client::Decor_AllDesktops
);
354 if (_decorations
& Client::Decor_Handle
) {
355 geom
.handle_y
= _innersize
.top
+ _client
->area().height() + geom
.cbwidth
;
356 XMoveResizeWindow(**otk::display
, _handle
, -geom
.bwidth
, geom
.handle_y
,
357 geom
.width
, geom
.handle_height
);
358 XMoveWindow(**otk::display
, _lgrip
, -geom
.bwidth
, -geom
.bwidth
);
359 XMoveWindow(**otk::display
, _rgrip
,
360 -geom
.bwidth
+ geom
.width
- geom
.grip_width(),
362 _innersize
.bottom
+= geom
.handle_height
+ geom
.bwidth
;
363 XMapWindow(**otk::display
, _handle
);
365 XUnmapWindow(**otk::display
, _handle
);
367 XResizeWindow(**otk::display
, _frame
, geom
.width
,
368 (_client
->shaded() ? geom
.title_height() :
369 _innersize
.top
+ _innersize
.bottom
+
370 _client
->area().height()));
372 // do this in two steps because clients whose gravity is set to
373 // 'Static' don't end up getting moved at all with an XMoveResizeWindow
374 XMoveWindow(**otk::display
, _plate
, _innersize
.left
- geom
.cbwidth
,
375 _innersize
.top
- geom
.cbwidth
);
376 XResizeWindow(**otk::display
, _plate
, _client
->area().width(),
377 _client
->area().height());
379 _size
.left
= _innersize
.left
+ geom
.bwidth
;
380 _size
.right
= _innersize
.right
+ geom
.bwidth
;
381 _size
.top
= _innersize
.top
+ geom
.bwidth
;
382 _size
.bottom
= _innersize
.bottom
+ geom
.bwidth
;
384 _area
= otk::Rect(_area
.position(), otk::Size(_client
->area().width() +
385 _size
.left
+ _size
.right
,
386 _client
->area().height() +
387 _size
.top
+ _size
.bottom
));
389 // render all the elements
390 int screen
= _client
->screen();
391 bool focus
= _client
->focused();
392 if (_decorations
& Client::Decor_Titlebar
) {
393 render(screen
, otk::Size(geom
.width
, geom
.title_height()), _title
,
394 &_title_sur
, *(focus
? style
->titlebarFocusBackground() :
395 style
->titlebarUnfocusBackground()), false);
405 if (_decorations
& Client::Decor_Handle
) {
406 render(screen
, otk::Size(geom
.width
, geom
.handle_height
), _handle
,
407 &_handle_sur
, *(focus
? style
->handleFocusBackground() :
408 style
->handleUnfocusBackground()));
409 render(screen
, otk::Size(geom
.grip_width(), geom
.handle_height
), _lgrip
,
410 &_grip_sur
, *(focus
? style
->gripFocusBackground() :
411 style
->gripUnfocusBackground()));
412 XSetWindowBackgroundPixmap(**otk::display
, _rgrip
, _grip_sur
->pixmap());
413 XClearWindow(**otk::display
, _rgrip
);
416 XSetWindowBorder(**otk::display
, _plate
,
417 focus
? style
->clientBorderFocusColor()->pixel() :
418 style
->clientBorderUnfocusColor()->pixel());
423 void Frame::renderLabel()
425 const otk::RenderStyle
*style
= otk::RenderStyle::style(_client
->screen());
426 const otk::RenderControl
*control
=
427 otk::display
->renderControl(_client
->screen());
428 const otk::Font
*font
= style
->labelFont();
430 otk::Surface
*s
= new otk::Surface(_client
->screen(),
431 otk::Size(geom
.label_width
,
432 geom
.label_height()));
433 control
->drawBackground(*s
, *(_client
->focused() ?
434 style
->labelFocusBackground() :
435 style
->labelUnfocusBackground()));
437 otk::ustring t
= _client
->title(); // the actual text to draw
438 int x
= geom
.bevel
; // x coord for the text
440 if (x
* 2 > geom
.label_width
) return; // no room at all
442 // find a string that will fit inside the area for text
443 otk::ustring::size_type text_len
= t
.size();
445 int maxsize
= geom
.label_width
- geom
.bevel
* 2;
449 length
= font
->measureString(t
); // this returns an unsigned, so check < 0
450 if (length
< 0) length
= maxsize
; // if the string's that long just adjust
451 } while (length
> maxsize
&& text_len
-- > 0);
453 if (text_len
<= 0) return; // won't fit anything
456 switch (style
->labelTextJustify()) {
457 case otk::RenderStyle::RightBottomJustify
:
458 x
+= maxsize
- length
;
460 case otk::RenderStyle::CenterJustify
:
461 x
+= (maxsize
- length
) / 2;
463 case otk::RenderStyle::LeftTopJustify
:
467 control
->drawString(*s
, *font
, x
, 0,
468 *(_client
->focused() ? style
->textFocusColor() :
469 style
->textUnfocusColor()), t
);
471 XSetWindowBackgroundPixmap(**otk::display
, _label
, s
->pixmap());
472 XClearWindow(**otk::display
, _label
);
473 if (_label_sur
) delete _label_sur
;
478 static void renderButton(int screen
, bool focus
, bool press
, Window win
,
479 otk::Surface
**sur
, int butsize
,
480 const otk::PixmapMask
*mask
)
482 const otk::RenderStyle
*style
= otk::RenderStyle::style(screen
);
483 const otk::RenderControl
*control
= otk::display
->renderControl(screen
);
484 otk::Surface
*s
= new otk::Surface(screen
, otk::Size(butsize
, butsize
));
486 const otk::RenderTexture
*tx
= (focus
?
488 style
->buttonPressFocusBackground() :
489 style
->buttonUnpressFocusBackground()) :
491 style
->buttonPressUnfocusBackground() :
492 style
->buttonUnpressUnfocusBackground()));
493 const otk::RenderColor
*maskcolor
= (focus
?
494 style
->buttonFocusColor() :
495 style
->buttonUnfocusColor());
496 control
->drawBackground(*s
, *tx
);
497 control
->drawMask(*s
, *maskcolor
, *mask
);
499 XSetWindowBackgroundPixmap(**otk::display
, win
, s
->pixmap());
500 XClearWindow(**otk::display
, win
);
501 if (*sur
) delete *sur
;
506 void Frame::renderMax()
508 if (!(_decorations
& Client::Decor_Maximize
)) return;
509 bool press
= _max_press
|| _client
->maxVert() || _client
->maxHorz();
510 renderButton(_client
->screen(), _client
->focused(), press
, _max
,
511 &_max_sur
, geom
.button_size
,
512 otk::RenderStyle::style(_client
->screen())->maximizeMask());
515 void Frame::renderDesk()
517 if (!(_decorations
& Client::Decor_AllDesktops
)) return;
518 bool press
= _desk_press
|| _client
->desktop() == 0xffffffff;
519 renderButton(_client
->screen(), _client
->focused(), press
, _desk
,
520 &_desk_sur
, geom
.button_size
,
521 otk::RenderStyle::style(_client
->screen())->alldesktopsMask());
524 void Frame::renderIconify()
526 if (!(_decorations
& Client::Decor_Iconify
)) return;
527 renderButton(_client
->screen(), _client
->focused(), _iconify_press
, _iconify
,
528 &_iconify_sur
, geom
.button_size
,
529 otk::RenderStyle::style(_client
->screen())->iconifyMask());
532 void Frame::renderClose()
534 if (!(_decorations
& Client::Decor_Close
)) return;
535 renderButton(_client
->screen(), _client
->focused(), _close_press
, _close
,
536 &_close_sur
, geom
.button_size
,
537 otk::RenderStyle::style(_client
->screen())->closeMask());
540 void Frame::renderIcon()
542 if (!(_decorations
& Client::Decor_Icon
)) return;
543 const int screen
= _client
->screen();
544 const otk::RenderControl
*control
= otk::display
->renderControl(screen
);
546 otk::Surface
*s
= new otk::Surface(screen
, otk::Size(geom
.button_size
,
548 otk::pixel32
*dest
= s
->pixelData(), *src
;
549 int w
= _title_sur
->size().width();
551 src
= _title_sur
->pixelData() + w
* (geom
.bevel
+ 1) + geom
.icon_x
;
553 // get the background under the icon button
554 for (int y
= 0; y
< geom
.button_size
; ++y
, src
+= w
- geom
.button_size
)
555 for (int x
= 0; x
< geom
.button_size
; ++x
, ++dest
, ++src
)
557 // draw the icon over it
558 const Icon
*icon
= _client
->icon(otk::Size(geom
.button_size
,
560 control
->drawImage(*s
, icon
->w
, icon
->h
, icon
->data
);
562 XSetWindowBackgroundPixmap(**otk::display
, _icon
, s
->pixmap());
563 XClearWindow(**otk::display
, _icon
);
564 if (_icon_sur
) delete _icon_sur
;
568 void Frame::layoutTitle()
570 // figure out whats being shown, and the width of the label
571 geom
.label_width
= geom
.width
- geom
.bevel
* 2;
572 bool n
, d
, i
, t
, m
,c
;
573 n
= d
= i
= t
= m
= c
= false;
574 for (const char *l
= _layout
.c_str(); *l
; ++l
) {
578 if (!(_decorations
& Client::Decor_Icon
)) break;
580 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
584 if (!(_decorations
& Client::Decor_AllDesktops
)) break;
586 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
590 if (!(_decorations
& Client::Decor_Iconify
)) break;
592 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
600 if (!(_decorations
& Client::Decor_Maximize
)) break;
602 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
606 if (!(_decorations
& Client::Decor_Close
)) break;
608 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
612 if (geom
.label_width
< 1) geom
.label_width
= 1;
614 XResizeWindow(**otk::display
, _label
, geom
.label_width
, geom
.font_height
);
617 _decorations
&= ~Client::Decor_Icon
;
618 XUnmapWindow(**otk::display
, _icon
);
621 _decorations
&= ~Client::Decor_AllDesktops
;
622 XUnmapWindow(**otk::display
, _desk
);
625 _decorations
&= ~Client::Decor_Iconify
;
626 XUnmapWindow(**otk::display
, _iconify
);
629 XUnmapWindow(**otk::display
, _label
);
631 _decorations
&= ~Client::Decor_Maximize
;
632 XUnmapWindow(**otk::display
, _max
);
635 _decorations
&= ~Client::Decor_Close
;
636 XUnmapWindow(**otk::display
, _close
);
640 for (const char *lc
= _layout
.c_str(); *lc
; ++lc
) {
646 XMapWindow(**otk::display
, _icon
);
647 XMoveWindow(**otk::display
, _icon
, x
, geom
.bevel
+ 1);
648 x
+= geom
.button_size
+ geom
.bevel
;
653 XMapWindow(**otk::display
, _desk
);
654 XMoveWindow(**otk::display
, _desk
, x
, geom
.bevel
+ 1);
655 x
+= geom
.button_size
+ geom
.bevel
;
660 XMapWindow(**otk::display
, _iconify
);
661 XMoveWindow(**otk::display
, _iconify
, x
, geom
.bevel
+ 1);
662 x
+= geom
.button_size
+ geom
.bevel
;
667 XMapWindow(**otk::display
, _label
);
668 XMoveWindow(**otk::display
, _label
, x
, geom
.bevel
);
669 x
+= geom
.label_width
+ geom
.bevel
;
674 XMapWindow(**otk::display
, _max
);
675 XMoveWindow(**otk::display
, _max
, x
, geom
.bevel
+ 1);
676 x
+= geom
.button_size
+ geom
.bevel
;
681 XMapWindow(**otk::display
, _close
);
682 XMoveWindow(**otk::display
, _close
, x
, geom
.bevel
+ 1);
683 x
+= geom
.button_size
+ geom
.bevel
;
689 void Frame::adjustPosition()
692 x
= _client
->area().x();
693 y
= _client
->area().y();
695 XMoveWindow(**otk::display
, _frame
, x
, y
);
696 _area
= otk::Rect(otk::Point(x
, y
), _area
.size());
700 void Frame::adjustShape()
703 if (!_client
->shaped()) {
704 // clear the shape on the frame window
705 XShapeCombineMask(**otk::display
, _frame
, ShapeBounding
,
710 // make the frame's shape match the clients
711 XShapeCombineShape(**otk::display
, _frame
, ShapeBounding
,
714 _client
->window(), ShapeBounding
, ShapeSet
);
719 if (_decorations
& Client::Decor_Titlebar
) {
720 xrect
[0].x
= -geom
.bevel
;
721 xrect
[0].y
= -geom
.bevel
;
722 xrect
[0].width
= geom
.width
+ geom
.bwidth
* 2;
723 xrect
[0].height
= geom
.title_height() + geom
.bwidth
* 2;
727 if (_decorations
& Client::Decor_Handle
) {
728 xrect
[1].x
= -geom
.bevel
;
729 xrect
[1].y
= geom
.handle_y
;
730 xrect
[1].width
= geom
.width
+ geom
.bwidth
* 2;
731 xrect
[1].height
= geom
.handle_height
+ geom
.bwidth
* 2;
735 XShapeCombineRectangles(**otk::display
, _frame
,
736 ShapeBounding
, 0, 0, xrect
, num
,
737 ShapeUnion
, Unsorted
);
742 void Frame::adjustState()
748 void Frame::adjustIcon()
753 void Frame::grabClient()
755 // reparent the client to the frame
756 XReparentWindow(**otk::display
, _client
->window(), _plate
, 0, 0);
758 When reparenting the client window, it is usually not mapped yet, since
759 this occurs from a MapRequest. However, in the case where Openbox is
760 starting up, the window is already mapped, so we'll see unmap events for
761 it. There are 2 unmap events generated that we see, one with the 'event'
762 member set the root window, and one set to the client, but both get handled
763 and need to be ignored.
765 if (openbox
->state() == Openbox::State_Starting
)
766 _client
->ignore_unmaps
+= 2;
768 // select the event mask on the client's parent (to receive config/map req's)
769 XSelectInput(**otk::display
, _plate
, SubstructureRedirectMask
);
771 // map the client so it maps when the frame does
772 XMapWindow(**otk::display
, _client
->window());
779 void Frame::releaseClient()
783 // check if the app has already reparented its window away
784 if (XCheckTypedWindowEvent(**otk::display
, _client
->window(),
785 ReparentNotify
, &ev
)) {
786 XPutBackEvent(**otk::display
, &ev
);
787 // re-map the window since the unmanaging process unmaps it
788 XMapWindow(**otk::display
, _client
->window());
790 // according to the ICCCM - if the client doesn't reparent itself, then we
791 // will reparent the window to root for them
792 XReparentWindow(**otk::display
, _client
->window(),
793 otk::display
->screenInfo(_client
->screen())->rootWindow(),
794 _client
->area().x(), _client
->area().y());
799 void Frame::clientGravity(int &x
, int &y
)
802 switch (_client
->gravity()) {
804 case NorthWestGravity
:
805 case SouthWestGravity
:
812 x
-= (_size
.left
+ _size
.right
) / 2;
815 case NorthEastGravity
:
816 case SouthEastGravity
:
818 x
-= _size
.left
+ _size
.right
;
828 switch (_client
->gravity()) {
830 case NorthWestGravity
:
831 case NorthEastGravity
:
838 y
-= (_size
.top
+ _size
.bottom
) / 2;
841 case SouthWestGravity
:
842 case SouthEastGravity
:
844 y
-= _size
.top
+ _size
.bottom
;
855 void Frame::frameGravity(int &x
, int &y
)
858 switch (_client
->gravity()) {
860 case NorthWestGravity
:
862 case SouthWestGravity
:
867 x
+= (_size
.left
+ _size
.right
) / 2;
869 case NorthEastGravity
:
871 case SouthEastGravity
:
872 x
+= _size
.left
+ _size
.right
;
881 switch (_client
->gravity()) {
883 case NorthWestGravity
:
885 case SouthWestGravity
:
890 y
+= (_size
.top
+ _size
.bottom
) / 2;
892 case NorthEastGravity
:
894 case SouthEastGravity
:
895 y
+= _size
.top
+ _size
.bottom
;