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 =
252 _skip_taskbar = _skip_pager = false;
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_skip_taskbar))
267 _skip_taskbar = true;
269 property->atom(otk::OBProperty::net_wm_state_skip_pager))
272 property->atom(otk::OBProperty::net_wm_state_fullscreen))
275 property->atom(otk::OBProperty::net_wm_state_maximized_vert))
278 property->atom(otk::OBProperty::net_wm_state_maximized_horz))
281 property->atom(otk::OBProperty::net_wm_state_above))
284 property->atom(otk::OBProperty::net_wm_state_below))
293 void OBClient::getShaped()
297 if (otk::OBDisplay::shape()) {
302 XShapeSelectInput(otk::OBDisplay::display, _window, ShapeNotifyMask);
304 XShapeQueryExtents(otk::OBDisplay::display, _window, &s, &foo,
305 &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo);
312 void OBClient::calcLayer() {
313 if (_iconic) _layer = OBScreen::Layer_Icon;
314 else if (_type == Type_Desktop) _layer = OBScreen::Layer_Desktop;
315 else if (_type == Type_Dock) _layer = OBScreen::Layer_Top;
316 else if (_fullscreen) _layer = OBScreen::Layer_Fullscreen;
317 else if (_above) _layer = OBScreen::Layer_Above;
318 else if (_below) _layer = OBScreen::Layer_Below;
319 else _layer = OBScreen::Layer_Normal;
323 void OBClient::updateProtocols()
325 const otk::OBProperty *property = Openbox::instance->property();
330 _focus_notify = false;
331 _decorations &= ~Decor_Close;
332 _functions &= ~Func_Close;
334 if (XGetWMProtocols(otk::OBDisplay::display, _window, &proto, &num_return)) {
335 for (int i = 0; i < num_return; ++i) {
336 if (proto[i] == property->atom(otk::OBProperty::wm_delete_window)) {
337 _decorations |= Decor_Close;
338 _functions |= Func_Close;
339 // XXX: update the decor?
340 } else if (proto[i] == property->atom(otk::OBProperty::wm_take_focus))
341 // if this protocol is requested, then the window will be notified
342 // by the window manager whenever it receives focus
343 _focus_notify = true;
350 void OBClient::updateNormalHints()
354 int oldgravity = _gravity;
357 _gravity = NorthWestGravity;
358 _size_inc.setPoint(1, 1);
359 _base_size.setPoint(0, 0);
360 _min_size.setPoint(0, 0);
361 _max_size.setPoint(INT_MAX, INT_MAX);
363 // XXX: might want to cancel any interactive resizing of the window at this
366 // get the hints from the window
367 if (XGetWMNormalHints(otk::OBDisplay::display, _window, &size, &ret)) {
368 _positioned = (size.flags & (PPosition|USPosition));
370 if (size.flags & PWinGravity)
371 _gravity = size.win_gravity;
373 if (size.flags & PMinSize)
374 _min_size.setPoint(size.min_width, size.min_height);
376 if (size.flags & PMaxSize)
377 _max_size.setPoint(size.max_width, size.max_height);
379 if (size.flags & PBaseSize)
380 _base_size.setPoint(size.base_width, size.base_height);
382 if (size.flags & PResizeInc)
383 _size_inc.setPoint(size.width_inc, size.height_inc);
386 // if the client has a frame, i.e. has already been mapped and is
387 // changing its gravity
388 if (frame && _gravity != oldgravity) {
389 // move our idea of the client's position based on its new gravity
391 frame->frameGravity(x, y);
397 void OBClient::updateWMHints()
401 // assume a window takes input if it doesnt specify
405 if ((hints = XGetWMHints(otk::OBDisplay::display, _window)) != NULL) {
406 if (hints->flags & InputHint)
407 _can_focus = hints->input;
409 if (hints->flags & XUrgencyHint)
412 if (hints->flags & WindowGroupHint) {
413 if (hints->window_group != _group) {
414 // XXX: remove from the old group if there was one
415 _group = hints->window_group;
416 // XXX: do stuff with the group
426 void OBClient::updateTitle()
428 const otk::OBProperty *property = Openbox::instance->property();
433 if (! property->get(_window, otk::OBProperty::net_wm_name,
434 otk::OBProperty::utf8, &_title)) {
436 property->get(_window, otk::OBProperty::wm_name,
437 otk::OBProperty::ascii, &_title);
441 _title = _("Unnamed Window");
444 frame->setTitle(_title);
448 void OBClient::updateIconTitle()
450 const otk::OBProperty *property = Openbox::instance->property();
455 if (! property->get(_window, otk::OBProperty::net_wm_icon_name,
456 otk::OBProperty::utf8, &_icon_title)) {
458 property->get(_window, otk::OBProperty::wm_icon_name,
459 otk::OBProperty::ascii, &_icon_title);
463 _icon_title = _("Unnamed Window");
467 void OBClient::updateClass()
469 const otk::OBProperty *property = Openbox::instance->property();
472 _app_name = _app_class = "";
474 otk::OBProperty::StringVect v;
475 unsigned long num = 2;
477 if (! property->get(_window, otk::OBProperty::wm_class,
478 otk::OBProperty::ascii, &num, &v))
481 if (num > 0) _app_name = v[0];
482 if (num > 1) _app_class = v[1];
486 void OBClient::propertyHandler(const XPropertyEvent &e)
488 otk::OtkEventHandler::propertyHandler(e);
490 const otk::OBProperty *property = Openbox::instance->property();
492 // compress changes to a single property into a single change
494 while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) {
495 // XXX: it would be nice to compress ALL changes to a property, not just
496 // changes in a row without other props between.
497 if (ce.xproperty.atom != e.atom) {
498 XPutBackEvent(otk::OBDisplay::display, &ce);
503 if (e.atom == XA_WM_NORMAL_HINTS)
505 else if (e.atom == XA_WM_HINTS)
507 else if (e.atom == property->atom(otk::OBProperty::net_wm_name) ||
508 e.atom == property->atom(otk::OBProperty::wm_name))
510 else if (e.atom == property->atom(otk::OBProperty::net_wm_icon_name) ||
511 e.atom == property->atom(otk::OBProperty::wm_icon_name))
513 else if (e.atom == property->atom(otk::OBProperty::wm_class))
515 else if (e.atom == property->atom(otk::OBProperty::wm_protocols))
517 // XXX: transient for hint
522 void OBClient::setWMState(long state)
524 if (state == _wmstate) return; // no change
528 // XXX: cause it to iconify
531 // XXX: cause it to uniconify
538 void OBClient::setDesktop(long target)
541 //assert(target == 0xffffffff || target < MAX);
543 // XXX: move the window to the new desktop
548 void OBClient::setState(StateAction action, long data1, long data2)
550 const otk::OBProperty *property = Openbox::instance->property();
552 if (!(action == State_Add || action == State_Remove ||
553 action == State_Toggle))
554 return; // an invalid action was passed to the client message, ignore it
556 for (int i = 0; i < 2; ++i) {
557 Atom state = i == 0 ? data1 : data2;
559 if (! state) continue;
561 // if toggling, then pick whether we're adding or removing
562 if (action == State_Toggle) {
563 if (state == property->atom(otk::OBProperty::net_wm_state_modal))
564 action = _modal ? State_Remove : State_Add;
566 property->atom(otk::OBProperty::net_wm_state_maximized_vert))
567 action = _max_vert ? State_Remove : State_Add;
569 property->atom(otk::OBProperty::net_wm_state_maximized_horz))
570 action = _max_horz ? State_Remove : State_Add;
571 else if (state == property->atom(otk::OBProperty::net_wm_state_shaded))
572 action = _shaded ? State_Remove : State_Add;
574 property->atom(otk::OBProperty::net_wm_state_skip_taskbar))
575 action = _skip_taskbar ? State_Remove : State_Add;
577 property->atom(otk::OBProperty::net_wm_state_skip_pager))
578 action = _skip_pager ? State_Remove : State_Add;
580 property->atom(otk::OBProperty::net_wm_state_fullscreen))
581 action = _fullscreen ? State_Remove : State_Add;
582 else if (state == property->atom(otk::OBProperty::net_wm_state_above))
583 action = _above ? State_Remove : State_Add;
584 else if (state == property->atom(otk::OBProperty::net_wm_state_below))
585 action = _below ? State_Remove : State_Add;
588 if (action == State_Add) {
589 if (state == property->atom(otk::OBProperty::net_wm_state_modal)) {
590 if (_modal) continue;
592 // XXX: give it focus if another window has focus that shouldnt now
594 property->atom(otk::OBProperty::net_wm_state_maximized_vert)){
595 if (_max_vert) continue;
597 // XXX: resize the window etc
599 property->atom(otk::OBProperty::net_wm_state_maximized_horz)){
600 if (_max_horz) continue;
602 // XXX: resize the window etc
604 property->atom(otk::OBProperty::net_wm_state_shaded)) {
605 if (_shaded) continue;
607 // XXX: hide the client window
609 property->atom(otk::OBProperty::net_wm_state_skip_taskbar)) {
610 _skip_taskbar = true;
612 property->atom(otk::OBProperty::net_wm_state_skip_pager)) {
615 property->atom(otk::OBProperty::net_wm_state_fullscreen)) {
616 if (_fullscreen) continue;
618 // XXX: raise the window n shit
620 property->atom(otk::OBProperty::net_wm_state_above)) {
621 if (_above) continue;
623 // XXX: raise the window n shit
625 property->atom(otk::OBProperty::net_wm_state_below)) {
626 if (_below) continue;
628 // XXX: lower the window n shit
631 } else { // action == State_Remove
632 if (state == property->atom(otk::OBProperty::net_wm_state_modal)) {
633 if (!_modal) continue;
636 property->atom(otk::OBProperty::net_wm_state_maximized_vert)){
637 if (!_max_vert) continue;
639 // XXX: resize the window etc
641 property->atom(otk::OBProperty::net_wm_state_maximized_horz)){
642 if (!_max_horz) continue;
644 // XXX: resize the window etc
646 property->atom(otk::OBProperty::net_wm_state_shaded)) {
647 if (!_shaded) continue;
649 // XXX: show the client window
651 property->atom(otk::OBProperty::net_wm_state_skip_taskbar)) {
652 _skip_taskbar = false;
654 property->atom(otk::OBProperty::net_wm_state_skip_pager)) {
657 property->atom(otk::OBProperty::net_wm_state_fullscreen)) {
658 if (!_fullscreen) continue;
660 // XXX: lower the window to its proper layer
662 property->atom(otk::OBProperty::net_wm_state_above)) {
663 if (!_above) continue;
665 // XXX: lower the window to its proper layer
667 property->atom(otk::OBProperty::net_wm_state_below)) {
668 if (!_below) continue;
670 // XXX: raise the window to its proper layer
675 Openbox::instance->screen(_screen)->restack(true, this); // raise
679 void OBClient::toggleClientBorder(bool addborder)
681 // adjust our idea of where the client is, based on its border. When the
682 // border is removed, the client should now be considered to be in a
683 // different position.
684 // when re-adding the border to the client, the same operation needs to be
686 int x = _area.x(), y = _area.y();
688 case NorthWestGravity:
690 case SouthWestGravity:
692 case NorthEastGravity:
694 case SouthEastGravity:
695 if (addborder) x -= _border_width * 2;
696 else x += _border_width * 2;
700 case NorthWestGravity:
702 case NorthEastGravity:
704 case SouthWestGravity:
706 case SouthEastGravity:
707 if (addborder) y -= _border_width * 2;
708 else y += _border_width * 2;
711 // no change for StaticGravity etc.
717 XSetWindowBorderWidth(otk::OBDisplay::display, _window, _border_width);
719 // move the client so it is back it the right spot _with_ its border!
720 XMoveWindow(otk::OBDisplay::display, _window, x, y);
722 XSetWindowBorderWidth(otk::OBDisplay::display, _window, 0);
726 void OBClient::clientMessageHandler(const XClientMessageEvent &e)
728 otk::OtkEventHandler::clientMessageHandler(e);
730 if (e.format != 32) return;
732 const otk::OBProperty *property = Openbox::instance->property();
734 if (e.message_type == property->atom(otk::OBProperty::wm_change_state)) {
735 // compress changes into a single change
736 bool compress = false;
738 while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) {
739 // XXX: it would be nice to compress ALL messages of a type, not just
740 // messages in a row without other message types between.
741 if (ce.xclient.message_type != e.message_type) {
742 XPutBackEvent(otk::OBDisplay::display, &ce);
748 setWMState(ce.xclient.data.l[0]); // use the found event
750 setWMState(e.data.l[0]); // use the original event
751 } else if (e.message_type ==
752 property->atom(otk::OBProperty::net_wm_desktop)) {
753 // compress changes into a single change
754 bool compress = false;
756 while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) {
757 // XXX: it would be nice to compress ALL messages of a type, not just
758 // messages in a row without other message types between.
759 if (ce.xclient.message_type != e.message_type) {
760 XPutBackEvent(otk::OBDisplay::display, &ce);
766 setDesktop(e.data.l[0]); // use the found event
768 setDesktop(e.data.l[0]); // use the original event
770 else if (e.message_type == property->atom(otk::OBProperty::net_wm_state))
771 // can't compress these
772 setState((StateAction)e.data.l[0], e.data.l[1], e.data.l[2]);
776 #if defined(SHAPE) || defined(DOXYGEN_IGNORE)
777 void OBClient::shapeHandler(const XShapeEvent &e)
779 otk::OtkEventHandler::shapeHandler(e);
786 void OBClient::resize(Corner anchor, int w, int h)
791 // for interactive resizing. have to move half an increment in each
793 w += _size_inc.x() / 2;
794 h += _size_inc.y() / 2;
796 // is the window resizable? if it is not, then don't check its sizes, the
797 // client can do what it wants and the user can't change it anyhow
798 if (_min_size.x() <= _max_size.x() && _min_size.y() <= _max_size.y()) {
799 // smaller than min size or bigger than max size?
800 if (w < _min_size.x()) w = _min_size.x();
801 else if (w > _max_size.x()) w = _max_size.x();
802 if (h < _min_size.y()) h = _min_size.y();
803 else if (h > _max_size.y()) h = _max_size.y();
806 // keep to the increments
810 // store the logical size
811 _logical_size.setPoint(w, h);
819 int x = _area.x(), y = _area.y();
824 x -= w - _area.width();
827 y -= h - _area.height();
830 x -= w - _area.width();
831 y -= h - _area.height();
836 XResizeWindow(otk::OBDisplay::display, _window, w, h);
838 // resize the frame to match the request
844 void OBClient::move(int x, int y)
847 // move the frame to be in the requested position
848 frame->adjustPosition();
852 void OBClient::close()
855 const otk::OBProperty *property = Openbox::instance->property();
857 if (!(_functions & Func_Close)) return;
859 // XXX: itd be cool to do timeouts and shit here for killing the client's
862 ce.xclient.type = ClientMessage;
863 ce.xclient.message_type = property->atom(otk::OBProperty::wm_protocols);
864 ce.xclient.display = otk::OBDisplay::display;
865 ce.xclient.window = _window;
866 ce.xclient.format = 32;
867 ce.xclient.data.l[0] = property->atom(otk::OBProperty::wm_delete_window);
868 ce.xclient.data.l[1] = CurrentTime;
869 ce.xclient.data.l[2] = 0l;
870 ce.xclient.data.l[3] = 0l;
871 ce.xclient.data.l[4] = 0l;
872 XSendEvent(otk::OBDisplay::display, _window, False, NoEventMask, &ce);
876 void OBClient::changeState()
878 const otk::OBProperty *property = Openbox::instance->property();
880 unsigned long state[2];
883 property->set(_window, otk::OBProperty::wm_state, otk::OBProperty::wm_state,
889 netstate[num++] = property->atom(otk::OBProperty::net_wm_state_modal);
891 netstate[num++] = property->atom(otk::OBProperty::net_wm_state_shaded);
893 netstate[num++] = property->atom(otk::OBProperty::net_wm_state_hidden);
896 property->atom(otk::OBProperty::net_wm_state_skip_taskbar);
898 netstate[num++] = property->atom(otk::OBProperty::net_wm_state_skip_pager);
900 netstate[num++] = property->atom(otk::OBProperty::net_wm_state_fullscreen);
903 property->atom(otk::OBProperty::net_wm_state_maximized_vert);
906 property->atom(otk::OBProperty::net_wm_state_maximized_horz);
908 netstate[num++] = property->atom(otk::OBProperty::net_wm_state_above);
910 netstate[num++] = property->atom(otk::OBProperty::net_wm_state_below);
911 property->set(_window, otk::OBProperty::net_wm_state,
912 otk::OBProperty::Atom_Atom, netstate, num);
916 void OBClient::shade(bool shade)
918 if (shade == _shaded) return; // already done
920 _wmstate = shade ? IconicState : NormalState;
927 bool OBClient::focus()
929 if (!_can_focus || _focused) return false;
931 XSetInputFocus(otk::OBDisplay::display, _window, RevertToNone, CurrentTime);
936 void OBClient::unfocus()
938 if (!_focused) return;
940 assert(Openbox::instance->focusedClient() == this);
941 Openbox::instance->setFocusedClient(0);
945 void OBClient::focusHandler(const XFocusChangeEvent &e)
948 printf("FocusIn for 0x%lx\n", e.window);
951 OtkEventHandler::focusHandler(e);
956 Openbox::instance->setFocusedClient(this);
960 void OBClient::unfocusHandler(const XFocusChangeEvent &e)
963 printf("FocusOut for 0x%lx\n", e.window);
966 OtkEventHandler::unfocusHandler(e);
971 if (Openbox::instance->focusedClient() == this) {
972 printf("UNFOCUSED!\n");
973 Openbox::instance->setFocusedClient(this);
978 void OBClient::configureRequestHandler(const XConfigureRequestEvent &e)
981 printf("ConfigureRequest for 0x%lx\n", e.window);
984 OtkEventHandler::configureRequestHandler(e);
986 // XXX: if we are iconic (or shaded? (fvwm does that)) ignore the event
988 if (e.value_mask & CWBorderWidth)
989 _border_width = e.border_width;
991 // resize, then move, as specified in the EWMH section 7.7
992 if (e.value_mask & (CWWidth | CWHeight)) {
993 int w = (e.value_mask & CWWidth) ? e.width : _area.width();
994 int h = (e.value_mask & CWHeight) ? e.height : _area.height();
998 case NorthEastGravity:
1002 case SouthWestGravity:
1004 corner = BottomLeft;
1006 case SouthEastGravity:
1007 corner = BottomRight;
1009 default: // NorthWest, Static, etc
1013 resize(corner, w, h);
1016 if (e.value_mask & (CWX | CWY)) {
1017 int x = (e.value_mask & CWX) ? e.x : _area.x();
1018 int y = (e.value_mask & CWY) ? e.y : _area.y();
1022 if (e.value_mask & CWStackMode) {
1026 // XXX: lower the window
1032 // XXX: raise the window
1039 void OBClient::unmapHandler(const XUnmapEvent &e)
1042 printf("UnmapNotify for 0x%lx\n", e.window);
1045 if (ignore_unmaps) {
1050 OtkEventHandler::unmapHandler(e);
1052 // this deletes us etc
1053 Openbox::instance->screen(_screen)->unmanageWindow(this);
1057 void OBClient::destroyHandler(const XDestroyWindowEvent &e)
1060 printf("DestroyNotify for 0x%lx\n", e.window);
1063 OtkEventHandler::destroyHandler(e);
1065 // this deletes us etc
1066 Openbox::instance->screen(_screen)->unmanageWindow(this);
1070 void OBClient::reparentHandler(const XReparentEvent &e)
1072 // this is when the client is first taken captive in the frame
1073 if (e.parent == frame->plate()) return;
1076 printf("ReparentNotify for 0x%lx\n", e.window);
1079 OtkEventHandler::reparentHandler(e);
1082 This event is quite rare and is usually handled in unmapHandler.
1083 However, if the window is unmapped when the reparent event occurs,
1084 the window manager never sees it because an unmap event is not sent
1085 to an already unmapped window.
1088 // this deletes us etc
1089 Openbox::instance->screen(_screen)->unmanageWindow(this);