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
;
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();
96 printf("Mapped window: 0x%lx\n"
97 " title: \t%s\t icon title: \t%s\n"
98 " app name: \t%s\t\t class: \t%s\n"
99 " position: \t%d, %d\t\t size: \t%d, %d\n"
100 " desktop: \t%lu\t\t group: \t0x%lx\n"
101 " type: \t%d\t\t min size \t%d, %d\n"
102 " base size \t%d, %d\t\t max size \t%d, %d\n"
103 " size incr \t%d, %d\t\t gravity \t%d\n"
104 " wm state \t%ld\t\t can be focused:\t%s\n"
105 " notify focus: \t%s\t\t urgent: \t%s\n"
106 " shaped: \t%s\t\t modal: \t%s\n"
107 " shaded: \t%s\t\t iconic: \t%s\n"
108 " vert maximized:\t%s\t\t horz maximized:\t%s\n"
109 " fullscreen: \t%s\t\t floating: \t%s\n"
110 " requested pos: \t%s\n",
116 _area.x(), _area.y(),
117 _area.width(), _area.height(),
127 _can_focus ? "yes" : "no",
128 _focus_notify ? "yes" : "no",
129 _urgent ? "yes" : "no",
130 _shaped ? "yes" : "no",
131 _modal ? "yes" : "no",
132 _shaded ? "yes" : "no",
133 _iconic ? "yes" : "no",
134 _max_vert ? "yes" : "no",
135 _max_horz ? "yes" : "no",
136 _fullscreen ? "yes" : "no",
137 _floating ? "yes" : "no",
138 _positioned ? "yes" : "no");
144 OBClient::~OBClient()
146 const otk::OBProperty
*property
= Openbox::instance
->property();
148 // these values should not be persisted across a window unmapping/mapping
149 property
->erase(_window
, otk::OBProperty::net_wm_desktop
);
150 property
->erase(_window
, otk::OBProperty::net_wm_state
);
154 void OBClient::getDesktop()
156 const otk::OBProperty
*property
= Openbox::instance
->property();
158 // defaults to the current desktop
159 _desktop
= 0; // XXX: change this to the current desktop!
161 property
->get(_window
, otk::OBProperty::net_wm_desktop
,
162 otk::OBProperty::Atom_Cardinal
,
167 void OBClient::getType()
169 const otk::OBProperty
*property
= Openbox::instance
->property();
171 _type
= (WindowType
) -1;
174 unsigned long num
= (unsigned) -1;
175 if (property
->get(_window
, otk::OBProperty::net_wm_window_type
,
176 otk::OBProperty::Atom_Atom
,
178 // use the first value that we know about in the array
179 for (unsigned long i
= 0; i
< num
; ++i
) {
181 property
->atom(otk::OBProperty::net_wm_window_type_desktop
))
182 _type
= Type_Desktop
;
184 property
->atom(otk::OBProperty::net_wm_window_type_dock
))
187 property
->atom(otk::OBProperty::net_wm_window_type_toolbar
))
188 _type
= Type_Toolbar
;
190 property
->atom(otk::OBProperty::net_wm_window_type_menu
))
193 property
->atom(otk::OBProperty::net_wm_window_type_utility
))
194 _type
= Type_Utility
;
196 property
->atom(otk::OBProperty::net_wm_window_type_splash
))
199 property
->atom(otk::OBProperty::net_wm_window_type_dialog
))
202 property
->atom(otk::OBProperty::net_wm_window_type_normal
))
204 // else if (val[i] ==
205 // property->atom(otk::OBProperty::kde_net_wm_window_type_override))
206 // mwm_decorations = 0; // prevent this window from getting any decor
207 // XXX: make this work again
212 if (_type
== (WindowType
) -1) {
214 * the window type hint was not set, which means we either classify ourself
215 * as a normal window or a dialog, depending on if we are a transient.
217 // XXX: make this code work!
219 // _type = Type_Dialog;
226 void OBClient::getMwmHints()
228 const otk::OBProperty
*property
= Openbox::instance
->property();
233 num
= MwmHints::elements
;
234 if (!property
->get(_window
, otk::OBProperty::motif_wm_hints
,
235 otk::OBProperty::motif_wm_hints
, &num
,
236 (unsigned long **)&hints
))
239 if (num
< MwmHints::elements
) {
244 // retrieved the hints
245 // Mwm Hints are applied subtractively to what has already been chosen for
246 // decor and functionality
248 if (hints
->flags
& MwmFlag_Decorations
) {
249 if (! (hints
->decorations
& MwmDecor_All
)) {
250 if (! (hints
->decorations
& MwmDecor_Border
))
251 _decorations
&= ~Decor_Border
;
252 if (! (hints
->decorations
& MwmDecor_Handle
))
253 _decorations
&= ~Decor_Handle
;
254 if (! (hints
->decorations
& MwmDecor_Title
))
255 _decorations
&= ~Decor_Titlebar
;
256 if (! (hints
->decorations
& MwmDecor_Iconify
))
257 _decorations
&= ~Decor_Iconify
;
258 if (! (hints
->decorations
& MwmDecor_Maximize
))
259 _decorations
&= ~Decor_Maximize
;
263 if (hints
->flags
& MwmFlag_Functions
) {
264 if (! (hints
->functions
& MwmFunc_All
)) {
265 if (! (hints
->functions
& MwmFunc_Resize
))
266 _functions
&= ~Func_Resize
;
267 if (! (hints
->functions
& MwmFunc_Move
))
268 _functions
&= ~Func_Move
;
269 if (! (hints
->functions
& MwmFunc_Iconify
))
270 _functions
&= ~Func_Iconify
;
271 if (! (hints
->functions
& MwmFunc_Maximize
))
272 _functions
&= ~Func_Maximize
;
273 //if (! (hints->functions & MwmFunc_Close))
274 // _functions &= ~Func_Close;
281 void OBClient::getArea()
283 XWindowAttributes wattrib
;
286 ret
= XGetWindowAttributes(otk::OBDisplay::display
, _window
, &wattrib
);
287 assert(ret
!= BadWindow
);
289 _area
.setRect(wattrib
.x
, wattrib
.y
, wattrib
.width
, wattrib
.height
);
290 _border_width
= wattrib
.border_width
;
294 void OBClient::getState()
296 const otk::OBProperty
*property
= Openbox::instance
->property();
298 _modal
= _shaded
= _max_horz
= _max_vert
= _fullscreen
= _floating
= false;
300 unsigned long *state
;
301 unsigned long num
= (unsigned) -1;
303 if (property
->get(_window
, otk::OBProperty::net_wm_state
,
304 otk::OBProperty::Atom_Atom
, &num
, &state
)) {
305 for (unsigned long i
= 0; i
< num
; ++i
) {
306 if (state
[i
] == property
->atom(otk::OBProperty::net_wm_state_modal
))
309 property
->atom(otk::OBProperty::net_wm_state_shaded
))
312 property
->atom(otk::OBProperty::net_wm_state_fullscreen
))
315 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
))
318 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
))
327 void OBClient::getShaped()
331 if (otk::OBDisplay::shape()) {
336 XShapeSelectInput(otk::OBDisplay::display
, _window
, ShapeNotifyMask
);
338 XShapeQueryExtents(otk::OBDisplay::display
, _window
, &s
, &foo
,
339 &foo
, &ufoo
, &ufoo
, &foo
, &foo
, &foo
, &ufoo
, &ufoo
);
346 void OBClient::updateProtocols()
348 const otk::OBProperty
*property
= Openbox::instance
->property();
353 _focus_notify
= false;
354 _decorations
&= ~Decor_Close
;
355 _functions
&= ~Func_Close
;
357 if (XGetWMProtocols(otk::OBDisplay::display
, _window
, &proto
, &num_return
)) {
358 for (int i
= 0; i
< num_return
; ++i
) {
359 if (proto
[i
] == property
->atom(otk::OBProperty::wm_delete_window
)) {
360 _decorations
|= Decor_Close
;
361 _functions
|= Func_Close
;
362 // XXX: update the decor?
363 } else if (proto
[i
] == property
->atom(otk::OBProperty::wm_take_focus
))
364 // if this protocol is requested, then the window will be notified
365 // by the window manager whenever it receives focus
366 _focus_notify
= true;
373 void OBClient::updateNormalHints()
377 int oldgravity
= _gravity
;
380 _gravity
= NorthWestGravity
;
381 _size_inc
.setPoint(1, 1);
382 _base_size
.setPoint(0, 0);
383 _min_size
.setPoint(0, 0);
384 _max_size
.setPoint(INT_MAX
, INT_MAX
);
386 // XXX: might want to cancel any interactive resizing of the window at this
389 // get the hints from the window
390 if (XGetWMNormalHints(otk::OBDisplay::display
, _window
, &size
, &ret
)) {
391 _positioned
= (size
.flags
& (PPosition
|USPosition
));
393 if (size
.flags
& PWinGravity
)
394 _gravity
= size
.win_gravity
;
396 if (size
.flags
& PMinSize
)
397 _min_size
.setPoint(size
.min_width
, size
.min_height
);
399 if (size
.flags
& PMaxSize
)
400 _max_size
.setPoint(size
.max_width
, size
.max_height
);
402 if (size
.flags
& PBaseSize
)
403 _base_size
.setPoint(size
.base_width
, size
.base_height
);
405 if (size
.flags
& PResizeInc
)
406 _size_inc
.setPoint(size
.width_inc
, size
.height_inc
);
409 // if the client has a frame, i.e. has already been mapped and is
410 // changing its gravity
411 if (frame
&& _gravity
!= oldgravity
) {
412 // move our idea of the client's position based on its new gravity
414 frame
->frameGravity(x
, y
);
420 void OBClient::updateWMHints()
424 // assume a window takes input if it doesnt specify
428 if ((hints
= XGetWMHints(otk::OBDisplay::display
, _window
)) != NULL
) {
429 if (hints
->flags
& InputHint
)
430 _can_focus
= hints
->input
;
432 if (hints
->flags
& XUrgencyHint
)
435 if (hints
->flags
& WindowGroupHint
) {
436 if (hints
->window_group
!= _group
) {
437 // XXX: remove from the old group if there was one
438 _group
= hints
->window_group
;
439 // XXX: do stuff with the group
449 void OBClient::updateTitle()
451 const otk::OBProperty
*property
= Openbox::instance
->property();
456 if (! property
->get(_window
, otk::OBProperty::net_wm_name
,
457 otk::OBProperty::utf8
, &_title
)) {
459 property
->get(_window
, otk::OBProperty::wm_name
,
460 otk::OBProperty::ascii
, &_title
);
464 _title
= _("Unnamed Window");
467 frame
->setTitle(_title
);
471 void OBClient::updateIconTitle()
473 const otk::OBProperty
*property
= Openbox::instance
->property();
478 if (! property
->get(_window
, otk::OBProperty::net_wm_icon_name
,
479 otk::OBProperty::utf8
, &_icon_title
)) {
481 property
->get(_window
, otk::OBProperty::wm_icon_name
,
482 otk::OBProperty::ascii
, &_icon_title
);
486 _icon_title
= _("Unnamed Window");
490 void OBClient::updateClass()
492 const otk::OBProperty
*property
= Openbox::instance
->property();
495 _app_name
= _app_class
= "";
497 otk::OBProperty::StringVect v
;
498 unsigned long num
= 2;
500 if (! property
->get(_window
, otk::OBProperty::wm_class
,
501 otk::OBProperty::ascii
, &num
, &v
))
504 if (num
> 0) _app_name
= v
[0];
505 if (num
> 1) _app_class
= v
[1];
509 void OBClient::propertyHandler(const XPropertyEvent
&e
)
511 otk::OtkEventHandler::propertyHandler(e
);
513 const otk::OBProperty
*property
= Openbox::instance
->property();
515 // compress changes to a single property into a single change
517 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
518 // XXX: it would be nice to compress ALL changes to a property, not just
519 // changes in a row without other props between.
520 if (ce
.xproperty
.atom
!= e
.atom
) {
521 XPutBackEvent(otk::OBDisplay::display
, &ce
);
526 if (e
.atom
== XA_WM_NORMAL_HINTS
)
528 else if (e
.atom
== XA_WM_HINTS
)
530 else if (e
.atom
== property
->atom(otk::OBProperty::net_wm_name
) ||
531 e
.atom
== property
->atom(otk::OBProperty::wm_name
))
533 else if (e
.atom
== property
->atom(otk::OBProperty::net_wm_icon_name
) ||
534 e
.atom
== property
->atom(otk::OBProperty::wm_icon_name
))
536 else if (e
.atom
== property
->atom(otk::OBProperty::wm_class
))
538 else if (e
.atom
== property
->atom(otk::OBProperty::wm_protocols
))
540 // XXX: transient for hint
545 void OBClient::setWMState(long state
)
547 if (state
== _wmstate
) return; // no change
551 // XXX: cause it to iconify
554 // XXX: cause it to uniconify
561 void OBClient::setDesktop(long target
)
564 //assert(target == 0xffffffff || target < MAX);
566 // XXX: move the window to the new desktop
571 void OBClient::setState(StateAction action
, long data1
, long data2
)
573 const otk::OBProperty
*property
= Openbox::instance
->property();
575 if (!(action
== State_Add
|| action
== State_Remove
||
576 action
== State_Toggle
))
577 return; // an invalid action was passed to the client message, ignore it
579 for (int i
= 0; i
< 2; ++i
) {
580 Atom state
= i
== 0 ? data1
: data2
;
582 if (! state
) continue;
584 // if toggling, then pick whether we're adding or removing
585 if (action
== State_Toggle
) {
586 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
))
587 action
= _modal
? State_Remove
: State_Add
;
589 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
))
590 action
= _max_vert
? State_Remove
: State_Add
;
592 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
))
593 action
= _max_horz
? State_Remove
: State_Add
;
594 else if (state
== property
->atom(otk::OBProperty::net_wm_state_shaded
))
595 action
= _shaded
? State_Remove
: State_Add
;
597 property
->atom(otk::OBProperty::net_wm_state_fullscreen
))
598 action
= _fullscreen
? State_Remove
: State_Add
;
599 else if (state
== property
->atom(otk::OBProperty::net_wm_state_floating
))
600 action
= _floating
? State_Remove
: State_Add
;
603 if (action
== State_Add
) {
604 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
605 if (_modal
) continue;
607 // XXX: give it focus if another window has focus that shouldnt now
609 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
610 if (_max_vert
) continue;
612 // XXX: resize the window etc
614 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
615 if (_max_horz
) continue;
617 // XXX: resize the window etc
619 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
620 if (_shaded
) continue;
622 // XXX: hide the client window
624 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
625 if (_fullscreen
) continue;
627 // XXX: raise the window n shit
629 property
->atom(otk::OBProperty::net_wm_state_floating
)) {
630 if (_floating
) continue;
632 // XXX: raise the window n shit
635 } else { // action == State_Remove
636 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
637 if (!_modal
) continue;
640 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
641 if (!_max_vert
) continue;
643 // XXX: resize the window etc
645 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
646 if (!_max_horz
) continue;
648 // XXX: resize the window etc
650 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
651 if (!_shaded
) continue;
653 // XXX: show the client window
655 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
656 if (!_fullscreen
) continue;
658 // XXX: lower the window to its proper layer
660 property
->atom(otk::OBProperty::net_wm_state_floating
)) {
661 if (!_floating
) continue;
663 // XXX: lower the window to its proper layer
670 void OBClient::toggleClientBorder(bool addborder
)
672 // adjust our idea of where the client is, based on its border. When the
673 // border is removed, the client should now be considered to be in a
674 // different position.
675 // when re-adding the border to the client, the same operation needs to be
677 int x
= _area
.x(), y
= _area
.y();
679 case NorthWestGravity
:
681 case SouthWestGravity
:
683 case NorthEastGravity
:
685 case SouthEastGravity
:
686 if (addborder
) x
-= _border_width
* 2;
687 else x
+= _border_width
* 2;
691 case NorthWestGravity
:
693 case NorthEastGravity
:
695 case SouthWestGravity
:
697 case SouthEastGravity
:
698 if (addborder
) y
-= _border_width
* 2;
699 else y
+= _border_width
* 2;
702 // no change for StaticGravity etc.
708 XSetWindowBorderWidth(otk::OBDisplay::display
, _window
, _border_width
);
710 // move the client so it is back it the right spot _with_ its border!
711 XMoveWindow(otk::OBDisplay::display
, _window
, x
, y
);
713 XSetWindowBorderWidth(otk::OBDisplay::display
, _window
, 0);
717 void OBClient::clientMessageHandler(const XClientMessageEvent
&e
)
719 otk::OtkEventHandler::clientMessageHandler(e
);
721 if (e
.format
!= 32) return;
723 const otk::OBProperty
*property
= Openbox::instance
->property();
725 if (e
.message_type
== property
->atom(otk::OBProperty::wm_change_state
)) {
726 // compress changes into a single change
727 bool compress
= false;
729 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
730 // XXX: it would be nice to compress ALL messages of a type, not just
731 // messages in a row without other message types between.
732 if (ce
.xclient
.message_type
!= e
.message_type
) {
733 XPutBackEvent(otk::OBDisplay::display
, &ce
);
739 setWMState(ce
.xclient
.data
.l
[0]); // use the found event
741 setWMState(e
.data
.l
[0]); // use the original event
742 } else if (e
.message_type
==
743 property
->atom(otk::OBProperty::net_wm_desktop
)) {
744 // compress changes into a single change
745 bool compress
= false;
747 while (XCheckTypedEvent(otk::OBDisplay::display
, e
.type
, &ce
)) {
748 // XXX: it would be nice to compress ALL messages of a type, not just
749 // messages in a row without other message types between.
750 if (ce
.xclient
.message_type
!= e
.message_type
) {
751 XPutBackEvent(otk::OBDisplay::display
, &ce
);
757 setDesktop(e
.data
.l
[0]); // use the found event
759 setDesktop(e
.data
.l
[0]); // use the original event
761 else if (e
.message_type
== property
->atom(otk::OBProperty::net_wm_state
))
762 // can't compress these
763 setState((StateAction
)e
.data
.l
[0], e
.data
.l
[1], e
.data
.l
[2]);
767 #if defined(SHAPE) || defined(DOXYGEN_IGNORE)
768 void OBClient::shapeHandler(const XShapeEvent
&e
)
770 otk::OtkEventHandler::shapeHandler(e
);
777 void OBClient::resize(Corner anchor
, int w
, int h
)
782 // for interactive resizing. have to move half an increment in each
784 w
+= _size_inc
.x() / 2;
785 h
+= _size_inc
.y() / 2;
787 // is the window resizable? if it is not, then don't check its sizes, the
788 // client can do what it wants and the user can't change it anyhow
789 if (_min_size
.x() <= _max_size
.x() && _min_size
.y() <= _max_size
.y()) {
790 // smaller than min size or bigger than max size?
791 if (w
< _min_size
.x()) w
= _min_size
.x();
792 else if (w
> _max_size
.x()) w
= _max_size
.x();
793 if (h
< _min_size
.y()) h
= _min_size
.y();
794 else if (h
> _max_size
.y()) h
= _max_size
.y();
797 // keep to the increments
801 // store the logical size
802 _logical_size
.setPoint(w
, h
);
810 int x
= _area
.x(), y
= _area
.y();
815 x
-= w
- _area
.width();
818 y
-= h
- _area
.height();
821 x
-= w
- _area
.width();
822 y
-= h
- _area
.height();
827 XResizeWindow(otk::OBDisplay::display
, _window
, w
, h
);
829 // resize the frame to match the request
835 void OBClient::move(int x
, int y
)
838 // move the frame to be in the requested position
839 frame
->adjustPosition();
843 void OBClient::close()
846 const otk::OBProperty
*property
= Openbox::instance
->property();
848 if (!(_functions
& Func_Close
)) return;
850 // XXX: itd be cool to do timeouts and shit here for killing the client's
853 ce
.xclient
.type
= ClientMessage
;
854 ce
.xclient
.message_type
= property
->atom(otk::OBProperty::wm_protocols
);
855 ce
.xclient
.display
= otk::OBDisplay::display
;
856 ce
.xclient
.window
= _window
;
857 ce
.xclient
.format
= 32;
858 ce
.xclient
.data
.l
[0] = property
->atom(otk::OBProperty::wm_delete_window
);
859 ce
.xclient
.data
.l
[1] = CurrentTime
;
860 ce
.xclient
.data
.l
[2] = 0l;
861 ce
.xclient
.data
.l
[3] = 0l;
862 ce
.xclient
.data
.l
[4] = 0l;
863 XSendEvent(otk::OBDisplay::display
, _window
, False
, NoEventMask
, &ce
);
867 bool OBClient::focus()
869 if (!_can_focus
|| _focused
) return false;
871 XSetInputFocus(otk::OBDisplay::display
, _window
, RevertToNone
, CurrentTime
);
876 void OBClient::unfocus()
878 if (!_focused
) return;
880 assert(Openbox::instance
->focusedClient() == this);
881 Openbox::instance
->setFocusedClient(0);
885 void OBClient::focusHandler(const XFocusChangeEvent
&e
)
888 printf("FocusIn for 0x%lx\n", e
.window
);
891 OtkEventHandler::focusHandler(e
);
896 Openbox::instance
->setFocusedClient(this);
900 void OBClient::unfocusHandler(const XFocusChangeEvent
&e
)
903 printf("FocusOut for 0x%lx\n", e
.window
);
906 OtkEventHandler::unfocusHandler(e
);
911 if (Openbox::instance
->focusedClient() == this) {
912 printf("UNFOCUSED!\n");
913 Openbox::instance
->setFocusedClient(this);
918 void OBClient::configureRequestHandler(const XConfigureRequestEvent
&e
)
921 printf("ConfigureRequest for 0x%lx\n", e
.window
);
924 OtkEventHandler::configureRequestHandler(e
);
926 // XXX: if we are iconic (or shaded? (fvwm does that)) ignore the event
928 if (e
.value_mask
& CWBorderWidth
)
929 _border_width
= e
.border_width
;
931 // resize, then move, as specified in the EWMH section 7.7
932 if (e
.value_mask
& (CWWidth
| CWHeight
)) {
933 int w
= (e
.value_mask
& CWWidth
) ? e
.width
: _area
.width();
934 int h
= (e
.value_mask
& CWHeight
) ? e
.height
: _area
.height();
938 case NorthEastGravity
:
942 case SouthWestGravity
:
946 case SouthEastGravity
:
947 corner
= BottomRight
;
949 default: // NorthWest, Static, etc
953 resize(corner
, w
, h
);
956 if (e
.value_mask
& (CWX
| CWY
)) {
957 int x
= (e
.value_mask
& CWX
) ? e
.x
: _area
.x();
958 int y
= (e
.value_mask
& CWY
) ? e
.y
: _area
.y();
962 if (e
.value_mask
& CWStackMode
) {
966 // XXX: lower the window
972 // XXX: raise the window
979 void OBClient::unmapHandler(const XUnmapEvent
&e
)
982 printf("UnmapNotify for 0x%lx\n", e
.window
);
990 OtkEventHandler::unmapHandler(e
);
992 // this deletes us etc
993 Openbox::instance
->screen(_screen
)->unmanageWindow(this);
997 void OBClient::destroyHandler(const XDestroyWindowEvent
&e
)
1000 printf("DestroyNotify for 0x%lx\n", e
.window
);
1003 OtkEventHandler::destroyHandler(e
);
1005 // this deletes us etc
1006 Openbox::instance
->screen(_screen
)->unmanageWindow(this);
1010 void OBClient::reparentHandler(const XReparentEvent
&e
)
1012 // this is when the client is first taken captive in the frame
1013 if (e
.parent
== frame
->plate()) return;
1016 printf("ReparentNotify for 0x%lx\n", e
.window
);
1019 OtkEventHandler::reparentHandler(e
);
1022 This event is quite rare and is usually handled in unmapHandler.
1023 However, if the window is unmapped when the reparent event occurs,
1024 the window manager never sees it because an unmap event is not sent
1025 to an already unmapped window.
1028 // this deletes us etc
1029 Openbox::instance
->screen(_screen
)->unmanageWindow(this);