_layer = Layer_Normal;
// default to not urgent
_urgent = false;
+ // not positioned unless specified
+ _positioned = false;
+ // nothing is disabled unless specified
+ _disabled_decorations = 0;
getArea();
getDesktop();
updateProtocols();
- // got the type, the mwmhints, and the protocols, so we're ready to set up
+ getGravity(); // get the attribute gravity
+ updateNormalHints(); // this may override the attribute gravity
+
+ // got the type, the mwmhints, the protocols, and the normal hints (min/max
+ // sizes), so we're ready to set up
// the decorations/functions
setupDecorAndFunctions();
- getGravity(); // get the attribute gravity
- updateNormalHints(); // this may override the attribute gravity
// also get the initial_state and set _iconic if we aren't "starting"
// when we're "starting" that means we should use whatever state was already
// on the window over the initial map state, because it was already mapped
}
+bool Client::validate() const
+{
+ XSync(**otk::display, false); // get all events on the server
+
+ XEvent e;
+ if (XCheckTypedWindowEvent(**otk::display, _window, DestroyNotify, &e) ||
+ XCheckTypedWindowEvent(**otk::display, _window, UnmapNotify, &e)) {
+ XPutBackEvent(**otk::display, &e);
+ return false;
+ }
+
+ return true;
+}
+
+
void Client::getGravity()
{
XWindowAttributes wattrib;
_functions |= Func_Close;
}
- if (_min_size.x() > _max_size.x() || _min_size.y() > _max_size.y()) {
- _decorations &= ~Decor_Maximize;
+ if (!(_min_size.x() < _max_size.x() || _min_size.y() < _max_size.y())) {
+ _decorations &= ~(Decor_Maximize | Decor_Handle);
_functions &= ~(Func_Resize | Func_Maximize);
}
}
}
+ // finally, user specified disabled decorations are applied to subtract
+ // decorations
+ if (_disabled_decorations & Decor_Titlebar)
+ _decorations &= ~Decor_Titlebar;
+ if (_disabled_decorations & Decor_Handle)
+ _decorations &= ~Decor_Handle;
+ if (_disabled_decorations & Decor_Border)
+ _decorations &= ~Decor_Border;
+ if (_disabled_decorations & Decor_Iconify)
+ _decorations &= ~Decor_Iconify;
+ if (_disabled_decorations & Decor_Maximize)
+ _decorations &= ~Decor_Maximize;
+ if (_disabled_decorations & Decor_AllDesktops)
+ _decorations &= ~Decor_AllDesktops;
+ if (_disabled_decorations & Decor_Close)
+ _decorations &= ~Decor_Close;
+
+ // You can't shade without a titlebar
+ if (!(_decorations & Decor_Titlebar))
+ _functions &= ~Func_Shade;
+
changeAllowedActions();
+
+ if (frame) {
+ frame->adjustSize(); // change the decors on the frame
+ frame->adjustPosition(); // with more/less decorations, we may need to be
+ // moved
+ }
}
_strut.right = data[1];
_strut.top = data[2];
_strut.bottom = data[3];
-
- openbox->screen(_screen)->updateStrut();
+
+ // updating here is pointless while we're being mapped cuz we're not in
+ // the screen's client list yet
+ if (frame)
+ openbox->screen(_screen)->updateStrut();
}
delete [] data;
void Client::propertyHandler(const XPropertyEvent &e)
{
otk::EventHandler::propertyHandler(e);
+
+ // validate cuz we query stuff off the client here
+ if (!validate()) return;
// compress changes to a single property into a single change
XEvent ce;
getType();
calcLayer(); // type may have changed, so update the layer
setupDecorAndFunctions();
- frame->adjustSize(); // this updates the frame for any new decor settings
}
else if (e.atom == otk::Property::atoms.net_wm_name ||
e.atom == otk::Property::atoms.wm_name)
else if (e.atom == otk::Property::atoms.wm_protocols) {
updateProtocols();
setupDecorAndFunctions();
- frame->adjustSize(); // update the decorations
}
else if (e.atom == otk::Property::atoms.net_wm_strut)
updateStrut();
if (shadestate != _shaded)
shade(shadestate);
calcLayer();
+ changeState(); // change the hint to relect these changes
}
// different position.
// when re-adding the border to the client, the same operation needs to be
// reversed.
- int x = _area.x(), y = _area.y();
+ int oldx = _area.x(), oldy = _area.y();
+ int x = oldx, y = oldy;
switch(_gravity) {
default:
case NorthWestGravity:
XSetWindowBorderWidth(**otk::display, _window, _border_width);
// move the client so it is back it the right spot _with_ its border!
- XMoveWindow(**otk::display, _window, x, y);
+ if (x != oldx || y != oldy)
+ XMoveWindow(**otk::display, _window, x, y);
} else
XSetWindowBorderWidth(**otk::display, _window, 0);
}
{
otk::EventHandler::clientMessageHandler(e);
+ // validate cuz we query stuff off the client here
+ if (!validate()) return;
+
if (e.format != 32) return;
if (e.message_type == otk::Property::atoms.wm_change_state) {
event.xconfigure.display = **otk::display;
event.xconfigure.event = _window;
event.xconfigure.window = _window;
- event.xconfigure.x = x;
- event.xconfigure.y = y;
+
+ // root window coords with border in mind
+ event.xconfigure.x = x - _border_width + frame->size().left;
+ event.xconfigure.y = y - _border_width + frame->size().top;
+
event.xconfigure.width = _area.width();
event.xconfigure.height = _area.height();
event.xconfigure.border_width = _border_width;
- event.xconfigure.above = frame->window();
+ event.xconfigure.above = frame->plate();
event.xconfigure.override_redirect = False;
XSendEvent(event.xconfigure.display, event.xconfigure.window, False,
StructureNotifyMask, &event);
+#if 0//def DEBUG
+ printf("Sent synthetic ConfigureNotify %d,%d %d,%d to 0x%lx\n",
+ event.xconfigure.x, event.xconfigure.y, event.xconfigure.width,
+ event.xconfigure.height, event.xconfigure.window);
+#endif
}
}
}
+void Client::disableDecorations(DecorationFlags flags)
+{
+ _disabled_decorations = flags;
+ setupDecorAndFunctions();
+}
+
+
bool Client::focus()
{
// won't try focus if the client doesn't want it, or if the window isn't
XSendEvent(**otk::display, _window, False, NoEventMask, &ce);
}
+ XSync(**otk::display, False);
return true;
}