1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
7 #include <X11/extensions/shape.h>
14 #include "otk/display.hh"
15 #include "otk/surface.hh"
22 const long Frame::event_mask
;
24 Window
createWindow(const otk::ScreenInfo
*info
, Window parent
,
25 unsigned long mask
, XSetWindowAttributes
*attrib
)
27 return XCreateWindow(**otk::display
, parent
, 0, 0, 1, 1, 0,
28 info
->depth(), InputOutput
, info
->visual(),
33 Frame::Frame(Client
*client
)
59 _iconify_press(false),
66 XSetWindowAttributes attrib
;
68 const otk::ScreenInfo
*info
= otk::display
->screenInfo(client
->screen());
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
);
77 _plate
= createWindow(info
, _frame
, mask
, &attrib
);
79 attrib
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
|
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
);
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
);
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
);
101 applyStyle(*otk::RenderStyle::style(_client
->screen()));
104 python_get_string("titlebar_layout", &_layout
);
106 // register all of the windows with the event dispatcher
107 Window
*w
= allWindows();
108 for (unsigned int i
= 0; w
[i
]; ++i
)
109 openbox
->registerHandler(w
[i
], this);
115 // unregister all of the windows with the event dispatcher
116 Window
*w
= allWindows();
117 for (unsigned int i
= 0; w
[i
]; ++i
)
118 openbox
->clearHandler(w
[i
]);
121 XDestroyWindow(**otk::display
, _rgrip
);
122 XDestroyWindow(**otk::display
, _lgrip
);
123 XDestroyWindow(**otk::display
, _handle
);
124 XDestroyWindow(**otk::display
, _max
);
125 XDestroyWindow(**otk::display
, _icon
);
126 XDestroyWindow(**otk::display
, _iconify
);
127 XDestroyWindow(**otk::display
, _desk
);
128 XDestroyWindow(**otk::display
, _close
);
129 XDestroyWindow(**otk::display
, _label
);
130 XDestroyWindow(**otk::display
, _title
);
131 XDestroyWindow(**otk::display
, _frame
);
133 if (_frame_sur
) delete _frame_sur
;
134 if (_title_sur
) delete _title_sur
;
135 if (_label_sur
) delete _label_sur
;
136 if (_handle_sur
) delete _handle_sur
;
137 if (_grip_sur
) delete _grip_sur
;
138 if (_max_sur
) delete _max_sur
;
139 if (_desk_sur
) delete _desk_sur
;
140 if (_iconify_sur
) delete _iconify_sur
;
141 if (_icon_sur
) delete _icon_sur
;
142 if (_close_sur
) delete _close_sur
;
149 XMapWindow(**otk::display
, _frame
);
157 XUnmapWindow(**otk::display
, _frame
);
161 void Frame::buttonPressHandler(const XButtonEvent
&e
)
163 if (_press_button
) return;
164 _press_button
= e
.button
;
166 if (e
.window
== _max
) {
170 if (e
.window
== _close
) {
174 if (e
.window
== _desk
) {
178 if (e
.window
== _iconify
) {
179 _iconify_press
= true;
182 if (e
.window
== _icon
) {
188 void Frame::buttonReleaseHandler(const XButtonEvent
&e
)
190 if (e
.button
!= _press_button
) return;
193 if (e
.window
== _max
) {
197 if (e
.window
== _close
) {
198 _close_press
= false;
201 if (e
.window
== _desk
) {
205 if (e
.window
== _iconify
) {
206 _iconify_press
= false;
209 if (e
.window
== _icon
) {
215 MouseContext::MC
Frame::mouseContext(Window win
) const
217 if (win
== _frame
) return MouseContext::Frame
;
219 win
== _label
) return MouseContext::Titlebar
;
220 if (win
== _handle
) return MouseContext::Handle
;
221 if (win
== _plate
) return MouseContext::Window
;
223 win
== _rgrip
) return MouseContext::Grip
;
224 if (win
== _max
) return MouseContext::MaximizeButton
;
225 if (win
== _close
) return MouseContext::CloseButton
;
226 if (win
== _desk
) return MouseContext::AllDesktopsButton
;
227 if (win
== _iconify
)return MouseContext::IconifyButton
;
228 if (win
== _icon
) return MouseContext::IconButton
;
229 return (MouseContext::MC
) -1;
232 Window
*Frame::allWindows() const
234 Window
*w
= new Window
[12 + 1];
252 void Frame::applyStyle(const otk::RenderStyle
&style
)
254 // set static border colors
255 XSetWindowBorder(**otk::display
, _frame
, style
.frameBorderColor()->pixel());
256 XSetWindowBorder(**otk::display
, _title
, style
.frameBorderColor()->pixel());
257 XSetWindowBorder(**otk::display
, _handle
, style
.frameBorderColor()->pixel());
258 XSetWindowBorder(**otk::display
, _lgrip
, style
.frameBorderColor()->pixel());
259 XSetWindowBorder(**otk::display
, _rgrip
, style
.frameBorderColor()->pixel());
261 // size all the fixed-size elements
262 geom
.font_height
= style
.labelFont()->height();
263 if (geom
.font_height
< 1) geom
.font_height
= 1;
264 geom
.button_size
= geom
.font_height
- 2;
265 if (geom
.button_size
< 1) geom
.button_size
= 1;
266 geom
.handle_height
= style
.handleWidth();
267 if (geom
.handle_height
< 1) geom
.handle_height
= 1;
268 geom
.bevel
= style
.bevelWidth();
270 XResizeWindow(**otk::display
, _lgrip
, geom
.grip_width(), geom
.handle_height
);
271 XResizeWindow(**otk::display
, _rgrip
, geom
.grip_width(), geom
.handle_height
);
273 XResizeWindow(**otk::display
, _max
, geom
.button_size
, geom
.button_size
);
274 XResizeWindow(**otk::display
, _close
, geom
.button_size
, geom
.button_size
);
275 XResizeWindow(**otk::display
, _desk
, geom
.button_size
, geom
.button_size
);
276 XResizeWindow(**otk::display
, _iconify
, geom
.button_size
, geom
.button_size
);
277 XResizeWindow(**otk::display
, _icon
, geom
.button_size
, geom
.button_size
);
280 void Frame::styleChanged(const otk::RenderStyle
&style
)
284 // size/position everything
289 void Frame::adjustFocus()
291 // XXX optimizations later...
295 void Frame::adjustTitle()
297 // XXX optimizations later...
301 static void render(int screen
, const otk::Size
&size
, Window win
,
302 otk::Surface
**surface
,
303 const otk::RenderTexture
&texture
, bool freedata
=true)
305 otk::Surface
*s
= new otk::Surface(screen
, size
);
306 if (texture
.parentRelative())
307 XSetWindowBackgroundPixmap(**otk::display
, win
, ParentRelative
);
309 otk::display
->renderControl(screen
)->drawBackground(*s
, texture
);
310 XSetWindowBackgroundPixmap(**otk::display
, win
, s
->pixmap());
312 XClearWindow(**otk::display
, win
);
313 if (*surface
) delete *surface
;
314 if (freedata
) s
->freePixelData();
318 void Frame::adjustSize()
320 _decorations
= _client
->decorations();
321 const otk::RenderStyle
*style
= otk::RenderStyle::style(_client
->screen());
323 if (_decorations
& Client::Decor_Border
) {
324 geom
.bwidth
= style
->frameBorderWidth();
325 geom
.cbwidth
= style
->clientBorderWidth();
327 geom
.bwidth
= geom
.cbwidth
= 0;
329 _innersize
.left
= _innersize
.top
= _innersize
.bottom
= _innersize
.right
=
331 geom
.width
= _client
->area().width() + geom
.cbwidth
* 2;
332 assert(geom
.width
> 0);
335 XSetWindowBorderWidth(**otk::display
, _plate
, geom
.cbwidth
);
336 XSetWindowBorderWidth(**otk::display
, _frame
, geom
.bwidth
);
337 XSetWindowBorderWidth(**otk::display
, _title
, geom
.bwidth
);
338 XSetWindowBorderWidth(**otk::display
, _handle
, geom
.bwidth
);
339 XSetWindowBorderWidth(**otk::display
, _lgrip
, geom
.bwidth
);
340 XSetWindowBorderWidth(**otk::display
, _rgrip
, geom
.bwidth
);
342 // position/size and map/unmap all the windows
344 if (_decorations
& Client::Decor_Titlebar
) {
345 XMoveResizeWindow(**otk::display
, _title
, -geom
.bwidth
, -geom
.bwidth
,
346 geom
.width
, geom
.title_height());
347 _innersize
.top
+= geom
.title_height() + geom
.bwidth
;
348 XMapWindow(**otk::display
, _title
);
350 // layout the title bar elements
353 XUnmapWindow(**otk::display
, _title
);
354 // make all the titlebar stuff not render
355 _decorations
&= ~(Client::Decor_Icon
| Client::Decor_Iconify
|
356 Client::Decor_Maximize
| Client::Decor_Close
|
357 Client::Decor_AllDesktops
);
360 if (_decorations
& Client::Decor_Handle
) {
361 geom
.handle_y
= _innersize
.top
+ _client
->area().height() + geom
.cbwidth
;
362 XMoveResizeWindow(**otk::display
, _handle
, -geom
.bwidth
, geom
.handle_y
,
363 geom
.width
, geom
.handle_height
);
364 XMoveWindow(**otk::display
, _lgrip
, -geom
.bwidth
, -geom
.bwidth
);
365 XMoveWindow(**otk::display
, _rgrip
,
366 -geom
.bwidth
+ geom
.width
- geom
.grip_width(),
368 _innersize
.bottom
+= geom
.handle_height
+ geom
.bwidth
;
369 XMapWindow(**otk::display
, _handle
);
371 XUnmapWindow(**otk::display
, _handle
);
373 XResizeWindow(**otk::display
, _frame
, geom
.width
,
374 (_client
->shaded() ? geom
.title_height() :
375 _innersize
.top
+ _innersize
.bottom
+
376 _client
->area().height()));
378 // do this in two steps because clients whose gravity is set to
379 // 'Static' don't end up getting moved at all with an XMoveResizeWindow
380 XMoveWindow(**otk::display
, _plate
, _innersize
.left
- geom
.cbwidth
,
381 _innersize
.top
- geom
.cbwidth
);
382 XResizeWindow(**otk::display
, _plate
, _client
->area().width(),
383 _client
->area().height());
385 _size
.left
= _innersize
.left
+ geom
.bwidth
;
386 _size
.right
= _innersize
.right
+ geom
.bwidth
;
387 _size
.top
= _innersize
.top
+ geom
.bwidth
;
388 _size
.bottom
= _innersize
.bottom
+ geom
.bwidth
;
390 _area
= otk::Rect(_area
.position(), otk::Size(_client
->area().width() +
391 _size
.left
+ _size
.right
,
392 _client
->area().height() +
393 _size
.top
+ _size
.bottom
));
395 // render all the elements
396 int screen
= _client
->screen();
397 bool focus
= _client
->focused();
398 if (_decorations
& Client::Decor_Titlebar
) {
399 render(screen
, otk::Size(geom
.width
, geom
.title_height()), _title
,
400 &_title_sur
, *(focus
? style
->titlebarFocusBackground() :
401 style
->titlebarUnfocusBackground()), false);
411 if (_decorations
& Client::Decor_Handle
) {
412 render(screen
, otk::Size(geom
.width
, geom
.handle_height
), _handle
,
413 &_handle_sur
, *(focus
? style
->handleFocusBackground() :
414 style
->handleUnfocusBackground()));
415 render(screen
, otk::Size(geom
.grip_width(), geom
.handle_height
), _lgrip
,
416 &_grip_sur
, *(focus
? style
->gripFocusBackground() :
417 style
->gripUnfocusBackground()));
418 if ((focus
? style
->gripFocusBackground() :
419 style
->gripUnfocusBackground())->parentRelative())
420 XSetWindowBackgroundPixmap(**otk::display
, _rgrip
, ParentRelative
);
422 XSetWindowBackgroundPixmap(**otk::display
, _rgrip
, _grip_sur
->pixmap());
424 XClearWindow(**otk::display
, _rgrip
);
427 XSetWindowBorder(**otk::display
, _plate
,
428 focus
? style
->clientBorderFocusColor()->pixel() :
429 style
->clientBorderUnfocusColor()->pixel());
434 void Frame::renderLabel()
436 const otk::RenderStyle
*style
= otk::RenderStyle::style(_client
->screen());
437 const otk::RenderControl
*control
=
438 otk::display
->renderControl(_client
->screen());
439 const otk::Font
*font
= style
->labelFont();
441 otk::Surface
*s
= new otk::Surface(_client
->screen(),
442 otk::Size(geom
.label_width
,
443 geom
.label_height()));
444 const otk::RenderTexture
*tx
= (_client
->focused() ?
445 style
->labelFocusBackground() :
446 style
->labelUnfocusBackground());
447 if (tx
->parentRelative()) {
448 otk::pixel32
*dest
= s
->pixelData(), *src
;
449 int w
= _title_sur
->size().width();
451 src
= _title_sur
->pixelData() + w
* geom
.bevel
+ geom
.title_x
;
453 // get the background under the label
454 int xd
= s
->size().width();
455 int yd
= s
->size().height();
456 for (int y
= 0; y
< yd
; ++y
, src
+= w
- xd
)
457 for (int x
= 0; x
< xd
; ++x
, ++dest
, ++src
)
459 control
->drawImage(*s
, 0, 0, 0); // no image but draw the new background
461 control
->drawBackground(*s
, *tx
);
463 otk::ustring t
= _client
->title(); // the actual text to draw
464 int x
= geom
.bevel
; // x coord for the text
466 if (x
* 2 < geom
.label_width
) {
467 // find a string that will fit inside the area for text
468 otk::ustring::size_type text_len
= t
.size();
470 int maxsize
= geom
.label_width
- geom
.bevel
* 2;
474 length
= font
->measureString(t
);// this returns an unsigned, so check < 0
475 if (length
< 0) length
= maxsize
;// if the string's that long just adjust
476 } while (length
> maxsize
&& text_len
-- > 0);
479 switch (style
->labelTextJustify()) {
480 case otk::RenderStyle::RightBottomJustify
:
481 x
+= maxsize
- length
;
483 case otk::RenderStyle::CenterJustify
:
484 x
+= (maxsize
- length
) / 2;
486 case otk::RenderStyle::LeftTopJustify
:
491 control
->drawString(*s
, *font
, x
, 0,
492 *(_client
->focused() ? style
->textFocusColor() :
493 style
->textUnfocusColor()), t
);
496 XSetWindowBackgroundPixmap(**otk::display
, _label
, s
->pixmap());
497 XClearWindow(**otk::display
, _label
);
498 if (_label_sur
) delete _label_sur
;
503 static void renderButton(int screen
, bool focus
, bool press
, Window win
,
504 otk::Surface
**sur
, int butsize
,
505 const otk::PixmapMask
*mask
, int xoffset
, int yoffset
,
506 otk::Surface
*bgsurface
)
508 const otk::RenderStyle
*style
= otk::RenderStyle::style(screen
);
509 const otk::RenderControl
*control
= otk::display
->renderControl(screen
);
510 otk::Surface
*s
= new otk::Surface(screen
, otk::Size(butsize
, butsize
));
512 const otk::RenderTexture
*tx
= (focus
?
514 style
->buttonPressFocusBackground() :
515 style
->buttonUnpressFocusBackground()) :
517 style
->buttonPressUnfocusBackground() :
518 style
->buttonUnpressUnfocusBackground()));
519 const otk::RenderColor
*maskcolor
= (focus
?
520 style
->buttonFocusColor() :
521 style
->buttonUnfocusColor());
522 if (tx
->parentRelative()) {
523 otk::pixel32
*dest
= s
->pixelData(), *src
;
524 int w
= bgsurface
->size().width();
526 src
= bgsurface
->pixelData() + w
* yoffset
+ xoffset
;
528 // get the background under the button
529 for (int y
= 0; y
< butsize
; ++y
, src
+= w
- butsize
)
530 for (int x
= 0; x
< butsize
; ++x
, ++dest
, ++src
)
532 control
->drawImage(*s
, 0, 0, 0); // no image but draw the new background
534 control
->drawBackground(*s
, *tx
);
535 control
->drawMask(*s
, *maskcolor
, *mask
);
537 XSetWindowBackgroundPixmap(**otk::display
, win
, s
->pixmap());
538 XClearWindow(**otk::display
, win
);
539 if (*sur
) delete *sur
;
544 void Frame::renderMax()
546 if (!(_decorations
& Client::Decor_Maximize
)) return;
547 bool press
= _max_press
|| _client
->maxVert() || _client
->maxHorz();
548 renderButton(_client
->screen(), _client
->focused(), press
, _max
,
549 &_max_sur
, geom
.button_size
,
550 otk::RenderStyle::style(_client
->screen())->maximizeMask(),
551 geom
.max_x
, (geom
.bevel
+ 1), _title_sur
);
554 void Frame::renderDesk()
556 if (!(_decorations
& Client::Decor_AllDesktops
)) return;
557 bool press
= _desk_press
|| _client
->desktop() == 0xffffffff;
558 renderButton(_client
->screen(), _client
->focused(), press
, _desk
,
559 &_desk_sur
, geom
.button_size
,
560 otk::RenderStyle::style(_client
->screen())->alldesktopsMask(),
561 geom
.desktop_x
, (geom
.bevel
+ 1), _title_sur
);
564 void Frame::renderIconify()
566 if (!(_decorations
& Client::Decor_Iconify
)) return;
567 renderButton(_client
->screen(), _client
->focused(), _iconify_press
, _iconify
,
568 &_iconify_sur
, geom
.button_size
,
569 otk::RenderStyle::style(_client
->screen())->iconifyMask(),
570 geom
.iconify_x
, (geom
.bevel
+ 1), _title_sur
);
573 void Frame::renderClose()
575 if (!(_decorations
& Client::Decor_Close
)) return;
576 renderButton(_client
->screen(), _client
->focused(), _close_press
, _close
,
577 &_close_sur
, geom
.button_size
,
578 otk::RenderStyle::style(_client
->screen())->closeMask(),
579 geom
.close_x
, (geom
.bevel
+ 1), _title_sur
);
582 void Frame::renderIcon()
584 if (!(_decorations
& Client::Decor_Icon
)) return;
585 const int screen
= _client
->screen();
586 const otk::RenderControl
*control
= otk::display
->renderControl(screen
);
588 otk::Surface
*s
= new otk::Surface(screen
, otk::Size(geom
.button_size
,
590 otk::pixel32
*dest
= s
->pixelData(), *src
;
591 int w
= _title_sur
->size().width();
593 src
= _title_sur
->pixelData() + w
* (geom
.bevel
+ 1) + geom
.icon_x
;
595 // get the background under the icon button
596 for (int y
= 0; y
< geom
.button_size
; ++y
, src
+= w
- geom
.button_size
)
597 for (int x
= 0; x
< geom
.button_size
; ++x
, ++dest
, ++src
)
599 // draw the icon over it
600 const Icon
*icon
= _client
->icon(otk::Size(geom
.button_size
,
602 control
->drawImage(*s
, icon
->w
, icon
->h
, icon
->data
);
604 Pixmap p
= _client
->pixmapIcon(), m
= _client
->pixmapIconMask();
606 control
->drawImage(*s
, p
, m
);
609 XSetWindowBackgroundPixmap(**otk::display
, _icon
, s
->pixmap());
610 XClearWindow(**otk::display
, _icon
);
611 if (_icon_sur
) delete _icon_sur
;
615 void Frame::layoutTitle()
617 // figure out whats being shown, and the width of the label
618 geom
.label_width
= geom
.width
- geom
.bevel
* 2;
619 bool n
, d
, i
, t
, m
,c
;
620 n
= d
= i
= t
= m
= c
= false;
621 for (const char *l
= _layout
.c_str(); *l
; ++l
) {
625 if (!(_decorations
& Client::Decor_Icon
)) break;
627 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
631 if (!(_decorations
& Client::Decor_AllDesktops
)) break;
633 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
637 if (!(_decorations
& Client::Decor_Iconify
)) break;
639 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
647 if (!(_decorations
& Client::Decor_Maximize
)) break;
649 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
653 if (!(_decorations
& Client::Decor_Close
)) break;
655 geom
.label_width
-= geom
.button_size
+ geom
.bevel
;
659 if (geom
.label_width
< 1) geom
.label_width
= 1;
661 XResizeWindow(**otk::display
, _label
, geom
.label_width
, geom
.font_height
);
664 _decorations
&= ~Client::Decor_Icon
;
665 XUnmapWindow(**otk::display
, _icon
);
668 _decorations
&= ~Client::Decor_AllDesktops
;
669 XUnmapWindow(**otk::display
, _desk
);
672 _decorations
&= ~Client::Decor_Iconify
;
673 XUnmapWindow(**otk::display
, _iconify
);
676 XUnmapWindow(**otk::display
, _label
);
678 _decorations
&= ~Client::Decor_Maximize
;
679 XUnmapWindow(**otk::display
, _max
);
682 _decorations
&= ~Client::Decor_Close
;
683 XUnmapWindow(**otk::display
, _close
);
687 for (const char *lc
= _layout
.c_str(); *lc
; ++lc
) {
693 XMapWindow(**otk::display
, _icon
);
694 XMoveWindow(**otk::display
, _icon
, x
, geom
.bevel
+ 1);
695 x
+= geom
.button_size
+ geom
.bevel
;
701 XMapWindow(**otk::display
, _desk
);
702 XMoveWindow(**otk::display
, _desk
, x
, geom
.bevel
+ 1);
703 x
+= geom
.button_size
+ geom
.bevel
;
709 XMapWindow(**otk::display
, _iconify
);
710 XMoveWindow(**otk::display
, _iconify
, x
, geom
.bevel
+ 1);
711 x
+= geom
.button_size
+ geom
.bevel
;
717 XMapWindow(**otk::display
, _label
);
718 XMoveWindow(**otk::display
, _label
, x
, geom
.bevel
);
719 x
+= geom
.label_width
+ geom
.bevel
;
725 XMapWindow(**otk::display
, _max
);
726 XMoveWindow(**otk::display
, _max
, x
, geom
.bevel
+ 1);
727 x
+= geom
.button_size
+ geom
.bevel
;
733 XMapWindow(**otk::display
, _close
);
734 XMoveWindow(**otk::display
, _close
, x
, geom
.bevel
+ 1);
735 x
+= geom
.button_size
+ geom
.bevel
;
741 void Frame::adjustPosition()
744 x
= _client
->area().x();
745 y
= _client
->area().y();
747 XMoveWindow(**otk::display
, _frame
, x
, y
);
748 _area
= otk::Rect(otk::Point(x
, y
), _area
.size());
752 void Frame::adjustShape()
755 if (!_client
->shaped()) {
756 // clear the shape on the frame window
757 XShapeCombineMask(**otk::display
, _frame
, ShapeBounding
,
762 // make the frame's shape match the clients
763 XShapeCombineShape(**otk::display
, _frame
, ShapeBounding
,
766 _client
->window(), ShapeBounding
, ShapeSet
);
771 if (_decorations
& Client::Decor_Titlebar
) {
772 xrect
[0].x
= -geom
.bevel
;
773 xrect
[0].y
= -geom
.bevel
;
774 xrect
[0].width
= geom
.width
+ geom
.bwidth
* 2;
775 xrect
[0].height
= geom
.title_height() + geom
.bwidth
* 2;
779 if (_decorations
& Client::Decor_Handle
) {
780 xrect
[1].x
= -geom
.bevel
;
781 xrect
[1].y
= geom
.handle_y
;
782 xrect
[1].width
= geom
.width
+ geom
.bwidth
* 2;
783 xrect
[1].height
= geom
.handle_height
+ geom
.bwidth
* 2;
787 XShapeCombineRectangles(**otk::display
, _frame
,
788 ShapeBounding
, 0, 0, xrect
, num
,
789 ShapeUnion
, Unsorted
);
794 void Frame::adjustState()
800 void Frame::adjustIcon()
805 void Frame::grabClient()
807 // reparent the client to the frame
808 XReparentWindow(**otk::display
, _client
->window(), _plate
, 0, 0);
810 When reparenting the client window, it is usually not mapped yet, since
811 this occurs from a MapRequest. However, in the case where Openbox is
812 starting up, the window is already mapped, so we'll see unmap events for
813 it. There are 2 unmap events generated that we see, one with the 'event'
814 member set the root window, and one set to the client, but both get handled
815 and need to be ignored.
817 if (openbox
->state() == Openbox::State_Starting
)
818 _client
->ignore_unmaps
+= 2;
820 // select the event mask on the client's parent (to receive config/map req's)
821 // the ButtonPress is to catch clicks on the client border
822 XSelectInput(**otk::display
, _plate
, (SubstructureRedirectMask
|
825 // map the client so it maps when the frame does
826 XMapWindow(**otk::display
, _client
->window());
833 void Frame::releaseClient()
837 // check if the app has already reparented its window away
838 if (XCheckTypedWindowEvent(**otk::display
, _client
->window(),
839 ReparentNotify
, &ev
)) {
840 XPutBackEvent(**otk::display
, &ev
);
841 // re-map the window since the unmanaging process unmaps it
842 XMapWindow(**otk::display
, _client
->window());
844 // according to the ICCCM - if the client doesn't reparent itself, then we
845 // will reparent the window to root for them
846 XReparentWindow(**otk::display
, _client
->window(),
847 otk::display
->screenInfo(_client
->screen())->rootWindow(),
848 _client
->area().x(), _client
->area().y());
853 void Frame::clientGravity(int &x
, int &y
)
856 switch (_client
->gravity()) {
858 case NorthWestGravity
:
859 case SouthWestGravity
:
866 x
-= (_size
.left
+ _size
.right
) / 2;
869 case NorthEastGravity
:
870 case SouthEastGravity
:
872 x
-= _size
.left
+ _size
.right
;
882 switch (_client
->gravity()) {
884 case NorthWestGravity
:
885 case NorthEastGravity
:
892 y
-= (_size
.top
+ _size
.bottom
) / 2;
895 case SouthWestGravity
:
896 case SouthEastGravity
:
898 y
-= _size
.top
+ _size
.bottom
;
909 void Frame::frameGravity(int &x
, int &y
)
912 switch (_client
->gravity()) {
914 case NorthWestGravity
:
916 case SouthWestGravity
:
921 x
+= (_size
.left
+ _size
.right
) / 2;
923 case NorthEastGravity
:
925 case SouthEastGravity
:
926 x
+= _size
.left
+ _size
.right
;
935 switch (_client
->gravity()) {
937 case NorthWestGravity
:
939 case SouthWestGravity
:
944 y
+= (_size
.top
+ _size
.bottom
) / 2;
946 case NorthEastGravity
:
948 case SouthEastGravity
:
949 y
+= _size
.top
+ _size
.bottom
;