add support for desktop layouts specified by pagers
This commit is contained in:
parent
29bd1c97a2
commit
81c164bbf9
4 changed files with 154 additions and 6 deletions
|
@ -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(),
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue