#include "config.h"
+#include "screen.hh"
+#include "client.hh"
+#include "openbox.hh"
+#include "frame.hh"
+#include "bindings.hh"
+#include "python.hh"
+#include "otk/display.hh"
+#include "otk/property.hh"
+
extern "C" {
#ifdef HAVE_UNISTD_H
# include <sys/types.h>
#define _(str) gettext(str)
}
-#include "screen.hh"
-#include "client.hh"
-#include "openbox.hh"
-#include "frame.hh"
-#include "bindings.hh"
-#include "python.hh"
-#include "otk/display.hh"
-#include "otk/property.hh"
-
#include <vector>
#include <algorithm>
#include <cstdio>
_desktop = 0;
- if (!python_get_long("NUMBER_OF_DESKTOPS", &_num_desktops))
+ if (!python_get_long("NUMBER_OF_DESKTOPS", (long*)&_num_desktops))
_num_desktops = 1;
changeNumDesktops(_num_desktops); // set the hint
changeDesktop(0); // set the hint
+ // don't start in showing-desktop mode
+ _showing_desktop = false;
+ otk::Property::set(_info->rootWindow(),
+ otk::Property::atoms.net_showing_desktop,
+ otk::Property::atoms.cardinal, 0);
+
// create the window which gets focus when no clients get it
XSetWindowAttributes attr;
attr.override_redirect = true;
// 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);
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()
{
ClientList::const_iterator it, end = clients.end();
for (it = clients.begin(); it != end; ++it) {
- long desk = (*it)->desktop();
+ if ((*it)->iconic()) continue; // these dont count in the strut
+
+ unsigned int desk = (*it)->desktop();
const otk::Strut &s = (*it)->strut();
- if (desk == (signed) 0xffffffff)
+ if (desk == 0xffffffff)
for (unsigned int i = 0, e = _struts.size(); i < e; ++i)
apply(_struts[i], s);
- else if ((unsigned)desk < _struts.size())
+ else if (desk < _struts.size())
apply(_struts[desk], s);
- else if (desk == Client::ICONIC_DESKTOP)
- continue; // skip for the 'all desktops' strut
else
assert(false); // invalid desktop otherwise..
// apply to the 'all desktops' strut
void Screen::changeWorkArea()
{
unsigned long *dims = new unsigned long[4 * _num_desktops];
- for (long i = 0; i < _num_desktops + 1; ++i) {
+ for (unsigned int i = 0; i < _num_desktops + 1; ++i) {
otk::Rect old_area = _area[i];
/*
#ifdef XINERAMA
(*it)->remaximize();
} else {
// the 'all desktops' size
- if ((*it)->desktop() == (signed) 0xffffffff)
+ if ((*it)->desktop() == 0xffffffff)
(*it)->remaximize();
}
}
otk::Property::atoms.net_client_list_stacking,
otk::Property::atoms.net_desktop_names,
otk::Property::atoms.net_close_window,
+ otk::Property::atoms.net_desktop_layout,
+ otk::Property::atoms.net_showing_desktop,
otk::Property::atoms.net_wm_name,
otk::Property::atoms.net_wm_visible_name,
otk::Property::atoms.net_wm_icon_name,
otk::Property::atoms.net_wm_visible_icon_name,
-/*
otk::Property::atoms.net_wm_desktop,
-*/
otk::Property::atoms.net_wm_strut,
otk::Property::atoms.net_wm_window_type,
otk::Property::atoms.net_wm_window_type_desktop,
EventData ddata(_number, client, EventAction::DisplayingWindow, 0);
openbox->bindings()->fireEvent(&ddata);
- // if on the current desktop.. (or all desktops)
- if (client->desktop() == _desktop ||
- client->desktop() == (signed)0xffffffff) {
- client->frame->show();
- }
+ client->showhide();
client->applyStartupState();
const ClientList::iterator end = _stacking.end();
// the stacking list is from highest to lowest
-// for (;it != end, ++it) {
-// if ((*it)->layer() <= client->layer() && m != *it) break;
-// }
for (; it != end && ((*it)->layer() > client->layer() || m == *it); ++it);
/*
changeStackingList();
}
-void Screen::changeDesktop(long desktop)
+void Screen::changeDesktop(unsigned int desktop)
{
- if (!(desktop >= 0 && desktop < _num_desktops)) return;
+ if (desktop >= _num_desktops) return;
- printf("Moving to desktop %ld\n", desktop);
+ printf("Moving to desktop %u\n", desktop);
- long old = _desktop;
+ unsigned int old = _desktop;
_desktop = desktop;
otk::Property::set(_info->rootWindow(),
if (old == _desktop) return;
ClientList::iterator it, end = clients.end();
- for (it = clients.begin(); it != end; ++it) {
- if ((*it)->desktop() == old) {
- (*it)->frame->hide();
- } else if ((*it)->desktop() == _desktop) {
- (*it)->frame->show();
- }
- }
+ for (it = clients.begin(); it != end; ++it)
+ (*it)->showhide();
// force the callbacks to fire
if (!openbox->focusedClient())
openbox->setFocusedClient(0);
}
-void Screen::changeNumDesktops(long num)
+void Screen::changeNumDesktops(unsigned int num)
{
assert(num > 0);
// move windows on desktops that will no longer exist!
ClientList::iterator it, end = clients.end();
for (it = clients.begin(); it != end; ++it) {
- int d = (*it)->desktop();
- if (d >= num && !(d == (signed) 0xffffffff ||
- d == Client::ICONIC_DESKTOP)) {
+ unsigned int d = (*it)->desktop();
+ if (d >= num && d != 0xffffffff) {
XEvent ce;
ce.xclient.type = ClientMessage;
ce.xclient.message_type = otk::Property::atoms.net_wm_desktop;
_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);
otk::Property::atoms.net_desktop_names,
otk::Property::utf8, &num, &_desktop_names))
_desktop_names.clear();
- while ((long)_desktop_names.size() < _num_desktops)
+ while (_desktop_names.size() < _num_desktops)
_desktop_names.push_back("Unnamed");
}
-void Screen::setDesktopName(long i, const otk::ustring &name)
+void Screen::setDesktopName(unsigned int i, const otk::ustring &name)
{
- assert(i >= 0);
-
if (i >= _num_desktops) return;
otk::Property::StringVect newnames = _desktop_names;
otk::Property::utf8, newnames);
}
+otk::ustring Screen::desktopName(unsigned int i) const
+{
+ if (i >= _num_desktops) return "";
+ return _desktop_names[i];
+}
-const otk::Rect& Screen::area(long desktop) const {
- assert(desktop >= 0 || desktop == (signed) 0xffffffff);
- assert(desktop < _num_desktops || desktop == (signed) 0xffffffff);
- if (desktop >= 0 && desktop < _num_desktops)
+const otk::Rect& Screen::area(unsigned int desktop) const {
+ assert(desktop < _num_desktops || desktop == 0xffffffff);
+ if (desktop < _num_desktops)
return _area[desktop];
else
return _area[_num_desktops];
XUninstallColormap(**otk::display, _info->colormap());
}
+void Screen::showDesktop(bool show)
+{
+ if (show == _showing_desktop) return; // no change
+
+ // save the window focus, and restore it when leaving the show-desktop mode
+ static Window saved_focus = 0;
+ if (show) {
+ Client *c = openbox->focusedClient();
+ if (c) saved_focus = c->window();
+ }
+
+ _showing_desktop = show;
+
+ ClientList::iterator it, end = clients.end();
+ for (it = clients.begin(); it != end; ++it) {
+ if ((*it)->type() == Client::Type_Desktop) {
+ if (show)
+ (*it)->focus();
+ } else
+ (*it)->showhide();
+ }
+
+ if (!show) {
+ Client *f = openbox->focusedClient();
+ if (!f || f->type() == Client::Type_Desktop) {
+ Client *c = openbox->findClient(saved_focus);
+ if (c) c->focus();
+ }
+ }
+
+ otk::Property::set(_info->rootWindow(),
+ otk::Property::atoms.net_showing_desktop,
+ otk::Property::atoms.cardinal,
+ show ? 1 : 0);
+}
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();
}
changeDesktop(e.data.l[0]);
} else if (e.message_type == otk::Property::atoms.net_number_of_desktops) {
changeNumDesktops(e.data.l[0]);
+ } else if (e.message_type == otk::Property::atoms.net_showing_desktop) {
+ showDesktop(e.data.l[0] != 0);
}
}
#ifdef DEBUG
printf("DEBUG: MAP REQUEST CAUGHT IN SCREEN. IGNORED.\n");
#endif
- } else
+ } else {
+ if (_showing_desktop)
+ showDesktop(false); // leave showing-the-desktop mode
manageWindow(e.window);
+ }
}
}