From 2a2f4306f85a8aee0d0b89c3cd4dfaee5a85a928 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sat, 1 Feb 2003 05:26:06 +0000 Subject: [PATCH] maximizing! --- otk/property.cc | 2 + otk/property.hh | 2 + otk/renderstyle.cc | 4 +- scripts/behavior.py | 2 + scripts/callbacks.py | 40 +++++++++ src/client.cc | 199 ++++++++++++++++++++++++++++++++++++------- src/client.hh | 16 +++- 7 files changed, 233 insertions(+), 32 deletions(-) diff --git a/otk/property.cc b/otk/property.cc index b12ff503..a0404f68 100644 --- a/otk/property.cc +++ b/otk/property.cc @@ -134,6 +134,8 @@ void Property::initialize() create("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR"); atoms.kde_net_wm_window_type_override = create("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"); + + atoms.openbox_premax = create("_OPENBOX_PREMAX"); } void Property::set(Window win, Atom atom, Atom type, unsigned char* data, diff --git a/otk/property.hh b/otk/property.hh index 9ff30887..e38bb23a 100644 --- a/otk/property.hh +++ b/otk/property.hh @@ -123,6 +123,8 @@ struct Atoms { Atom kde_net_system_tray_windows; Atom kde_net_wm_system_tray_window_for; Atom kde_net_wm_window_type_override; + + Atom openbox_premax; }; diff --git a/otk/renderstyle.cc b/otk/renderstyle.cc index 8afb1141..330870c6 100644 --- a/otk/renderstyle.cc +++ b/otk/renderstyle.cc @@ -15,8 +15,8 @@ RenderStyle::RenderStyle(int screen, const std::string &stylefile) _file(stylefile) { // pick one.. -#define FIERON -//#define MERRY +//#define FIERON +#define MERRY #ifdef FIERON _root_color = new RenderColor(_screen, 0x272a2f); diff --git a/scripts/behavior.py b/scripts/behavior.py index 5e475af8..131cbe3f 100644 --- a/scripts/behavior.py +++ b/scripts/behavior.py @@ -72,6 +72,8 @@ def setup_window_buttons(): ob.MouseAction.Click, callbacks.close) ob.mbind("Left", ob.MouseContext.IconifyButton, ob.MouseAction.Click, callbacks.iconify) + ob.mbind("Left", ob.MouseContext.MaximizeButton, + ob.MouseAction.Click, callbacks.toggle_maximize) def setup_scroll(): """Sets up the default behaviors for the mouse scroll wheel. diff --git a/scripts/callbacks.py b/scripts/callbacks.py index 25ac965f..6d6ed51e 100644 --- a/scripts/callbacks.py +++ b/scripts/callbacks.py @@ -36,6 +36,34 @@ def state_shaded(data, add=StateAdd): otk.Property_atoms().net_wm_state, data.client.window(), add, otk.Property_atoms().net_wm_state_shaded) +def state_maximize(data, add=StateAdd): + """Toggles, adds or removes the horizontal and vertical 'maximized' state + on a window. The second paramater should one of: StateRemove, StateAdd, + or StateToggle.""" + if not data.client: return + ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(), + otk.Property_atoms().net_wm_state, data.client.window(), + add, otk.Property_atoms().net_wm_state_maximized_horz, + otk.Property_atoms().net_wm_state_maximized_vert) + +def state_maximize_horz(data, add=StateAdd): + """Toggles, adds or removes the horizontal 'maximized' state on a window. + The second paramater should one of: StateRemove, StateAdd, or + StateToggle.""" + if not data.client: return + ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(), + otk.Property_atoms().net_wm_state, data.client.window(), + add, otk.Property_atoms().net_wm_state_maximized_horz) + +def state_maximize_vert(data, add=StateAdd): + """Toggles, adds or removes the vertical 'maximized' state on a window. + The second paramater should one of: StateRemove, StateAdd, or + StateToggle.""" + if not data.client: return + ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(), + otk.Property_atoms().net_wm_state, data.client.window(), + add, otk.Property_atoms().net_wm_state_maximized_vert) + def state_skip_taskbar(data, add=StateAdd): """Toggles, adds or removes the 'skip_taskbar' state on a window. The second paramater should one of: StateRemove, StateAdd, or @@ -99,6 +127,18 @@ def lower_win(data): if not data.client: return ob.openbox.screen(data.screen).lowerWindow(data.client) +def toggle_maximize(data): + """Toggles the maximized status of the window on which the event occured""" + state_maximize(data, StateToggle) + +def maximize(data): + """Maximizes the window on which the event occured""" + state_maximize(data, StateAdd) + +def unmaximize(data): + """Unmaximizes the window on which the event occured""" + state_maximize(data, StateRemove) + def toggle_shade(data): """Toggles the shade status of the window on which the event occured""" state_shaded(data, StateToggle) diff --git a/src/client.cc b/src/client.cc index 8f654908..e9418cb3 100644 --- a/src/client.cc +++ b/src/client.cc @@ -797,6 +797,8 @@ void Client::setState(StateAction action, long data1, long data2) { bool shadestate = _shaded; bool fsstate = _fullscreen; + bool maxh = _max_horz; + bool maxv = _max_vert; if (!(action == State_Add || action == State_Remove || action == State_Toggle)) @@ -835,12 +837,10 @@ void Client::setState(StateAction action, long data1, long data2) _modal = true; // XXX: give it focus if another window has focus that shouldnt now } else if (state == otk::Property::atoms.net_wm_state_maximized_vert) { - if (_max_vert) continue; - _max_vert = true; - // XXX: resize the window etc + maxv = true; } else if (state == otk::Property::atoms.net_wm_state_maximized_horz) { if (_max_horz) continue; - _max_horz = true; + maxh = true; // XXX: resize the window etc } else if (state == otk::Property::atoms.net_wm_state_shaded) { shadestate = true; @@ -863,13 +863,9 @@ void Client::setState(StateAction action, long data1, long data2) if (!_modal) continue; _modal = false; } else if (state == otk::Property::atoms.net_wm_state_maximized_vert) { - if (!_max_vert) continue; - _max_vert = false; - // XXX: resize the window etc + maxv = false; } else if (state == otk::Property::atoms.net_wm_state_maximized_horz) { - if (!_max_horz) continue; - _max_horz = false; - // XXX: resize the window etc + maxh = false; } else if (state == otk::Property::atoms.net_wm_state_shaded) { shadestate = false; } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) { @@ -887,10 +883,25 @@ void Client::setState(StateAction action, long data1, long data2) } } } + if (maxh != _max_horz || maxv != _max_vert) { + if (maxh != _max_horz && maxv != _max_vert) { // toggling both + if (maxh == maxv) { // both going the same way + maximize(maxh, 0, true); + } else { + maximize(maxh, 1, true); + maximize(maxv, 2, true); + } + } else { // toggling one + if (maxh != _max_horz) + maximize(maxh, 1, true); + else + maximize(maxv, 1, true); + } + } // change fullscreen state before shading, as it will affect if the window // can shade or not if (fsstate != _fullscreen) - fullscreen(fsstate); + fullscreen(fsstate, true); if (shadestate != _shaded) shade(shadestate); calcLayer(); @@ -1276,7 +1287,7 @@ void Client::applyStartupState() } if (_fullscreen) { _fullscreen = false; - fullscreen(true); + fullscreen(true, false); } if (_shaded) { _shaded = false; @@ -1285,8 +1296,16 @@ void Client::applyStartupState() if (_urgent) fireUrgent(); - if (_max_vert); // XXX: incomplete - if (_max_horz); // XXX: incomplete + 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 @@ -1318,12 +1337,105 @@ void Client::shade(bool shade) } -void Client::fullscreen(bool fs) +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; + } + + int g = _gravity; + + const otk::Rect &a = openbox->screen(_screen)->area(); + int x = _area.x(), y = _area.y(), w = _area.width(), h = _area.height(); + + if (max) { + // when maximizing, put the client where we want, NOT the frame! + _gravity = StaticGravity; + + if (savearea) { + long dimensions[4]; + dimensions[0] = x; + dimensions[1] = y; + dimensions[2] = w; + dimensions[3] = h; + 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() + frame->size().top; + 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; + } + } + otk::Property::erase(_window, otk::Property::atoms.openbox_premax); + } + + if (dir == 0 || dir == 1) // horz + _max_horz = max; + if (dir == 0 || dir == 2) // vert + _max_vert = max; + changeState(); // change the state hints on the client + + internal_resize(TopLeft, w, h, true, x, y); + printf("before x %d y %d w %d h %d\n", x, y, w, h); + _gravity = g; + if (max) { + // because of my little gravity trick in here, we have to set the position + // of the client to what it really is + int x, y; + frame->frameGravity(x, y); + _area.setPos(x, y); + printf("after x %d y %d w %d h %d\n", x, y, w, h); + } +} + + +void Client::fullscreen(bool fs, bool savearea) { 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 @@ -1331,6 +1443,8 @@ void Client::fullscreen(bool fs) _fullscreen = fs; changeState(); // change the state hints on the client + int x = _area.x(), y = _area.y(), w = _area.width(), h = _area.height(); + if (fs) { // save the functions and remove them saved_func = _functions; @@ -1338,25 +1452,52 @@ void Client::fullscreen(bool fs) // 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; + if (savearea) { + long dimensions[4]; + dimensions[0] = _area.x(); + dimensions[1] = _area.y(); + dimensions[2] = _area.width(); + dimensions[3] = _area.height(); + otk::Property::set(_window, otk::Property::atoms.openbox_premax, + otk::Property::atoms.cardinal, + (long unsigned*)dimensions, 4); + } 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()); + x = 0; + y = 0; + w = info->width(); + h = info->height(); } else { _functions = saved_func; _decorations = saved_decor; - _area = saved_area; - _logical_size = saved_logical_size; + + 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) { + x = dimensions[0]; + y = dimensions[1]; + w = dimensions[2]; + h = dimensions[3]; + } + delete dimensions; + } else { + // pick some fallbacks... + const otk::Rect &a = openbox->screen(_screen)->area(); + x = a.x() + a.width() / 4; + y = a.y() + a.height() / 4; + w = a.width() / 2; + h = a.height() / 2; + } } changeAllowedActions(); // based on the new _functions - - frame->adjustSize(); // drop/replace the decor's and resize - frame->adjustPosition(); // get (back) in position! + + // when fullscreening, don't obey things like increments, fill the screen + internal_resize(TopLeft, w, h, !fs, x, y); // raise (back) into our stacking layer openbox->screen(_screen)->raiseWindow(this); diff --git a/src/client.hh b/src/client.hh index d43984cb..7539a7c8 100644 --- a/src/client.hh +++ b/src/client.hh @@ -431,8 +431,22 @@ private: /*! @param fs true if the window should be made fullscreen; false if it should be returned to normal state. + @param savearea true to have the client's current size and position saved; + otherwise, they are not. You should not save when mapping a + new window that is set to fullscreen. */ - void fullscreen(bool fs); + void fullscreen(bool fs, bool savearea); + + //! Maximize or unmaximize the client window + /*! + @param max true if the window should be maximized; false if it should be + returned to normal size. + @param dir 0 to set both horz and vert, 1 to set horz, 2 to set vert. + @param savearea true to have the client's current size and position saved; + otherwise, they are not. You should not save when mapping a + new window that is set to fullscreen. + */ + void maximize(bool max, int dir, bool savearea); //! Internal version of the Client::move function /*! -- 2.45.2