+ const otk::OBProperty *property = Openbox::instance->property();
+
+ // clean up parents reference to this
+ if (_transient_for)
+ _transient_for->_transients.remove(this); // remove from old parent
+
+ if (Openbox::instance->state() != Openbox::State_Exiting) {
+ // these values should not be persisted across a window unmapping/mapping
+ property->erase(_window, otk::OBProperty::net_wm_desktop);
+ property->erase(_window, otk::OBProperty::net_wm_state);
+ }
+}
+
+
+void OBClient::getDesktop()
+{
+ const otk::OBProperty *property = Openbox::instance->property();
+
+ // defaults to the current desktop
+ _desktop = Openbox::instance->screen(_screen)->desktop();
+
+ if (!property->get(_window, otk::OBProperty::net_wm_desktop,
+ otk::OBProperty::Atom_Cardinal,
+ (long unsigned*)&_desktop)) {
+ // make sure the hint exists
+ Openbox::instance->property()->set(_window,
+ otk::OBProperty::net_wm_desktop,
+ otk::OBProperty::Atom_Cardinal,
+ (unsigned)_desktop);
+ }
+}
+
+
+void OBClient::getType()
+{
+ const otk::OBProperty *property = Openbox::instance->property();
+
+ _type = (WindowType) -1;
+
+ unsigned long *val;
+ unsigned long num = (unsigned) -1;
+ if (property->get(_window, otk::OBProperty::net_wm_window_type,
+ otk::OBProperty::Atom_Atom,
+ &num, &val)) {
+ // use the first value that we know about in the array
+ for (unsigned long i = 0; i < num; ++i) {
+ if (val[i] ==
+ property->atom(otk::OBProperty::net_wm_window_type_desktop))
+ _type = Type_Desktop;
+ else if (val[i] ==
+ property->atom(otk::OBProperty::net_wm_window_type_dock))
+ _type = Type_Dock;
+ else if (val[i] ==
+ property->atom(otk::OBProperty::net_wm_window_type_toolbar))
+ _type = Type_Toolbar;
+ else if (val[i] ==
+ property->atom(otk::OBProperty::net_wm_window_type_menu))
+ _type = Type_Menu;
+ else if (val[i] ==
+ property->atom(otk::OBProperty::net_wm_window_type_utility))
+ _type = Type_Utility;
+ else if (val[i] ==
+ property->atom(otk::OBProperty::net_wm_window_type_splash))
+ _type = Type_Splash;
+ else if (val[i] ==
+ property->atom(otk::OBProperty::net_wm_window_type_dialog))
+ _type = Type_Dialog;
+ else if (val[i] ==
+ property->atom(otk::OBProperty::net_wm_window_type_normal))
+ _type = Type_Normal;
+// else if (val[i] ==
+// property->atom(otk::OBProperty::kde_net_wm_window_type_override))
+// mwm_decorations = 0; // prevent this window from getting any decor
+ // XXX: make this work again
+ if (_type != (WindowType) -1)
+ break; // grab the first known type
+ }
+ delete val;
+ }
+
+ if (_type == (WindowType) -1) {
+ /*
+ * the window type hint was not set, which means we either classify ourself
+ * as a normal window or a dialog, depending on if we are a transient.
+ */
+ if (_transient_for)
+ _type = Type_Dialog;
+ else
+ _type = Type_Normal;
+ }
+}
+
+
+void OBClient::setupDecorAndFunctions()
+{
+ // start with everything
+ _decorations = Decor_Titlebar | Decor_Handle | Decor_Border |
+ Decor_Iconify | Decor_Maximize;
+ _functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
+
+ switch (_type) {
+ case Type_Normal:
+ // normal windows retain all of the possible decorations and
+ // functionality
+
+ case Type_Dialog:
+ // dialogs cannot be maximized
+ _decorations &= ~Decor_Maximize;
+ _functions &= ~Func_Maximize;
+ break;
+
+ case Type_Menu:
+ case Type_Toolbar:
+ case Type_Utility:
+ // these windows get less functionality
+ _decorations &= ~(Decor_Iconify | Decor_Handle);
+ _functions &= ~(Func_Iconify | Func_Resize);
+ break;
+
+ case Type_Desktop:
+ case Type_Dock:
+ case Type_Splash:
+ // none of these windows are manipulated by the window manager
+ _decorations = 0;
+ _functions = 0;
+ break;
+ }
+
+ // Mwm Hints are applied subtractively to what has already been chosen for
+ // decor and functionality
+ if (_mwmhints.flags & MwmFlag_Decorations) {
+ if (! (_mwmhints.decorations & MwmDecor_All)) {
+ if (! (_mwmhints.decorations & MwmDecor_Border))
+ _decorations &= ~Decor_Border;
+ if (! (_mwmhints.decorations & MwmDecor_Handle))
+ _decorations &= ~Decor_Handle;
+ if (! (_mwmhints.decorations & MwmDecor_Title))
+ _decorations &= ~Decor_Titlebar;
+ if (! (_mwmhints.decorations & MwmDecor_Iconify))
+ _decorations &= ~Decor_Iconify;
+ if (! (_mwmhints.decorations & MwmDecor_Maximize))
+ _decorations &= ~Decor_Maximize;
+ }
+ }
+
+ if (_mwmhints.flags & MwmFlag_Functions) {
+ if (! (_mwmhints.functions & MwmFunc_All)) {
+ if (! (_mwmhints.functions & MwmFunc_Resize))
+ _functions &= ~Func_Resize;
+ if (! (_mwmhints.functions & MwmFunc_Move))
+ _functions &= ~Func_Move;
+ if (! (_mwmhints.functions & MwmFunc_Iconify))
+ _functions &= ~Func_Iconify;
+ if (! (_mwmhints.functions & MwmFunc_Maximize))
+ _functions &= ~Func_Maximize;
+ // dont let mwm hints kill the close button
+ //if (! (_mwmhints.functions & MwmFunc_Close))
+ // _functions &= ~Func_Close;
+ }
+ }
+
+ // XXX: changeAllowedActions();
+}
+
+
+void OBClient::getMwmHints()
+{
+ const otk::OBProperty *property = Openbox::instance->property();
+
+ unsigned long num = MwmHints::elements;
+ unsigned long *hints;
+
+ _mwmhints.flags = 0; // default to none
+
+ if (!property->get(_window, otk::OBProperty::motif_wm_hints,
+ otk::OBProperty::motif_wm_hints, &num,
+ (unsigned long **)&hints))
+ return;
+
+ if (num >= MwmHints::elements) {
+ // retrieved the hints
+ _mwmhints.flags = hints[0];
+ _mwmhints.functions = hints[1];
+ _mwmhints.decorations = hints[2];
+ }
+
+ delete [] hints;
+}
+
+
+void OBClient::getArea()
+{
+ XWindowAttributes wattrib;
+ Status ret;
+
+ ret = XGetWindowAttributes(otk::OBDisplay::display, _window, &wattrib);
+ assert(ret != BadWindow);
+
+ _area.setRect(wattrib.x, wattrib.y, wattrib.width, wattrib.height);
+ _border_width = wattrib.border_width;
+}
+
+
+void OBClient::getState()
+{
+ const otk::OBProperty *property = Openbox::instance->property();
+
+ _modal = _shaded = _max_horz = _max_vert = _fullscreen = _above = _below =
+ _skip_taskbar = _skip_pager = false;
+
+ unsigned long *state;
+ unsigned long num = (unsigned) -1;
+
+ if (property->get(_window, otk::OBProperty::net_wm_state,
+ otk::OBProperty::Atom_Atom, &num, &state)) {
+ for (unsigned long i = 0; i < num; ++i) {
+ if (state[i] == property->atom(otk::OBProperty::net_wm_state_modal))
+ _modal = true;
+ else if (state[i] ==
+ property->atom(otk::OBProperty::net_wm_state_shaded)) {
+ _shaded = true;
+ _wmstate = IconicState;
+ } else if (state[i] ==
+ property->atom(otk::OBProperty::net_wm_state_skip_taskbar))
+ _skip_taskbar = true;
+ else if (state[i] ==
+ property->atom(otk::OBProperty::net_wm_state_skip_pager))
+ _skip_pager = true;
+ else if (state[i] ==
+ property->atom(otk::OBProperty::net_wm_state_fullscreen))
+ _fullscreen = true;
+ else if (state[i] ==
+ property->atom(otk::OBProperty::net_wm_state_maximized_vert))
+ _max_vert = true;
+ else if (state[i] ==
+ property->atom(otk::OBProperty::net_wm_state_maximized_horz))
+ _max_horz = true;
+ else if (state[i] ==
+ property->atom(otk::OBProperty::net_wm_state_above))
+ _above = true;
+ else if (state[i] ==
+ property->atom(otk::OBProperty::net_wm_state_below))
+ _below = true;
+ }
+
+ delete [] state;
+ }
+}
+
+
+void OBClient::getShaped()
+{
+ _shaped = false;
+#ifdef SHAPE
+ if (otk::OBDisplay::shape()) {
+ int foo;
+ unsigned int ufoo;
+ int s;
+
+ XShapeSelectInput(otk::OBDisplay::display, _window, ShapeNotifyMask);
+
+ XShapeQueryExtents(otk::OBDisplay::display, _window, &s, &foo,
+ &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo);
+ _shaped = (s != 0);
+ }
+#endif // SHAPE
+}
+
+
+void OBClient::calcLayer() {
+ StackLayer l;
+
+ if (_iconic) l = Layer_Icon;
+ else if (_fullscreen) l = Layer_Fullscreen;
+ else if (_type == Type_Desktop) l = Layer_Desktop;
+ else if (_type == Type_Dock) {
+ if (!_below) l = Layer_Top;
+ else l = Layer_Normal;
+ }
+ else if (_above) l = Layer_Above;
+ else if (_below) l = Layer_Below;
+ else l = Layer_Normal;
+
+ if (l != _layer) {
+ _layer = l;
+ if (frame) {
+ /*
+ if we don't have a frame, then we aren't mapped yet (and this would
+ SIGSEGV :)
+ */
+ Openbox::instance->screen(_screen)->restack(true, this); // raise
+ }
+ }
+}
+
+
+void OBClient::updateProtocols()
+{
+ const otk::OBProperty *property = Openbox::instance->property();
+
+ Atom *proto;
+ int num_return = 0;
+
+ _focus_notify = false;
+ _decorations &= ~Decor_Close;
+ _functions &= ~Func_Close;
+
+ if (XGetWMProtocols(otk::OBDisplay::display, _window, &proto, &num_return)) {
+ for (int i = 0; i < num_return; ++i) {
+ if (proto[i] == property->atom(otk::OBProperty::wm_delete_window)) {
+ _decorations |= Decor_Close;
+ _functions |= Func_Close;
+ if (frame)
+ frame->adjustSize(); // update the decorations
+ } else if (proto[i] == property->atom(otk::OBProperty::wm_take_focus))
+ // if this protocol is requested, then the window will be notified
+ // by the window manager whenever it receives focus
+ _focus_notify = true;
+ }
+ XFree(proto);
+ }