From 81c164bbf9ed2462e5f9fb7599fa6f0279a087fa Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 10 Feb 2003 16:12:33 +0000 Subject: [PATCH] add support for desktop layouts specified by pagers --- scripts/callbacks.py | 66 +++++++++++++++++++++++++++++++++++++++++++- scripts/defaults.py | 8 ++++-- src/screen.cc | 66 ++++++++++++++++++++++++++++++++++++++++++++ src/screen.hh | 20 ++++++++++++-- 4 files changed, 154 insertions(+), 6 deletions(-) diff --git a/scripts/callbacks.py b/scripts/callbacks.py index 6c33bc77..f7cb37c1 100644 --- a/scripts/callbacks.py +++ b/scripts/callbacks.py @@ -209,7 +209,71 @@ def prev_desktop(data, no_wrap=0): d = n - 1 change_desktop(data, d) -def send_to_desktop(data, num): +def up_desktop(data, num=1): + """Switches to the desktop vertically above the current one. This is based + on the desktop layout chosen by an EWMH compliant pager. Optionally, num + can be specified to move more than one row at a time.""" + screen = ob.openbox.screen(data.screen) + d = screen.desktop() + n = screen.numDesktops() + l = screen.desktopLayout() + + target = d - num * l.columns + if target < 0: + target += l.rows * l.columns + while target >= n: + target -= l.columns + change_desktop(data, target) + +def down_desktop(data, num=1): + """Switches to the desktop vertically below the current one. This is based + on the desktop layout chosen by an EWMH compliant pager. Optionally, num + can be specified to move more than one row at a time.""" + screen = ob.openbox.screen(data.screen) + d = screen.desktop() + n = screen.numDesktops() + l = screen.desktopLayout() + + target = d + num * l.columns + if target >= n: + target -= l.rows * l.columns + while target < 0: + target += l.columns + change_desktop(data, target) + +def left_desktop(data, num=1): + """Switches to the desktop horizotally left of the current one. This is + based on the desktop layout chosen by an EWMH compliant pager. + Optionally, num can be specified to move more than one column at a + time.""" + screen = ob.openbox.screen(data.screen) + d = screen.desktop() + n = screen.numDesktops() + l = screen.desktopLayout() + + rowstart = d - d % l.columns + target = d - num + while target < rowstart: + target += l.columns + change_desktop(data, target) + +def right_desktop(data, num=1): + """Switches to the desktop horizotally right of the current one. This is + based on the desktop layout chosen by an EWMH compliant pager. + Optionally, num can be specified to move more than one column at a + time.""" + screen = ob.openbox.screen(data.screen) + d = screen.desktop() + n = screen.numDesktops() + l = screen.desktopLayout() + + rowstart = d - d % l.columns + target = d + num + while target >= rowstart + l.columns: + target -= l.columns + change_desktop(data, target) + +def send_to_desktop(data, num=1): """Sends a client to a specified desktop""" if not data.client: return ob.send_client_msg(otk.display.screenInfo(data.screen).rootWindow(), diff --git a/scripts/defaults.py b/scripts/defaults.py index 04143e11..98c57ce5 100644 --- a/scripts/defaults.py +++ b/scripts/defaults.py @@ -53,9 +53,13 @@ ob.kbind(["C-2"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 1)) ob.kbind(["C-3"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 2)) ob.kbind(["C-4"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 3)) ob.kbind(["C-A-Right"], ob.KeyContext.All, - lambda(d): callbacks.next_desktop(d)) + lambda(d): callbacks.right_desktop(d)) ob.kbind(["C-A-Left"], ob.KeyContext.All, - lambda(d): callbacks.prev_desktop(d)) + lambda(d): callbacks.left_desktop(d)) +ob.kbind(["C-A-Up"], ob.KeyContext.All, + lambda(d): callbacks.up_desktop(d)) +ob.kbind(["C-A-Down"], ob.KeyContext.All, + lambda(d): callbacks.down_desktop(d)) ob.kbind(["C-S-A-Right"], ob.KeyContext.All, lambda(d): callbacks.send_to_next_desktop(d)) diff --git a/src/screen.cc b/src/screen.cc index a2514276..b556e7ac 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -123,6 +123,8 @@ Screen::Screen(int screen) // the manageExising() function changeClientList(); // initialize the client lists, which will be empty + updateDesktopLayout(); + // register this class as the event handler for the root window openbox->registerHandler(_info->rootWindow(), this); @@ -198,6 +200,65 @@ void Screen::manageExisting() XFree(children); } +void Screen::updateDesktopLayout() +{ + //const unsigned long _NET_WM_ORIENTATION_HORZ = 0; + const unsigned long _NET_WM_ORIENTATION_VERT = 1; + //const unsigned long _NET_WM_TOPLEFT = 0; + const unsigned long _NET_WM_TOPRIGHT = 1; + const unsigned long _NET_WM_BOTTOMRIGHT = 2; + const unsigned long _NET_WM_BOTTOMLEFT = 3; + + // defaults + _layout.orientation = DesktopLayout::Horizontal; + _layout.start_corner = DesktopLayout::TopLeft; + _layout.rows = 1; + _layout.columns = _num_desktops; + + unsigned long *data, num = 4; + if (otk::Property::get(_info->rootWindow(), + otk::Property::atoms.net_desktop_layout, + otk::Property::atoms.cardinal, + &num, &data)) { + if (num >= 4) { + if (data[0] == _NET_WM_ORIENTATION_VERT) + _layout.orientation = DesktopLayout::Vertical; + if (data[3] == _NET_WM_TOPRIGHT) + _layout.start_corner = DesktopLayout::TopRight; + else if (data[3] == _NET_WM_BOTTOMRIGHT) + _layout.start_corner = DesktopLayout::BottomRight; + else if (data[3] == _NET_WM_BOTTOMLEFT) + _layout.start_corner = DesktopLayout::BottomLeft; + + // fill in a zero rows/columns + if (!(data[1] == 0 && data[2] == 0)) { // both 0's is bad data.. + if (data[1] == 0) { + data[1] = (_num_desktops + _num_desktops % data[2]) / data[2]; + } else if (data[2] == 0) { + data[2] = (_num_desktops + _num_desktops % data[1]) / data[1]; + } + _layout.columns = data[1]; + _layout.rows = data[2]; + } + + // bounds checking + if (_layout.orientation == DesktopLayout::Horizontal) { + if (_layout.rows > _num_desktops) _layout.rows = _num_desktops; + if (_layout.columns > (_num_desktops + _num_desktops % _layout.rows) / + _layout.rows) + _layout.columns = (_num_desktops + _num_desktops % _layout.rows) / + _layout.rows; + } else { + if (_layout.columns > _num_desktops) _layout.columns = _num_desktops; + if (_layout.rows > (_num_desktops + _num_desktops % _layout.columns) / + _layout.columns) + _layout.rows = (_num_desktops + _num_desktops % _layout.columns) / + _layout.columns; + } + } + delete [] data; + } +} void Screen::updateStruts() { @@ -770,6 +831,9 @@ void Screen::changeNumDesktops(unsigned int num) _struts.resize(_num_desktops + 1); updateStruts(); + // the number of rows/columns will differ + updateDesktopLayout(); + // change our desktop if we're on one that no longer exists! if (_desktop >= _num_desktops) changeDesktop(_num_desktops - 1); @@ -836,6 +900,8 @@ void Screen::propertyHandler(const XPropertyEvent &e) if (e.atom == otk::Property::atoms.net_desktop_names) updateDesktopNames(); + else if (e.atom == otk::Property::atoms.net_desktop_layout) + updateDesktopLayout(); } diff --git a/src/screen.hh b/src/screen.hh index 9b3618c9..adccf180 100644 --- a/src/screen.hh +++ b/src/screen.hh @@ -24,6 +24,16 @@ namespace ob { class Client; +struct DesktopLayout { + enum Corner { TopLeft, TopRight, BottomRight, BottomLeft }; + enum Direction { Horizontal, Vertical }; + + Direction orientation; + Corner start_corner; + unsigned int rows; + unsigned int columns; +}; + //! Manages a single screen /*! */ @@ -58,9 +68,6 @@ private: //! Information about this screen const otk::ScreenInfo *_info; - //! Is the root colormap currently installed? - bool _root_cmap_installed; - //! Area usable for placement etc (total - struts), one per desktop, //! plus one extra for windows on all desktops RectList _area; @@ -88,6 +95,8 @@ private: //! The names of all desktops otk::Property::StringVect _desktop_names; + DesktopLayout _layout; + //! Calculate the Screen::_area member void calcArea(); //! Set the list of supported NETWM atoms on the root window @@ -112,6 +121,9 @@ private: //! Get desktop names from the root window property void updateDesktopNames(); + //! Gets the layout of the desktops from the root window property + void updateDesktopLayout(); + //! Changes to the specified desktop, displaying windows on it and hiding //! windows on the others. /*! @@ -158,6 +170,8 @@ public: */ const otk::Rect& area(unsigned int desktop) const; + const DesktopLayout& desktopLayout() const { return _layout; } + //! Update's the screen's combined strut of all the clients. /*! Clients should call this whenever they change their strut. -- 2.44.0