1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
4 # include "../config.h"
11 #include "otk/display.hh"
12 #include "otk/property.hh"
16 #include <X11/Xutil.h>
21 #define _(str) gettext(str)
26 OBClient::OBClient(int screen
, Window window
)
27 : otk::OtkEventHandler(),
28 OBWidget(OBWidget::Type_Client
),
29 frame(0), _screen(screen
), _window(window
)
36 // update EVERYTHING the first time!!
38 // the state is kinda assumed to be normal. is this right? XXX
39 _wmstate
= NormalState
; _iconic
= false;
40 // no default decors or functions, each has to be enabled
41 _decorations
= _functions
= 0;
49 // set the decorations and functions
52 // normal windows retain all of the possible decorations and
54 _decorations
= Decor_Titlebar
| Decor_Handle
| Decor_Border
|
55 Decor_Iconify
| Decor_Maximize
;
56 _functions
= Func_Resize
| Func_Move
| Func_Iconify
| Func_Maximize
;
59 // dialogs cannot be maximized
60 _decorations
&= ~Decor_Maximize
;
61 _functions
&= ~Func_Maximize
;
67 // these windows get less functionality
68 _decorations
&= ~(Decor_Iconify
| Decor_Handle
);
69 _functions
&= ~(Func_Iconify
| Func_Resize
);
75 // none of these windows are manipulated by the window manager
81 getMwmHints(); // this fucks (in good ways) with the decors and functions
88 // XXX: updateTransientFor();
99 const otk::OBProperty
*property
= Openbox::instance
->property();
101 // these values should not be persisted across a window unmapping/mapping
102 property
->erase(_window
, otk::OBProperty::net_wm_desktop
);
103 property
->erase(_window
, otk::OBProperty::net_wm_state
);
107 void OBClient::getDesktop()
109 const otk::OBProperty
*property
= Openbox::instance
->property();
111 // defaults to the current desktop
112 _desktop
= 0; // XXX: change this to the current desktop!
114 property
->get(_window
, otk::OBProperty::net_wm_desktop
,
115 otk::OBProperty::Atom_Cardinal
,
120 void OBClient::getType()
122 const otk::OBProperty
*property
= Openbox::instance
->property();
124 _type
= (WindowType
) -1;
127 unsigned long num
= (unsigned) -1;
128 if (property
->get(_window
, otk::OBProperty::net_wm_window_type
,
129 otk::OBProperty::Atom_Atom
,
131 // use the first value that we know about in the array
132 for (unsigned long i
= 0; i
< num
; ++i
) {
134 property
->atom(otk::OBProperty::net_wm_window_type_desktop
))
135 _type
= Type_Desktop
;
137 property
->atom(otk::OBProperty::net_wm_window_type_dock
))
140 property
->atom(otk::OBProperty::net_wm_window_type_toolbar
))
141 _type
= Type_Toolbar
;
143 property
->atom(otk::OBProperty::net_wm_window_type_menu
))
146 property
->atom(otk::OBProperty::net_wm_window_type_utility
))
147 _type
= Type_Utility
;
149 property
->atom(otk::OBProperty::net_wm_window_type_splash
))
152 property
->atom(otk::OBProperty::net_wm_window_type_dialog
))
155 property
->atom(otk::OBProperty::net_wm_window_type_normal
))
157 // else if (val[i] ==
158 // property->atom(otk::OBProperty::kde_net_wm_window_type_override))
159 // mwm_decorations = 0; // prevent this window from getting any decor
160 // XXX: make this work again
165 if (_type
== (WindowType
) -1) {
167 * the window type hint was not set, which means we either classify ourself
168 * as a normal window or a dialog, depending on if we are a transient.
170 // XXX: make this code work!
172 // _type = Type_Dialog;
179 void OBClient::getMwmHints()
181 const otk::OBProperty
*property
= Openbox::instance
->property();
186 num
= MwmHints::elements
;
187 if (!property
->get(_window
, otk::OBProperty::motif_wm_hints
,
188 otk::OBProperty::motif_wm_hints
, &num
,
189 (unsigned long **)&hints
))
192 if (num
< MwmHints::elements
) {
197 // retrieved the hints
198 // Mwm Hints are applied subtractively to what has already been chosen for
199 // decor and functionality
201 if (hints
->flags
& MwmFlag_Decorations
) {
202 if (! (hints
->decorations
& MwmDecor_All
)) {
203 if (! (hints
->decorations
& MwmDecor_Border
))
204 _decorations
&= ~Decor_Border
;
205 if (! (hints
->decorations
& MwmDecor_Handle
))
206 _decorations
&= ~Decor_Handle
;
207 if (! (hints
->decorations
& MwmDecor_Title
))
208 _decorations
&= ~Decor_Titlebar
;
209 if (! (hints
->decorations
& MwmDecor_Iconify
))
210 _decorations
&= ~Decor_Iconify
;
211 if (! (hints
->decorations
& MwmDecor_Maximize
))
212 _decorations
&= ~Decor_Maximize
;
216 if (hints
->flags
& MwmFlag_Functions
) {
217 if (! (hints
->functions
& MwmFunc_All
)) {
218 if (! (hints
->functions
& MwmFunc_Resize
))
219 _functions
&= ~Func_Resize
;
220 if (! (hints
->functions
& MwmFunc_Move
))
221 _functions
&= ~Func_Move
;
222 if (! (hints
->functions
& MwmFunc_Iconify
))
223 _functions
&= ~Func_Iconify
;
224 if (! (hints
->functions
& MwmFunc_Maximize
))
225 _functions
&= ~Func_Maximize
;
226 //if (! (hints->functions & MwmFunc_Close))
227 // _functions &= ~Func_Close;
234 void OBClient::getArea()
236 XWindowAttributes wattrib
;
239 ret
= XGetWindowAttributes(otk::OBDisplay::display
, _window
, &wattrib
);
240 assert(ret
!= BadWindow
);
242 _area
.setRect(wattrib
.x
, wattrib
.y
, wattrib
.width
, wattrib
.height
);
243 _border_width
= wattrib
.border_width
;
247 void OBClient::getState()
249 const otk::OBProperty
*property
= Openbox::instance
->property();
251 _modal
= _shaded
= _max_horz
= _max_vert
= _fullscreen
= _above
= _below
=
254 unsigned long *state
;
255 unsigned long num
= (unsigned) -1;
257 if (property
->get(_window
, otk::OBProperty::net_wm_state
,
258 otk::OBProperty::Atom_Atom
, &num
, &state
)) {
259 for (unsigned long i
= 0; i
< num
; ++i
) {
260 if (state
[i
] == property
->atom(otk::OBProperty::net_wm_state_modal
))
263 property
->atom(otk::OBProperty::net_wm_state_shaded
))
266 property
->atom(otk::OBProperty::net_wm_state_fullscreen
))
269 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
))
272 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
))
275 property
->atom(otk::OBProperty::net_wm_state_above
))
278 property
->atom(otk::OBProperty::net_wm_state_below
))
287 void OBClient::getShaped()
291 if (otk::OBDisplay::shape()) {
296 XShapeSelectInput(otk::OBDisplay::display
, _window
, ShapeNotifyMask
);
298 XShapeQueryExtents(otk::OBDisplay::display
, _window
, &s
, &foo
,
299 &foo
, &ufoo
, &ufoo
, &foo
, &foo
, &foo
, &ufoo
, &ufoo
);
306 void OBClient::calcLayer() {
307 if (_iconic
) _layer
= OBScreen::Layer_Icon
;
308 else if (_type
== Type_Desktop
) _layer
= OBScreen::Layer_Desktop
;
309 else if (_type
== Type_Dock
) _layer
= OBScreen::Layer_Top
;
310 else if (_fullscreen
) _layer
= OBScreen::Layer_Fullscreen
;
311 else if (_above
) _layer
= OBScreen::Layer_Above
;
312 else if (_below
) _layer
= OBScreen::Layer_Below
;
313 else _layer
= OBScreen::Layer_Normal
;
317 void OBClient::updateProtocols()
319 const otk::OBProperty
*property
= Openbox::instance
->property();
324 _focus_notify
= false;
325 _decorations
&= ~Decor_Close
;
326 _functions
&= ~Func_Close
;
328 if (XGetWMProtocols(otk::OBDisplay::display
, _window
, &proto
, &num_return
)) {
329 for (int i
= 0; i
< num_return
; ++i
) {
330 if (proto
[i
] == property
->atom(otk::OBProperty::wm_delete_window
)) {
331 _decorations
|= Decor_Close
;
332 _functions
|= Func_Close
;
333 // XXX: update the decor?
334 } else if (proto
[i
] == property
->atom(otk::OBProperty::wm_take_focus
))
335 // if this protocol is requested, then the window will be notified
336 // by the window manager whenever it receives focus
337 _focus_notify
= true;
344 void OBClient::updateNormalHints()
348 int oldgravity
= _gravity
;
351 _gravity
= NorthWestGravity
;
352 _size_inc
.setPoint(1, 1);
353 _base_size
.setPoint(0, 0);
354 _min_size
.setPoint(0, 0);
355 _max_size
.setPoint(INT_MAX
, INT_MAX
);
357 // XXX: might want to cancel any interactive resizing of the window at this
360 // get the hints from the window
361 if (XGetWMNormalHints(otk::OBDisplay::display
, _window
, &size
, &ret
)) {
362 _positioned
= (size
.flags
& (PPosition
|USPosition
));
364 if (size
.flags
& PWinGravity
)
365 _gravity
= size
.win_gravity
;
367 if (size
.flags
& PMinSize
)
368 _min_size
.setPoint(size
.min_width
, size
.min_height
);
370 if (size
.flags
& PMaxSize
)
371 _max_size
.setPoint(size
.max_width
, size
.max_height
);
373 if (size
.flags
& PBaseSize
)
374 _base_size
.setPoint(size
.base_width
, size
.base_height
);
376 if (size
.flags
& PResizeInc
)
377 _size_inc
.setPoint(size
.width_inc
, size
.height_inc
);
380 // if the client has a frame, i.e. has already been mapped and is
381 // changing its gravity
382 if (frame
&& _gravity
!= oldgravity
) {
383 // move our idea of the client's position based on its new gravity
385 frame
->frameGravity(x
, y
);
391 void OBClient::updateWMHints()
395 // assume a window takes input if it doesnt specify
399 if ((hints
= XGetWMHints(otk::OBDisplay::display
, _window
)) != NULL
) {
400 if (hints
->flags
& InputHint
)
401 _can_focus
= hints
->input
;
403 if (hints
->flags
& XUrgencyHint
)
406 if (hints
->flags
& WindowGroupHint
) {
407 if (hints
->window_group
!= _group
) {
408 // XXX: remove from the old group if there was one
409 _group
= hints
->window_group
;
410 // XXX: do stuff with the group
420 void OBClient::updateTitle()
422 const otk::OBProperty
*property
= Openbox::instance
->property();
427 if (! property
->get(_window
, otk::OBProperty::net_wm_name
,
428 otk::OBProperty::utf8
, &_title
)) {
430 property
->get(_window
, otk::OBProperty::wm_name
,
431 otk::OBProperty::ascii
, &_title
);
435 _title
= _("Unnamed Window");
438 frame
->setTitle(_title
);
442 void OBClient::updateIconTitle()
444 const otk::OBProperty
*property
= Openbox::instance
->property();
449 if (! property
->get(_window
, otk::OBProperty::net_wm_icon_name
,
450 otk::OBProperty::utf8
, &_icon_title
)) {
452 property
->get(_window
, otk::OBProperty::wm_icon_name
,
453 otk::OBProperty::ascii
, &_icon_title
);
457 _icon_title
= _("Unnamed Window");
461 void OBClient::updateClass()
463 const otk::OBProperty
*property
= Openbox::instance
->property();
466 _app_name
= _app_class
= "";
468 otk::OBProperty::StringVect v
;
469 unsigned long num
= 2;
471 if (! property
->get(_window
, otk::OBProperty::wm_class
,
472 otk::OBProperty::ascii
, &num
, &v
))
475 if (num
> 0) _app_name
= v
[0];
476 if (num
> 1) _app_class
= v
[1];
480 void OBClient::propertyHandler(const XPropertyEvent
&e
)
482 otk::OtkEventHandler::propertyHandler(e
);
484 const otk::OBProperty
*property
= Openbox::instance
->property();
486 // compress changes to a single property into a single change
488 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
489 // XXX: it would be nice to compress ALL changes to a property, not just
490 // changes in a row without other props between.
491 if (ce
.xproperty
.atom
!= e
.atom
) {
492 XPutBackEvent(otk::OBDisplay::display
, &ce
);
497 if (e
.atom
== XA_WM_NORMAL_HINTS
)
499 else if (e
.atom
== XA_WM_HINTS
)
501 else if (e
.atom
== property
->atom(otk::OBProperty::net_wm_name
) ||
502 e
.atom
== property
->atom(otk::OBProperty::wm_name
))
504 else if (e
.atom
== property
->atom(otk::OBProperty::net_wm_icon_name
) ||
505 e
.atom
== property
->atom(otk::OBProperty::wm_icon_name
))
507 else if (e
.atom
== property
->atom(otk::OBProperty::wm_class
))
509 else if (e
.atom
== property
->atom(otk::OBProperty::wm_protocols
))
511 // XXX: transient for hint
516 void OBClient::setWMState(long state
)
518 if (state
== _wmstate
) return; // no change
522 // XXX: cause it to iconify
525 // XXX: cause it to uniconify
532 void OBClient::setDesktop(long target
)
535 //assert(target == 0xffffffff || target < MAX);
537 // XXX: move the window to the new desktop
542 void OBClient::setState(StateAction action
, long data1
, long data2
)
544 const otk::OBProperty
*property
= Openbox::instance
->property();
546 if (!(action
== State_Add
|| action
== State_Remove
||
547 action
== State_Toggle
))
548 return; // an invalid action was passed to the client message, ignore it
550 for (int i
= 0; i
< 2; ++i
) {
551 Atom state
= i
== 0 ? data1
: data2
;
553 if (! state
) continue;
555 // if toggling, then pick whether we're adding or removing
556 if (action
== State_Toggle
) {
557 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
))
558 action
= _modal
? State_Remove
: State_Add
;
560 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
))
561 action
= _max_vert
? State_Remove
: State_Add
;
563 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
))
564 action
= _max_horz
? State_Remove
: State_Add
;
565 else if (state
== property
->atom(otk::OBProperty::net_wm_state_shaded
))
566 action
= _shaded
? State_Remove
: State_Add
;
568 property
->atom(otk::OBProperty::net_wm_state_fullscreen
))
569 action
= _fullscreen
? State_Remove
: State_Add
;
570 else if (state
== property
->atom(otk::OBProperty::net_wm_state_above
))
571 action
= _above
? State_Remove
: State_Add
;
572 else if (state
== property
->atom(otk::OBProperty::net_wm_state_below
))
573 action
= _below
? State_Remove
: State_Add
;
576 if (action
== State_Add
) {
577 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
578 if (_modal
) continue;
580 // XXX: give it focus if another window has focus that shouldnt now
582 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
583 if (_max_vert
) continue;
585 // XXX: resize the window etc
587 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
588 if (_max_horz
) continue;
590 // XXX: resize the window etc
592 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
593 if (_shaded
) continue;
595 // XXX: hide the client window
597 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
598 if (_fullscreen
) continue;
600 // XXX: raise the window n shit
602 property
->atom(otk::OBProperty::net_wm_state_above
)) {
603 if (_above
) continue;
605 // XXX: raise the window n shit
607 property
->atom(otk::OBProperty::net_wm_state_below
)) {
608 if (_below
) continue;
610 // XXX: lower the window n shit
613 } else { // action == State_Remove
614 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
615 if (!_modal
) continue;
618 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
619 if (!_max_vert
) continue;
621 // XXX: resize the window etc
623 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
624 if (!_max_horz
) continue;
626 // XXX: resize the window etc
628 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
629 if (!_shaded
) continue;
631 // XXX: show the client window
633 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
634 if (!_fullscreen
) continue;
636 // XXX: lower the window to its proper layer
638 property
->atom(otk::OBProperty::net_wm_state_above
)) {
639 if (!_above
) continue;
641 // XXX: lower the window to its proper layer
643 property
->atom(otk::OBProperty::net_wm_state_below
)) {
644 if (!_below
) continue;
646 // XXX: raise the window to its proper layer
651 Openbox::instance
->screen(_screen
)->restack(true, this); // raise
655 void OBClient::toggleClientBorder(bool addborder
)
657 // adjust our idea of where the client is, based on its border. When the
658 // border is removed, the client should now be considered to be in a
659 // different position.
660 // when re-adding the border to the client, the same operation needs to be
662 int x
= _area
.x(), y
= _area
.y();
664 case NorthWestGravity
:
666 case SouthWestGravity
:
668 case NorthEastGravity
:
670 case SouthEastGravity
:
671 if (addborder
) x
-= _border_width
* 2;
672 else x
+= _border_width
* 2;
676 case NorthWestGravity
:
678 case NorthEastGravity
:
680 case SouthWestGravity
:
682 case SouthEastGravity
:
683 if (addborder
) y
-= _border_width
* 2;
684 else y
+= _border_width
* 2;
687 // no change for StaticGravity etc.
693 XSetWindowBorderWidth(otk::OBDisplay::display
, _window
, _border_width
);
695 // move the client so it is back it the right spot _with_ its border!
696 XMoveWindow(otk::OBDisplay::display
, _window
, x
, y
);
698 XSetWindowBorderWidth(otk::OBDisplay::display
, _window
, 0);
702 void OBClient::clientMessageHandler(const XClientMessageEvent
&e
)
704 otk::OtkEventHandler::clientMessageHandler(e
);
706 if (e
.format
!= 32) return;
708 const otk::OBProperty
*property
= Openbox::instance
->property();
710 if (e
.message_type
== property
->atom(otk::OBProperty::wm_change_state
)) {
711 // compress changes into a single change
712 bool compress
= false;
714 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
715 // XXX: it would be nice to compress ALL messages of a type, not just
716 // messages in a row without other message types between.
717 if (ce
.xclient
.message_type
!= e
.message_type
) {
718 XPutBackEvent(otk::OBDisplay::display
, &ce
);
724 setWMState(ce
.xclient
.data
.l
[0]); // use the found event
726 setWMState(e
.data
.l
[0]); // use the original event
727 } else if (e
.message_type
==
728 property
->atom(otk::OBProperty::net_wm_desktop
)) {
729 // compress changes into a single change
730 bool compress
= false;
732 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
733 // XXX: it would be nice to compress ALL messages of a type, not just
734 // messages in a row without other message types between.
735 if (ce
.xclient
.message_type
!= e
.message_type
) {
736 XPutBackEvent(otk::OBDisplay::display
, &ce
);
742 setDesktop(e
.data
.l
[0]); // use the found event
744 setDesktop(e
.data
.l
[0]); // use the original event
746 else if (e
.message_type
== property
->atom(otk::OBProperty::net_wm_state
))
747 // can't compress these
748 setState((StateAction
)e
.data
.l
[0], e
.data
.l
[1], e
.data
.l
[2]);
752 #if defined(SHAPE) || defined(DOXYGEN_IGNORE)
753 void OBClient::shapeHandler(const XShapeEvent
&e
)
755 otk::OtkEventHandler::shapeHandler(e
);
762 void OBClient::resize(Corner anchor
, int w
, int h
)
767 // for interactive resizing. have to move half an increment in each
769 w
+= _size_inc
.x() / 2;
770 h
+= _size_inc
.y() / 2;
772 // is the window resizable? if it is not, then don't check its sizes, the
773 // client can do what it wants and the user can't change it anyhow
774 if (_min_size
.x() <= _max_size
.x() && _min_size
.y() <= _max_size
.y()) {
775 // smaller than min size or bigger than max size?
776 if (w
< _min_size
.x()) w
= _min_size
.x();
777 else if (w
> _max_size
.x()) w
= _max_size
.x();
778 if (h
< _min_size
.y()) h
= _min_size
.y();
779 else if (h
> _max_size
.y()) h
= _max_size
.y();
782 // keep to the increments
786 // store the logical size
787 _logical_size
.setPoint(w
, h
);
795 int x
= _area
.x(), y
= _area
.y();
800 x
-= w
- _area
.width();
803 y
-= h
- _area
.height();
806 x
-= w
- _area
.width();
807 y
-= h
- _area
.height();
812 XResizeWindow(otk::OBDisplay::display
, _window
, w
, h
);
814 // resize the frame to match the request
820 void OBClient::move(int x
, int y
)
823 // move the frame to be in the requested position
824 frame
->adjustPosition();
828 void OBClient::close()
831 const otk::OBProperty
*property
= Openbox::instance
->property();
833 if (!(_functions
& Func_Close
)) return;
835 // XXX: itd be cool to do timeouts and shit here for killing the client's
838 ce
.xclient
.type
= ClientMessage
;
839 ce
.xclient
.message_type
= property
->atom(otk::OBProperty::wm_protocols
);
840 ce
.xclient
.display
= otk::OBDisplay::display
;
841 ce
.xclient
.window
= _window
;
842 ce
.xclient
.format
= 32;
843 ce
.xclient
.data
.l
[0] = property
->atom(otk::OBProperty::wm_delete_window
);
844 ce
.xclient
.data
.l
[1] = CurrentTime
;
845 ce
.xclient
.data
.l
[2] = 0l;
846 ce
.xclient
.data
.l
[3] = 0l;
847 ce
.xclient
.data
.l
[4] = 0l;
848 XSendEvent(otk::OBDisplay::display
, _window
, False
, NoEventMask
, &ce
);
852 bool OBClient::focus()
854 if (!_can_focus
|| _focused
) return false;
856 XSetInputFocus(otk::OBDisplay::display
, _window
, RevertToNone
, CurrentTime
);
861 void OBClient::unfocus()
863 if (!_focused
) return;
865 assert(Openbox::instance
->focusedClient() == this);
866 Openbox::instance
->setFocusedClient(0);
870 void OBClient::focusHandler(const XFocusChangeEvent
&e
)
873 printf("FocusIn for 0x%lx\n", e
.window
);
876 OtkEventHandler::focusHandler(e
);
881 Openbox::instance
->setFocusedClient(this);
885 void OBClient::unfocusHandler(const XFocusChangeEvent
&e
)
888 printf("FocusOut for 0x%lx\n", e
.window
);
891 OtkEventHandler::unfocusHandler(e
);
896 if (Openbox::instance
->focusedClient() == this) {
897 printf("UNFOCUSED!\n");
898 Openbox::instance
->setFocusedClient(this);
903 void OBClient::configureRequestHandler(const XConfigureRequestEvent
&e
)
906 printf("ConfigureRequest for 0x%lx\n", e
.window
);
909 OtkEventHandler::configureRequestHandler(e
);
911 // XXX: if we are iconic (or shaded? (fvwm does that)) ignore the event
913 if (e
.value_mask
& CWBorderWidth
)
914 _border_width
= e
.border_width
;
916 // resize, then move, as specified in the EWMH section 7.7
917 if (e
.value_mask
& (CWWidth
| CWHeight
)) {
918 int w
= (e
.value_mask
& CWWidth
) ? e
.width
: _area
.width();
919 int h
= (e
.value_mask
& CWHeight
) ? e
.height
: _area
.height();
923 case NorthEastGravity
:
927 case SouthWestGravity
:
931 case SouthEastGravity
:
932 corner
= BottomRight
;
934 default: // NorthWest, Static, etc
938 resize(corner
, w
, h
);
941 if (e
.value_mask
& (CWX
| CWY
)) {
942 int x
= (e
.value_mask
& CWX
) ? e
.x
: _area
.x();
943 int y
= (e
.value_mask
& CWY
) ? e
.y
: _area
.y();
947 if (e
.value_mask
& CWStackMode
) {
951 // XXX: lower the window
957 // XXX: raise the window
964 void OBClient::unmapHandler(const XUnmapEvent
&e
)
967 printf("UnmapNotify for 0x%lx\n", e
.window
);
975 OtkEventHandler::unmapHandler(e
);
977 // this deletes us etc
978 Openbox::instance
->screen(_screen
)->unmanageWindow(this);
982 void OBClient::destroyHandler(const XDestroyWindowEvent
&e
)
985 printf("DestroyNotify for 0x%lx\n", e
.window
);
988 OtkEventHandler::destroyHandler(e
);
990 // this deletes us etc
991 Openbox::instance
->screen(_screen
)->unmanageWindow(this);
995 void OBClient::reparentHandler(const XReparentEvent
&e
)
997 // this is when the client is first taken captive in the frame
998 if (e
.parent
== frame
->plate()) return;
1001 printf("ReparentNotify for 0x%lx\n", e
.window
);
1004 OtkEventHandler::reparentHandler(e
);
1007 This event is quite rare and is usually handled in unmapHandler.
1008 However, if the window is unmapped when the reparent event occurs,
1009 the window manager never sees it because an unmap event is not sent
1010 to an already unmapped window.
1013 // this deletes us etc
1014 Openbox::instance
->screen(_screen
)->unmanageWindow(this);