X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fclient.cc;h=27d89c077e7f0be41268cf0c579d94843d7d8696;hb=b45a68cc30121ad2c5cd3b795a6b5e8572425316;hp=e8a6b84bd14028f96b0e7e08147a09c454a7b9e3;hpb=105e3524a3f6b526d54ecc761a6e6c91b04f3949;p=chaz%2Fopenbox diff --git a/src/client.cc b/src/client.cc index e8a6b84b..27d89c07 100644 --- a/src/client.cc +++ b/src/client.cc @@ -168,15 +168,17 @@ void Client::getType() void Client::setupDecorAndFunctions() { - // start with everything + // start with everything (cept fullscreen) _decorations = Decor_Titlebar | Decor_Handle | Decor_Border | - Decor_Iconify | Decor_Maximize; - _functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize; + Decor_AllDesktops | Decor_Iconify | Decor_Maximize; + _functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize | + Func_Shade; switch (_type) { case Type_Normal: // normal windows retain all of the possible decorations and - // functionality + // functionality, and are the only windows that you can fullscreen + _functions |= Func_Fullscreen; case Type_Dialog: // dialogs cannot be maximized @@ -209,8 +211,11 @@ void Client::setupDecorAndFunctions() _decorations &= ~Decor_Border; if (! (_mwmhints.decorations & MwmDecor_Handle)) _decorations &= ~Decor_Handle; - if (! (_mwmhints.decorations & MwmDecor_Title)) + if (! (_mwmhints.decorations & MwmDecor_Title)) { _decorations &= ~Decor_Titlebar; + // if we don't have a titlebar, then we cannot shade! + _functions &= ~Func_Shade; + } if (! (_mwmhints.decorations & MwmDecor_Iconify)) _decorations &= ~Decor_Iconify; if (! (_mwmhints.decorations & MwmDecor_Maximize)) @@ -287,10 +292,9 @@ void Client::getState() for (unsigned long i = 0; i < num; ++i) { if (state[i] == otk::Property::atoms.net_wm_state_modal) _modal = true; - else if (state[i] == otk::Property::atoms.net_wm_state_shaded) { + else if (state[i] == otk::Property::atoms.net_wm_state_shaded) _shaded = true; - _wmstate = IconicState; - } else if (state[i] == otk::Property::atoms.net_wm_state_skip_taskbar) + else if (state[i] == otk::Property::atoms.net_wm_state_skip_taskbar) _skip_taskbar = true; else if (state[i] == otk::Property::atoms.net_wm_state_skip_pager) _skip_pager = true; @@ -651,12 +655,15 @@ void Client::setDesktop(long target) frame->show(); else frame->hide(); + + frame->adjustState(); } void Client::setState(StateAction action, long data1, long data2) { bool shadestate = _shaded; + bool fsstate = _fullscreen; if (!(action == State_Add || action == State_Remove || action == State_Toggle)) @@ -703,16 +710,13 @@ void Client::setState(StateAction action, long data1, long data2) _max_horz = true; // XXX: resize the window etc } else if (state == otk::Property::atoms.net_wm_state_shaded) { - if (_shaded) continue; - // shade when we're all thru here shadestate = true; } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) { _skip_taskbar = true; } else if (state == otk::Property::atoms.net_wm_state_skip_pager) { _skip_pager = true; } else if (state == otk::Property::atoms.net_wm_state_fullscreen) { - if (_fullscreen) continue; - _fullscreen = true; + fsstate = true; } else if (state == otk::Property::atoms.net_wm_state_above) { if (_above) continue; _above = true; @@ -734,16 +738,13 @@ void Client::setState(StateAction action, long data1, long data2) _max_horz = false; // XXX: resize the window etc } else if (state == otk::Property::atoms.net_wm_state_shaded) { - if (!_shaded) continue; - // unshade when we're all thru here shadestate = false; } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) { _skip_taskbar = false; } else if (state == otk::Property::atoms.net_wm_state_skip_pager) { _skip_pager = false; } else if (state == otk::Property::atoms.net_wm_state_fullscreen) { - if (!_fullscreen) continue; - _fullscreen = false; + fsstate = false; } else if (state == otk::Property::atoms.net_wm_state_above) { if (!_above) continue; _above = false; @@ -753,6 +754,10 @@ void Client::setState(StateAction action, long data1, long data2) } } } + // change fullscreen state before shading, as it will affect if the window + // can shade or not + if (fsstate != _fullscreen) + fullscreen(fsstate); if (shadestate != _shaded) shade(shadestate); calcLayer(); @@ -1069,23 +1074,31 @@ void Client::changeState() otk::Property::atoms.atom, netstate, num); calcLayer(); + + if (frame) + frame->adjustState(); } void Client::changeAllowedActions(void) { - Atom actions[7]; + Atom actions[9]; int num = 0; - actions[num++] = otk::Property::atoms.net_wm_action_shade; 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; + 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; + 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; @@ -1096,9 +1109,34 @@ void Client::changeAllowedActions(void) } +void Client::applyStartupState() +{ + // these are in a carefully crafted order.. + + if (_fullscreen) { + _fullscreen = false; + fullscreen(true); + } + if (_shaded) { + _shaded = false; + shade(true); + } + + if (_max_vert); // XXX: incomplete + if (_max_horz); // XXX: incomplete + + 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::shade(bool shade) { - if (shade == _shaded) return; // already done + if (!(_functions & Func_Shade) || // can't + _shaded == shade) return; // already done _wmstate = shade ? IconicState : NormalState; _shaded = shade; @@ -1107,6 +1145,54 @@ void Client::shade(bool shade) } +void Client::fullscreen(bool fs) +{ + static FunctionFlags saved_func; + static DecorationFlags saved_decor; + static otk::Rect saved_area; + static otk::Point saved_logical_size; + + if (!(_functions & Func_Fullscreen) || // can't + _fullscreen == fs) return; // already done + + _fullscreen = fs; + changeState(); // change the state hints on the client + + if (fs) { + // save the functions and remove them + saved_func = _functions; + _functions = _functions & (Func_Close | Func_Fullscreen | Func_Iconify); + // save the decorations and remove them + saved_decor = _decorations; + _decorations = 0; + // save the area and adjust it (we don't call internal resize here for + // constraints on the size, etc, we just make it fullscreen). + saved_area = _area; + const otk::ScreenInfo *info = otk::display->screenInfo(_screen); + _area.setRect(0, 0, info->width(), info->height()); + saved_logical_size = _logical_size; + _logical_size.setPoint((info->width() - _base_size.x()) / _size_inc.x(), + (info->height() - _base_size.y()) / _size_inc.y()); + } else { + _functions = saved_func; + _decorations = saved_decor; + _area = saved_area; + _logical_size = saved_logical_size; + } + + changeAllowedActions(); // based on the new _functions + + frame->adjustSize(); // drop/replace the decor's and resize + frame->adjustPosition(); // get (back) in position! + + // raise (back) into our stacking layer + openbox->screen(_screen)->raiseWindow(this); + + // try focus us when we go into fullscreen mode + if (fs) focus(); +} + + bool Client::focus() const { // won't try focus if the client doesn't want it, or if the window isn't @@ -1115,6 +1201,14 @@ bool Client::focus() const if (_focused) return true; + // do a check to see if the window has already been unmapped or destroyed + XEvent ev; + if (XCheckTypedWindowEvent(**otk::display, _window, UnmapNotify, &ev) || + XCheckTypedWindowEvent(**otk::display, _window, DestroyNotify, &ev)) { + XPutBackEvent(**otk::display, &ev); + return false; + } + if (_can_focus) XSetInputFocus(**otk::display, _window, RevertToNone, CurrentTime);