1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
4 # include "../config.h"
10 #include "bbscreen.hh"
12 #include "otk/display.hh"
13 #include "otk/property.hh"
17 #include <X11/Xutil.h>
22 #define _(str) gettext(str)
27 OBClient::OBClient(int screen
, Window window
)
28 : otk::OtkEventHandler(),
29 OBWidget(OBWidget::Type_Client
),
30 frame(0), _screen(screen
), _window(window
)
37 // update EVERYTHING the first time!!
39 // the state is kinda assumed to be normal. is this right? XXX
40 _wmstate
= NormalState
; _iconic
= false;
41 // no default decors or functions, each has to be enabled
42 _decorations
= _functions
= 0;
50 // set the decorations and functions
53 // normal windows retain all of the possible decorations and
55 _decorations
= Decor_Titlebar
| Decor_Handle
| Decor_Border
|
56 Decor_Iconify
| Decor_Maximize
;
57 _functions
= Func_Resize
| Func_Move
| Func_Iconify
| Func_Maximize
;
60 // dialogs cannot be maximized
61 _decorations
&= ~Decor_Maximize
;
62 _functions
&= ~Func_Maximize
;
68 // these windows get less functionality
69 _decorations
&= ~(Decor_Iconify
| Decor_Handle
);
70 _functions
&= ~(Func_Iconify
| Func_Resize
);
76 // none of these windows are manipulated by the window manager
82 getMwmHints(); // this fucks (in good ways) with the decors and functions
89 // XXX: updateTransientFor();
100 const otk::OBProperty
*property
= Openbox::instance
->property();
102 // these values should not be persisted across a window unmapping/mapping
103 property
->erase(_window
, otk::OBProperty::net_wm_desktop
);
104 property
->erase(_window
, otk::OBProperty::net_wm_state
);
108 void OBClient::getDesktop()
110 const otk::OBProperty
*property
= Openbox::instance
->property();
112 // defaults to the current desktop
113 _desktop
= 0; // XXX: change this to the current desktop!
115 property
->get(_window
, otk::OBProperty::net_wm_desktop
,
116 otk::OBProperty::Atom_Cardinal
,
121 void OBClient::getType()
123 const otk::OBProperty
*property
= Openbox::instance
->property();
125 _type
= (WindowType
) -1;
128 unsigned long num
= (unsigned) -1;
129 if (property
->get(_window
, otk::OBProperty::net_wm_window_type
,
130 otk::OBProperty::Atom_Atom
,
132 // use the first value that we know about in the array
133 for (unsigned long i
= 0; i
< num
; ++i
) {
135 property
->atom(otk::OBProperty::net_wm_window_type_desktop
))
136 _type
= Type_Desktop
;
138 property
->atom(otk::OBProperty::net_wm_window_type_dock
))
141 property
->atom(otk::OBProperty::net_wm_window_type_toolbar
))
142 _type
= Type_Toolbar
;
144 property
->atom(otk::OBProperty::net_wm_window_type_menu
))
147 property
->atom(otk::OBProperty::net_wm_window_type_utility
))
148 _type
= Type_Utility
;
150 property
->atom(otk::OBProperty::net_wm_window_type_splash
))
153 property
->atom(otk::OBProperty::net_wm_window_type_dialog
))
156 property
->atom(otk::OBProperty::net_wm_window_type_normal
))
158 // else if (val[i] ==
159 // property->atom(otk::OBProperty::kde_net_wm_window_type_override))
160 // mwm_decorations = 0; // prevent this window from getting any decor
161 // XXX: make this work again
166 if (_type
== (WindowType
) -1) {
168 * the window type hint was not set, which means we either classify ourself
169 * as a normal window or a dialog, depending on if we are a transient.
171 // XXX: make this code work!
173 // _type = Type_Dialog;
180 void OBClient::getMwmHints()
182 const otk::OBProperty
*property
= Openbox::instance
->property();
187 num
= MwmHints::elements
;
188 if (!property
->get(_window
, otk::OBProperty::motif_wm_hints
,
189 otk::OBProperty::motif_wm_hints
, &num
,
190 (unsigned long **)&hints
))
193 if (num
< MwmHints::elements
) {
198 // retrieved the hints
199 // Mwm Hints are applied subtractively to what has already been chosen for
200 // decor and functionality
202 if (hints
->flags
& MwmFlag_Decorations
) {
203 if (! (hints
->decorations
& MwmDecor_All
)) {
204 if (! (hints
->decorations
& MwmDecor_Border
))
205 _decorations
&= ~Decor_Border
;
206 if (! (hints
->decorations
& MwmDecor_Handle
))
207 _decorations
&= ~Decor_Handle
;
208 if (! (hints
->decorations
& MwmDecor_Title
))
209 _decorations
&= ~Decor_Titlebar
;
210 if (! (hints
->decorations
& MwmDecor_Iconify
))
211 _decorations
&= ~Decor_Iconify
;
212 if (! (hints
->decorations
& MwmDecor_Maximize
))
213 _decorations
&= ~Decor_Maximize
;
217 if (hints
->flags
& MwmFlag_Functions
) {
218 if (! (hints
->functions
& MwmFunc_All
)) {
219 if (! (hints
->functions
& MwmFunc_Resize
))
220 _functions
&= ~Func_Resize
;
221 if (! (hints
->functions
& MwmFunc_Move
))
222 _functions
&= ~Func_Move
;
223 if (! (hints
->functions
& MwmFunc_Iconify
))
224 _functions
&= ~Func_Iconify
;
225 if (! (hints
->functions
& MwmFunc_Maximize
))
226 _functions
&= ~Func_Maximize
;
227 //if (! (hints->functions & MwmFunc_Close))
228 // _functions &= ~Func_Close;
235 void OBClient::getArea()
237 XWindowAttributes wattrib
;
240 ret
= XGetWindowAttributes(otk::OBDisplay::display
, _window
, &wattrib
);
241 assert(ret
!= BadWindow
);
243 _area
.setRect(wattrib
.x
, wattrib
.y
, wattrib
.width
, wattrib
.height
);
244 _border_width
= wattrib
.border_width
;
248 void OBClient::getState()
250 const otk::OBProperty
*property
= Openbox::instance
->property();
252 _modal
= _shaded
= _max_horz
= _max_vert
= _fullscreen
= _above
= _below
=
255 unsigned long *state
;
256 unsigned long num
= (unsigned) -1;
258 if (property
->get(_window
, otk::OBProperty::net_wm_state
,
259 otk::OBProperty::Atom_Atom
, &num
, &state
)) {
260 for (unsigned long i
= 0; i
< num
; ++i
) {
261 if (state
[i
] == property
->atom(otk::OBProperty::net_wm_state_modal
))
264 property
->atom(otk::OBProperty::net_wm_state_shaded
))
267 property
->atom(otk::OBProperty::net_wm_state_fullscreen
))
270 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
))
273 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
))
276 property
->atom(otk::OBProperty::net_wm_state_above
))
279 property
->atom(otk::OBProperty::net_wm_state_below
))
288 void OBClient::getShaped()
292 if (otk::OBDisplay::shape()) {
297 XShapeSelectInput(otk::OBDisplay::display
, _window
, ShapeNotifyMask
);
299 XShapeQueryExtents(otk::OBDisplay::display
, _window
, &s
, &foo
,
300 &foo
, &ufoo
, &ufoo
, &foo
, &foo
, &foo
, &ufoo
, &ufoo
);
307 void OBClient::calcLayer() {
308 if (_iconic
) _layer
= OBScreen::Layer_Icon
;
309 else if (_type
== Type_Desktop
) _layer
= OBScreen::Layer_Desktop
;
310 else if (_type
== Type_Dock
) _layer
= OBScreen::Layer_Top
;
311 else if (_fullscreen
) _layer
= OBScreen::Layer_Fullscreen
;
312 else if (_above
) _layer
= OBScreen::Layer_Above
;
313 else if (_below
) _layer
= OBScreen::Layer_Below
;
314 else _layer
= OBScreen::Layer_Normal
;
318 void OBClient::updateProtocols()
320 const otk::OBProperty
*property
= Openbox::instance
->property();
325 _focus_notify
= false;
326 _decorations
&= ~Decor_Close
;
327 _functions
&= ~Func_Close
;
329 if (XGetWMProtocols(otk::OBDisplay::display
, _window
, &proto
, &num_return
)) {
330 for (int i
= 0; i
< num_return
; ++i
) {
331 if (proto
[i
] == property
->atom(otk::OBProperty::wm_delete_window
)) {
332 _decorations
|= Decor_Close
;
333 _functions
|= Func_Close
;
334 // XXX: update the decor?
335 } else if (proto
[i
] == property
->atom(otk::OBProperty::wm_take_focus
))
336 // if this protocol is requested, then the window will be notified
337 // by the window manager whenever it receives focus
338 _focus_notify
= true;
345 void OBClient::updateNormalHints()
349 int oldgravity
= _gravity
;
352 _gravity
= NorthWestGravity
;
353 _size_inc
.setPoint(1, 1);
354 _base_size
.setPoint(0, 0);
355 _min_size
.setPoint(0, 0);
356 _max_size
.setPoint(INT_MAX
, INT_MAX
);
358 // XXX: might want to cancel any interactive resizing of the window at this
361 // get the hints from the window
362 if (XGetWMNormalHints(otk::OBDisplay::display
, _window
, &size
, &ret
)) {
363 _positioned
= (size
.flags
& (PPosition
|USPosition
));
365 if (size
.flags
& PWinGravity
)
366 _gravity
= size
.win_gravity
;
368 if (size
.flags
& PMinSize
)
369 _min_size
.setPoint(size
.min_width
, size
.min_height
);
371 if (size
.flags
& PMaxSize
)
372 _max_size
.setPoint(size
.max_width
, size
.max_height
);
374 if (size
.flags
& PBaseSize
)
375 _base_size
.setPoint(size
.base_width
, size
.base_height
);
377 if (size
.flags
& PResizeInc
)
378 _size_inc
.setPoint(size
.width_inc
, size
.height_inc
);
381 // if the client has a frame, i.e. has already been mapped and is
382 // changing its gravity
383 if (frame
&& _gravity
!= oldgravity
) {
384 // move our idea of the client's position based on its new gravity
386 frame
->frameGravity(x
, y
);
392 void OBClient::updateWMHints()
396 // assume a window takes input if it doesnt specify
400 if ((hints
= XGetWMHints(otk::OBDisplay::display
, _window
)) != NULL
) {
401 if (hints
->flags
& InputHint
)
402 _can_focus
= hints
->input
;
404 if (hints
->flags
& XUrgencyHint
)
407 if (hints
->flags
& WindowGroupHint
) {
408 if (hints
->window_group
!= _group
) {
409 // XXX: remove from the old group if there was one
410 _group
= hints
->window_group
;
411 // XXX: do stuff with the group
421 void OBClient::updateTitle()
423 const otk::OBProperty
*property
= Openbox::instance
->property();
428 if (! property
->get(_window
, otk::OBProperty::net_wm_name
,
429 otk::OBProperty::utf8
, &_title
)) {
431 property
->get(_window
, otk::OBProperty::wm_name
,
432 otk::OBProperty::ascii
, &_title
);
436 _title
= _("Unnamed Window");
439 frame
->setTitle(_title
);
443 void OBClient::updateIconTitle()
445 const otk::OBProperty
*property
= Openbox::instance
->property();
450 if (! property
->get(_window
, otk::OBProperty::net_wm_icon_name
,
451 otk::OBProperty::utf8
, &_icon_title
)) {
453 property
->get(_window
, otk::OBProperty::wm_icon_name
,
454 otk::OBProperty::ascii
, &_icon_title
);
458 _icon_title
= _("Unnamed Window");
462 void OBClient::updateClass()
464 const otk::OBProperty
*property
= Openbox::instance
->property();
467 _app_name
= _app_class
= "";
469 otk::OBProperty::StringVect v
;
470 unsigned long num
= 2;
472 if (! property
->get(_window
, otk::OBProperty::wm_class
,
473 otk::OBProperty::ascii
, &num
, &v
))
476 if (num
> 0) _app_name
= v
[0];
477 if (num
> 1) _app_class
= v
[1];
481 void OBClient::propertyHandler(const XPropertyEvent
&e
)
483 otk::OtkEventHandler::propertyHandler(e
);
485 const otk::OBProperty
*property
= Openbox::instance
->property();
487 // compress changes to a single property into a single change
489 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
490 // XXX: it would be nice to compress ALL changes to a property, not just
491 // changes in a row without other props between.
492 if (ce
.xproperty
.atom
!= e
.atom
) {
493 XPutBackEvent(otk::OBDisplay::display
, &ce
);
498 if (e
.atom
== XA_WM_NORMAL_HINTS
)
500 else if (e
.atom
== XA_WM_HINTS
)
502 else if (e
.atom
== property
->atom(otk::OBProperty::net_wm_name
) ||
503 e
.atom
== property
->atom(otk::OBProperty::wm_name
))
505 else if (e
.atom
== property
->atom(otk::OBProperty::net_wm_icon_name
) ||
506 e
.atom
== property
->atom(otk::OBProperty::wm_icon_name
))
508 else if (e
.atom
== property
->atom(otk::OBProperty::wm_class
))
510 else if (e
.atom
== property
->atom(otk::OBProperty::wm_protocols
))
512 // XXX: transient for hint
517 void OBClient::setWMState(long state
)
519 if (state
== _wmstate
) return; // no change
523 // XXX: cause it to iconify
526 // XXX: cause it to uniconify
533 void OBClient::setDesktop(long target
)
536 //assert(target == 0xffffffff || target < MAX);
538 // XXX: move the window to the new desktop
543 void OBClient::setState(StateAction action
, long data1
, long data2
)
545 const otk::OBProperty
*property
= Openbox::instance
->property();
547 if (!(action
== State_Add
|| action
== State_Remove
||
548 action
== State_Toggle
))
549 return; // an invalid action was passed to the client message, ignore it
551 for (int i
= 0; i
< 2; ++i
) {
552 Atom state
= i
== 0 ? data1
: data2
;
554 if (! state
) continue;
556 // if toggling, then pick whether we're adding or removing
557 if (action
== State_Toggle
) {
558 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
))
559 action
= _modal
? State_Remove
: State_Add
;
561 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
))
562 action
= _max_vert
? State_Remove
: State_Add
;
564 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
))
565 action
= _max_horz
? State_Remove
: State_Add
;
566 else if (state
== property
->atom(otk::OBProperty::net_wm_state_shaded
))
567 action
= _shaded
? State_Remove
: State_Add
;
569 property
->atom(otk::OBProperty::net_wm_state_fullscreen
))
570 action
= _fullscreen
? State_Remove
: State_Add
;
571 else if (state
== property
->atom(otk::OBProperty::net_wm_state_above
))
572 action
= _above
? State_Remove
: State_Add
;
573 else if (state
== property
->atom(otk::OBProperty::net_wm_state_below
))
574 action
= _below
? State_Remove
: State_Add
;
577 if (action
== State_Add
) {
578 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
579 if (_modal
) continue;
581 // XXX: give it focus if another window has focus that shouldnt now
583 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
584 if (_max_vert
) continue;
586 // XXX: resize the window etc
588 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
589 if (_max_horz
) continue;
591 // XXX: resize the window etc
593 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
594 if (_shaded
) continue;
596 // XXX: hide the client window
598 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
599 if (_fullscreen
) continue;
601 // XXX: raise the window n shit
603 property
->atom(otk::OBProperty::net_wm_state_above
)) {
604 if (_above
) continue;
606 // XXX: raise the window n shit
608 property
->atom(otk::OBProperty::net_wm_state_below
)) {
609 if (_below
) continue;
611 // XXX: lower the window n shit
614 } else { // action == State_Remove
615 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
616 if (!_modal
) continue;
619 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
620 if (!_max_vert
) continue;
622 // XXX: resize the window etc
624 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
625 if (!_max_horz
) continue;
627 // XXX: resize the window etc
629 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
630 if (!_shaded
) continue;
632 // XXX: show the client window
634 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
635 if (!_fullscreen
) continue;
637 // XXX: lower the window to its proper layer
639 property
->atom(otk::OBProperty::net_wm_state_above
)) {
640 if (!_above
) continue;
642 // XXX: lower the window to its proper layer
644 property
->atom(otk::OBProperty::net_wm_state_below
)) {
645 if (!_below
) continue;
647 // XXX: raise the window to its proper layer
652 Openbox::instance
->screen(_screen
)->restack(true, this); // raise
656 void OBClient::toggleClientBorder(bool addborder
)
658 // adjust our idea of where the client is, based on its border. When the
659 // border is removed, the client should now be considered to be in a
660 // different position.
661 // when re-adding the border to the client, the same operation needs to be
663 int x
= _area
.x(), y
= _area
.y();
665 case NorthWestGravity
:
667 case SouthWestGravity
:
669 case NorthEastGravity
:
671 case SouthEastGravity
:
672 if (addborder
) x
-= _border_width
* 2;
673 else x
+= _border_width
* 2;
677 case NorthWestGravity
:
679 case NorthEastGravity
:
681 case SouthWestGravity
:
683 case SouthEastGravity
:
684 if (addborder
) y
-= _border_width
* 2;
685 else y
+= _border_width
* 2;
688 // no change for StaticGravity etc.
694 XSetWindowBorderWidth(otk::OBDisplay::display
, _window
, _border_width
);
696 // move the client so it is back it the right spot _with_ its border!
697 XMoveWindow(otk::OBDisplay::display
, _window
, x
, y
);
699 XSetWindowBorderWidth(otk::OBDisplay::display
, _window
, 0);
703 void OBClient::clientMessageHandler(const XClientMessageEvent
&e
)
705 otk::OtkEventHandler::clientMessageHandler(e
);
707 if (e
.format
!= 32) return;
709 const otk::OBProperty
*property
= Openbox::instance
->property();
711 if (e
.message_type
== property
->atom(otk::OBProperty::wm_change_state
)) {
712 // compress changes into a single change
713 bool compress
= false;
715 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
716 // XXX: it would be nice to compress ALL messages of a type, not just
717 // messages in a row without other message types between.
718 if (ce
.xclient
.message_type
!= e
.message_type
) {
719 XPutBackEvent(otk::OBDisplay::display
, &ce
);
725 setWMState(ce
.xclient
.data
.l
[0]); // use the found event
727 setWMState(e
.data
.l
[0]); // use the original event
728 } else if (e
.message_type
==
729 property
->atom(otk::OBProperty::net_wm_desktop
)) {
730 // compress changes into a single change
731 bool compress
= false;
733 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
734 // XXX: it would be nice to compress ALL messages of a type, not just
735 // messages in a row without other message types between.
736 if (ce
.xclient
.message_type
!= e
.message_type
) {
737 XPutBackEvent(otk::OBDisplay::display
, &ce
);
743 setDesktop(e
.data
.l
[0]); // use the found event
745 setDesktop(e
.data
.l
[0]); // use the original event
747 else if (e
.message_type
== property
->atom(otk::OBProperty::net_wm_state
))
748 // can't compress these
749 setState((StateAction
)e
.data
.l
[0], e
.data
.l
[1], e
.data
.l
[2]);
753 #if defined(SHAPE) || defined(DOXYGEN_IGNORE)
754 void OBClient::shapeHandler(const XShapeEvent
&e
)
756 otk::OtkEventHandler::shapeHandler(e
);
763 void OBClient::resize(Corner anchor
, int w
, int h
)
768 // for interactive resizing. have to move half an increment in each
770 w
+= _size_inc
.x() / 2;
771 h
+= _size_inc
.y() / 2;
773 // is the window resizable? if it is not, then don't check its sizes, the
774 // client can do what it wants and the user can't change it anyhow
775 if (_min_size
.x() <= _max_size
.x() && _min_size
.y() <= _max_size
.y()) {
776 // smaller than min size or bigger than max size?
777 if (w
< _min_size
.x()) w
= _min_size
.x();
778 else if (w
> _max_size
.x()) w
= _max_size
.x();
779 if (h
< _min_size
.y()) h
= _min_size
.y();
780 else if (h
> _max_size
.y()) h
= _max_size
.y();
783 // keep to the increments
787 // store the logical size
788 _logical_size
.setPoint(w
, h
);
796 int x
= _area
.x(), y
= _area
.y();
801 x
-= w
- _area
.width();
804 y
-= h
- _area
.height();
807 x
-= w
- _area
.width();
808 y
-= h
- _area
.height();
813 XResizeWindow(otk::OBDisplay::display
, _window
, w
, h
);
815 // resize the frame to match the request
821 void OBClient::move(int x
, int y
)
824 // move the frame to be in the requested position
825 frame
->adjustPosition();
829 void OBClient::close()
832 const otk::OBProperty
*property
= Openbox::instance
->property();
834 if (!(_functions
& Func_Close
)) return;
836 // XXX: itd be cool to do timeouts and shit here for killing the client's
839 ce
.xclient
.type
= ClientMessage
;
840 ce
.xclient
.message_type
= property
->atom(otk::OBProperty::wm_protocols
);
841 ce
.xclient
.display
= otk::OBDisplay::display
;
842 ce
.xclient
.window
= _window
;
843 ce
.xclient
.format
= 32;
844 ce
.xclient
.data
.l
[0] = property
->atom(otk::OBProperty::wm_delete_window
);
845 ce
.xclient
.data
.l
[1] = CurrentTime
;
846 ce
.xclient
.data
.l
[2] = 0l;
847 ce
.xclient
.data
.l
[3] = 0l;
848 ce
.xclient
.data
.l
[4] = 0l;
849 XSendEvent(otk::OBDisplay::display
, _window
, False
, NoEventMask
, &ce
);
853 bool OBClient::focus()
855 if (!_can_focus
|| _focused
) return false;
857 XSetInputFocus(otk::OBDisplay::display
, _window
, RevertToNone
, CurrentTime
);
862 void OBClient::unfocus()
864 if (!_focused
) return;
866 assert(Openbox::instance
->focusedClient() == this);
867 Openbox::instance
->setFocusedClient(0);
871 void OBClient::focusHandler(const XFocusChangeEvent
&e
)
874 printf("FocusIn for 0x%lx\n", e
.window
);
877 OtkEventHandler::focusHandler(e
);
882 Openbox::instance
->setFocusedClient(this);
886 void OBClient::unfocusHandler(const XFocusChangeEvent
&e
)
889 printf("FocusOut for 0x%lx\n", e
.window
);
892 OtkEventHandler::unfocusHandler(e
);
897 if (Openbox::instance
->focusedClient() == this) {
898 printf("UNFOCUSED!\n");
899 Openbox::instance
->setFocusedClient(this);
904 void OBClient::configureRequestHandler(const XConfigureRequestEvent
&e
)
907 printf("ConfigureRequest for 0x%lx\n", e
.window
);
910 OtkEventHandler::configureRequestHandler(e
);
912 // XXX: if we are iconic (or shaded? (fvwm does that)) ignore the event
914 if (e
.value_mask
& CWBorderWidth
)
915 _border_width
= e
.border_width
;
917 // resize, then move, as specified in the EWMH section 7.7
918 if (e
.value_mask
& (CWWidth
| CWHeight
)) {
919 int w
= (e
.value_mask
& CWWidth
) ? e
.width
: _area
.width();
920 int h
= (e
.value_mask
& CWHeight
) ? e
.height
: _area
.height();
924 case NorthEastGravity
:
928 case SouthWestGravity
:
932 case SouthEastGravity
:
933 corner
= BottomRight
;
935 default: // NorthWest, Static, etc
939 resize(corner
, w
, h
);
942 if (e
.value_mask
& (CWX
| CWY
)) {
943 int x
= (e
.value_mask
& CWX
) ? e
.x
: _area
.x();
944 int y
= (e
.value_mask
& CWY
) ? e
.y
: _area
.y();
948 if (e
.value_mask
& CWStackMode
) {
952 // XXX: lower the window
958 // XXX: raise the window
965 void OBClient::unmapHandler(const XUnmapEvent
&e
)
968 printf("UnmapNotify for 0x%lx\n", e
.window
);
976 OtkEventHandler::unmapHandler(e
);
978 // this deletes us etc
979 Openbox::instance
->screen(_screen
)->unmanageWindow(this);
983 void OBClient::destroyHandler(const XDestroyWindowEvent
&e
)
986 printf("DestroyNotify for 0x%lx\n", e
.window
);
989 OtkEventHandler::destroyHandler(e
);
991 // this deletes us etc
992 Openbox::instance
->screen(_screen
)->unmanageWindow(this);
996 void OBClient::reparentHandler(const XReparentEvent
&e
)
998 // this is when the client is first taken captive in the frame
999 if (e
.parent
== frame
->plate()) return;
1002 printf("ReparentNotify for 0x%lx\n", e
.window
);
1005 OtkEventHandler::reparentHandler(e
);
1008 This event is quite rare and is usually handled in unmapHandler.
1009 However, if the window is unmapped when the reparent event occurs,
1010 the window manager never sees it because an unmap event is not sent
1011 to an already unmapped window.
1014 // this deletes us etc
1015 Openbox::instance
->screen(_screen
)->unmanageWindow(this);