+ XSendEvent(**otk::display, _window, false, NoEventMask, &ce);
+}
+
+
+void Client::changeState()
+{
+ unsigned long state[2];
+ state[0] = _wmstate;
+ state[1] = None;
+ otk::Property::set(_window, otk::Property::atoms.wm_state,
+ otk::Property::atoms.wm_state, state, 2);
+
+ Atom netstate[10];
+ int num = 0;
+ if (_modal)
+ netstate[num++] = otk::Property::atoms.net_wm_state_modal;
+ if (_shaded)
+ netstate[num++] = otk::Property::atoms.net_wm_state_shaded;
+ if (_iconic)
+ netstate[num++] = otk::Property::atoms.net_wm_state_hidden;
+ if (_skip_taskbar)
+ netstate[num++] = otk::Property::atoms.net_wm_state_skip_taskbar;
+ if (_skip_pager)
+ netstate[num++] = otk::Property::atoms.net_wm_state_skip_pager;
+ if (_fullscreen)
+ netstate[num++] = otk::Property::atoms.net_wm_state_fullscreen;
+ if (_max_vert)
+ netstate[num++] = otk::Property::atoms.net_wm_state_maximized_vert;
+ if (_max_horz)
+ netstate[num++] = otk::Property::atoms.net_wm_state_maximized_horz;
+ if (_above)
+ netstate[num++] = otk::Property::atoms.net_wm_state_above;
+ if (_below)
+ netstate[num++] = otk::Property::atoms.net_wm_state_below;
+ otk::Property::set(_window, otk::Property::atoms.net_wm_state,
+ otk::Property::atoms.atom, netstate, num);
+
+ calcLayer();
+
+ if (frame)
+ frame->adjustState();
+}
+
+
+void Client::changeAllowedActions(void)
+{
+ Atom actions[9];
+ int num = 0;
+
+ actions[num++] = otk::Property::atoms.net_wm_action_change_desktop;
+
+ if (_functions & Func_Shade)
+ actions[num++] = otk::Property::atoms.net_wm_action_shade;
+ if (_functions & Func_Close)
+ actions[num++] = otk::Property::atoms.net_wm_action_close;
+ if (_functions & Func_Move)
+ actions[num++] = otk::Property::atoms.net_wm_action_move;
+ if (_functions & Func_Iconify)
+ actions[num++] = otk::Property::atoms.net_wm_action_minimize;
+ if (_functions & Func_Resize)
+ actions[num++] = otk::Property::atoms.net_wm_action_resize;
+ if (_functions & Func_Fullscreen)
+ actions[num++] = otk::Property::atoms.net_wm_action_fullscreen;
+ if (_functions & Func_Maximize) {
+ actions[num++] = otk::Property::atoms.net_wm_action_maximize_horz;
+ actions[num++] = otk::Property::atoms.net_wm_action_maximize_vert;
+ }
+
+ otk::Property::set(_window, otk::Property::atoms.net_wm_allowed_actions,
+ otk::Property::atoms.atom, actions, num);
+}
+
+
+void Client::remaximize()
+{
+ int dir;
+ if (_max_horz && _max_vert)
+ dir = 0;
+ else if (_max_horz)
+ dir = 1;
+ else if (_max_vert)
+ dir = 2;
+ else
+ return; // not maximized
+ _max_horz = _max_vert = false;
+ maximize(true, dir, false);
+}
+
+
+void Client::applyStartupState()
+{
+ // these are in a carefully crafted order..
+
+ if (_iconic) {
+ _iconic = false;
+ setDesktop(ICONIC_DESKTOP);
+ }
+ if (_fullscreen) {
+ _fullscreen = false;
+ fullscreen(true, false);
+ }
+ if (_shaded) {
+ _shaded = false;
+ shade(true);
+ }
+ if (_urgent)
+ fireUrgent();
+
+ if (_max_vert && _max_horz) {
+ _max_vert = _max_horz = false;
+ maximize(true, 0, false);
+ } else if (_max_vert) {
+ _max_vert = false;
+ maximize(true, 2, false);
+ } else if (_max_horz) {
+ _max_horz = false;
+ maximize(true, 1, false);
+ }
+
+ if (_skip_taskbar); // nothing to do for this
+ if (_skip_pager); // nothing to do for this
+ if (_modal); // nothing to do for this
+ if (_above); // nothing to do for this
+ if (_below); // nothing to do for this
+}
+
+
+void Client::fireUrgent()
+{
+ // call the python UrgentWindow callbacks
+ EventData data(_screen, this, EventAction::UrgentWindow, 0);
+ openbox->bindings()->fireEvent(&data);
+}
+
+
+void Client::shade(bool shade)
+{
+ if (!(_functions & Func_Shade) || // can't
+ _shaded == shade) return; // already done
+
+ // when we're iconic, don't change the wmstate
+ if (!_iconic)
+ _wmstate = shade ? IconicState : NormalState;
+ _shaded = shade;
+ changeState();
+ frame->adjustSize();
+}
+
+
+void Client::maximize(bool max, int dir, bool savearea)
+{
+ assert(dir == 0 || dir == 1 || dir == 2);
+ if (!(_functions & Func_Maximize)) return; // can't
+
+ // check if already done
+ if (max) {
+ if (dir == 0 && _max_horz && _max_vert) return;
+ if (dir == 1 && _max_horz) return;
+ if (dir == 2 && _max_vert) return;
+ } else {
+ if (dir == 0 && !_max_horz && !_max_vert) return;
+ if (dir == 1 && !_max_horz) return;
+ if (dir == 2 && !_max_vert) return;
+ }
+
+ const otk::Rect &a = openbox->screen(_screen)->area();
+ int x = frame->rect().x(), y = frame->rect().y(),
+ w = _area.width(), h = _area.height();
+
+ if (max) {
+ if (savearea) {
+ long dimensions[4];
+ long *readdim;
+ unsigned long n = 4;
+
+ dimensions[0] = x;
+ dimensions[1] = y;
+ dimensions[2] = w;
+ dimensions[3] = h;
+
+ // get the property off the window and use it for the dimentions we are
+ // already maxed on
+ if (otk::Property::get(_window, otk::Property::atoms.openbox_premax,
+ otk::Property::atoms.cardinal, &n,
+ (long unsigned**) &readdim)) {
+ if (n >= 4) {
+ if (_max_horz) {
+ dimensions[0] = readdim[0];
+ dimensions[2] = readdim[2];
+ }
+ if (_max_vert) {
+ dimensions[1] = readdim[1];
+ dimensions[3] = readdim[3];
+ }
+ }
+ delete readdim;
+ }
+
+ otk::Property::set(_window, otk::Property::atoms.openbox_premax,
+ otk::Property::atoms.cardinal,
+ (long unsigned*)dimensions, 4);
+ }
+ if (dir == 0 || dir == 1) { // horz
+ x = a.x();
+ w = a.width();
+ }
+ if (dir == 0 || dir == 2) { // vert
+ y = a.y();
+ h = a.height() - frame->size().top - frame->size().bottom;
+ }
+ } else {
+ long *dimensions;
+ long unsigned n = 4;
+
+ if (otk::Property::get(_window, otk::Property::atoms.openbox_premax,
+ otk::Property::atoms.cardinal, &n,
+ (long unsigned**) &dimensions)) {
+ if (n >= 4) {
+ if (dir == 0 || dir == 1) { // horz
+ x = (signed int)dimensions[0];
+ w = (signed int)dimensions[2];
+ }
+ if (dir == 0 || dir == 2) { // vert
+ y = (signed int)dimensions[1];
+ h = (signed int)dimensions[3];
+ }
+ }
+ delete dimensions;
+ } else {
+ // pick some fallbacks...
+ if (dir == 0 || dir == 1) { // horz
+ x = a.x() + a.width() / 4;
+ w = a.width() / 2;
+ }
+ if (dir == 0 || dir == 2) { // vert
+ y = a.y() + a.height() / 4;
+ h = a.height() / 2;
+ }
+ }
+ }
+
+ if (dir == 0 || dir == 1) // horz
+ _max_horz = max;
+ if (dir == 0 || dir == 2) // vert
+ _max_vert = max;
+
+ if (!_max_horz && !_max_vert)
+ otk::Property::erase(_window, otk::Property::atoms.openbox_premax);
+
+ changeState(); // change the state hints on the client
+
+ frame->frameGravity(x, y); // figure out where the client should be going
+ internal_resize(TopLeft, w, h, true, x, y);