X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fclient.cc;h=6b67f3c290aa9f1a3909169b84bb2fa2238f2de1;hb=37be3ef9249b452b8edec25a441aefff80c2d4b8;hp=9b26b3bf180ccac6eb71dd2d029b47c475b240b6;hpb=9df8ba78f3438f7ea63d9aef8121da969d5a1d9b;p=chaz%2Fopenbox diff --git a/src/client.cc b/src/client.cc index 9b26b3bf..6b67f3c2 100644 --- a/src/client.cc +++ b/src/client.cc @@ -27,13 +27,50 @@ OBClient::OBClient(Window window) // the state is kinda assumed to be normal. is this right? XXX _wmstate = NormalState; + // no default decors or functions, each has to be enabled + _decorations = _functions = 0; getArea(); getDesktop(); getType(); + + // set the decorations and functions + switch (_type) { + case Type_Normal: + // normal windows retain all of the possible decorations and + // functionality + _decorations = Decor_Titlebar | Decor_Handle | Decor_Border | + Decor_Iconify | Decor_Maximize; + _functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize; + + 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; + } + + getMwmHints(); // this fucks (in good ways) with the decors and functions getState(); getShaped(); + updateProtocols(); updateNormalHints(); updateWMHints(); // XXX: updateTransientFor(); @@ -170,12 +207,68 @@ void OBClient::getType() } +void OBClient::getMwmHints() +{ + const otk::OBProperty *property = Openbox::instance->property(); + + unsigned long num; + MwmHints *hints; + + num = MwmHints::elements; + if (!property->get(_window, otk::OBProperty::motif_wm_hints, + otk::OBProperty::motif_wm_hints, &num, + (unsigned long **)&hints)) + return; + + if (num < MwmHints::elements) { + delete [] hints; + return; + } + + // retrieved the hints + // Mwm Hints are applied subtractively to what has already been chosen for + // decor and functionality + + if (hints->flags & MwmFlag_Decorations) { + if (! (hints->decorations & MwmDecor_All)) { + if (! (hints->decorations & MwmDecor_Border)) + _decorations &= ~Decor_Border; + if (! (hints->decorations & MwmDecor_Handle)) + _decorations &= ~Decor_Handle; + if (! (hints->decorations & MwmDecor_Title)) + _decorations &= ~Decor_Titlebar; + if (! (hints->decorations & MwmDecor_Iconify)) + _decorations &= ~Decor_Iconify; + if (! (hints->decorations & MwmDecor_Maximize)) + _decorations &= ~Decor_Maximize; + } + } + + if (hints->flags & MwmFlag_Functions) { + if (! (hints->functions & MwmFunc_All)) { + if (! (hints->functions & MwmFunc_Resize)) + _functions &= ~Func_Resize; + if (! (hints->functions & MwmFunc_Move)) + _functions &= ~Func_Move; + if (! (hints->functions & MwmFunc_Iconify)) + _functions &= ~Func_Iconify; + if (! (hints->functions & MwmFunc_Maximize)) + _functions &= ~Func_Maximize; + //if (! (hints->functions & MwmFunc_Close)) + // _functions &= ~Func_Close; + } + } + delete [] hints; +} + + void OBClient::getArea() { XWindowAttributes wattrib; assert(XGetWindowAttributes(otk::OBDisplay::display, _window, &wattrib)); _area.setRect(wattrib.x, wattrib.y, wattrib.width, wattrib.height); + _border_width = wattrib.border_width; } @@ -227,6 +320,31 @@ void OBClient::getShaped() } +void OBClient::updateProtocols() +{ + const otk::OBProperty *property = Openbox::instance->property(); + + Atom *proto; + int num_return = 0; + + _focus_notify = false; + + 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; + // XXX: update the decor? + } 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); + } +} + + void OBClient::updateNormalHints() { XSizeHints size; @@ -239,6 +357,9 @@ void OBClient::updateNormalHints() _min_x = _min_y = 0; _max_x = _max_y = INT_MAX; + // XXX: might want to cancel any interactive resizing of the window at this + // point.. + // get the hints from the window if (XGetWMNormalHints(otk::OBDisplay::display, _window, &size, &ret)) { _positioned = (size.flags & (PPosition|USPosition)); @@ -351,7 +472,10 @@ void OBClient::update(const XPropertyEvent &e) updateTitle(); else if (e.atom == property->atom(otk::OBProperty::wm_class)) updateClass(); + else if (e.atom == property->atom(otk::OBProperty::wm_protocols)) + updateProtocols(); // XXX: transient for hint + // XXX: strut hint }