add support for desktop layouts specified by pagers

This commit is contained in:
Dana Jansens 2003-02-10 16:12:33 +00:00
parent 29bd1c97a2
commit 81c164bbf9
4 changed files with 154 additions and 6 deletions

View file

@ -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(),

View file

@ -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))

View file

@ -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();
}

View file

@ -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.