X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fscreen.cc;h=039d82050fa770004a9f2ff93ef877ba7353d33d;hb=7c32ac2b3f0bfd02a1efea1d67e5ad1c3c5be93f;hp=081b68d1a1367c7503c2094250783ee787ff7579;hpb=12108e16e166034cd1840627502280d9a1ab0b9e;p=chaz%2Fopenbox diff --git a/src/screen.cc b/src/screen.cc index 081b68d1..039d8205 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -2,6 +2,15 @@ #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 @@ -12,15 +21,6 @@ extern "C" { #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 #include #include @@ -105,12 +105,18 @@ Screen::Screen(int screen) _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; @@ -123,6 +129,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 +206,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() { @@ -217,16 +284,16 @@ 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 @@ -239,7 +306,7 @@ void Screen::updateStruts() 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 @@ -286,7 +353,7 @@ void Screen::changeWorkArea() (*it)->remaximize(); } else { // the 'all desktops' size - if ((*it)->desktop() == (signed) 0xffffffff) + if ((*it)->desktop() == 0xffffffff) (*it)->remaximize(); } } @@ -336,13 +403,13 @@ void Screen::changeSupportedAtoms() 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, @@ -537,11 +604,7 @@ void Screen::manageWindow(Window window) 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(); @@ -688,9 +751,6 @@ void Screen::raiseWindow(Client *client) 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); /* @@ -708,13 +768,13 @@ void Screen::raiseWindow(Client *client) 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(), @@ -724,20 +784,15 @@ void Screen::changeDesktop(long desktop) 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); @@ -746,9 +801,8 @@ void Screen::changeNumDesktops(long num) // 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; @@ -780,6 +834,9 @@ void Screen::changeNumDesktops(long 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); @@ -794,15 +851,13 @@ void Screen::updateDesktopNames() 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; @@ -812,11 +867,15 @@ void Screen::setDesktopName(long i, const otk::ustring &name) 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]; @@ -830,6 +889,41 @@ void Screen::installColormap(bool install) const 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) { @@ -849,6 +943,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(); } @@ -862,6 +958,8 @@ void Screen::clientMessageHandler(const XClientMessageEvent &e) 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); } } @@ -879,8 +977,11 @@ void Screen::mapRequestHandler(const XMapRequestEvent &e) #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); + } } }