X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fscreen.cc;h=16e37df61a731502f4a10349162cf3502f3fe77f;hb=b8de0b48fd32efed1fe242eaee9352cc16b2ee50;hp=a2514276d8cdb805081849e297cf835ba9f80282;hpb=4ef15148365c223b8e810611a10dc27dc5fba355;p=chaz%2Fopenbox diff --git a/src/screen.cc b/src/screen.cc index a2514276..16e37df6 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -2,6 +2,16 @@ #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" +#include "otk/util.hh" + extern "C" { #ifdef HAVE_UNISTD_H # include @@ -12,15 +22,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 @@ -66,24 +67,6 @@ Screen::Screen(int screen) XDefineCursor(**otk::display, _info->rootWindow(), openbox->cursors().session); - // XXX: initialize the screen's style - /* - otk::ustring stylepath; - python_get_string("THEME", &stylepath); - otk::Configuration sconfig(false); - sconfig.setFile(otk::expandTilde(stylepath.c_str())); - if (!sconfig.load()) { - sconfig.setFile(otk::expandTilde(DEFAULTSTYLE)); - if (!sconfig.load()) { - printf(_("Unable to load default style: %s. Aborting.\n"), DEFAULTSTYLE); - ::exit(1); - } - } - _style.load(sconfig); - */ - otk::display->renderControl(_number)-> - drawRoot(*otk::RenderStyle::style(_number)->rootColor()); - // set up notification of netwm support changeSupportedAtoms(); @@ -94,23 +77,17 @@ Screen::Screen(int screen) otk::Property::atoms.net_desktop_geometry, otk::Property::atoms.cardinal, geometry, 2); - // Set the net_desktop_names property - std::vector names; - python_get_stringlist("DESKTOP_NAMES", &names); - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_desktop_names, - otk::Property::utf8, names); - // the above set() will cause the updateDesktopNames to fire right away so - // we have a list of desktop names - _desktop = 0; - - if (!python_get_long("NUMBER_OF_DESKTOPS", (long*)&_num_desktops)) - _num_desktops = 1; - changeNumDesktops(_num_desktops); // set the hint + changeNumDesktops(4); // 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 +100,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 +177,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() { @@ -215,7 +253,7 @@ void Screen::updateStruts() for (sit = _struts.begin(); sit != send; ++sit) sit->left = sit->right = sit->top = sit->bottom = 0; - ClientList::const_iterator it, end = clients.end(); + std::list::const_iterator it, end = clients.end(); for (it = clients.begin(); it != end; ++it) { if ((*it)->iconic()) continue; // these dont count in the strut @@ -279,7 +317,7 @@ void Screen::changeWorkArea() */ if (old_area != _area[i]) { // the area has changed, adjust all the maximized windows - ClientList::iterator it, end = clients.end(); + std::list::iterator it, end = clients.end(); for (it = clients.begin(); it != end; ++it) if (i < _num_desktops) { if ((*it)->desktop() == i) @@ -336,13 +374,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, @@ -403,8 +441,8 @@ void Screen::changeClientList() windows = new Window[size]; win_it = windows; - ClientList::const_iterator it = clients.begin(); - const ClientList::const_iterator end = clients.end(); + std::list::const_iterator it = clients.begin(); + const std::list::const_iterator end = clients.end(); for (; it != end; ++it, ++win_it) *win_it = (*it)->window(); } else @@ -434,8 +472,8 @@ void Screen::changeStackingList() windows = new Window[size]; win_it = windows; - ClientList::const_reverse_iterator it = _stacking.rbegin(); - const ClientList::const_reverse_iterator end = _stacking.rend(); + std::list::const_reverse_iterator it = _stacking.rbegin(); + const std::list::const_reverse_iterator end = _stacking.rend(); for (; it != end; ++it, ++win_it) *win_it = (*it)->window(); } else @@ -619,7 +657,7 @@ void Screen::unmanageWindow(Client *client) client->_modal = false; // unfocus the client (calls the focus callbacks) - client->unfocus(); + if (client->focused()) client->unfocus(); #ifdef DEBUG printf("Unmanaged window 0x%lx frame 0x%lx\n", client->window(), framewin); @@ -637,8 +675,8 @@ void Screen::lowerWindow(Client *client) assert(!_stacking.empty()); // this would be bad - ClientList::iterator it = --_stacking.end(); - const ClientList::iterator end = _stacking.begin(); + std::list::iterator it = --_stacking.end(); + const std::list::iterator end = _stacking.begin(); if (client->modal() && client->transientFor()) { // don't let a modal window lower below its transient_for @@ -646,7 +684,8 @@ void Screen::lowerWindow(Client *client) assert(it != _stacking.end()); wins[0] = (it == _stacking.begin() ? _focuswindow : - ((*(--ClientList::const_iterator(it)))->frame->window())); + ((*(--std::list::const_iterator(it)))-> + frame->window())); wins[1] = client->frame->window(); if (wins[0] == wins[1]) return; // already right above the window @@ -680,13 +719,10 @@ void Screen::raiseWindow(Client *client) // remove the client before looking so we can't run into ourselves _stacking.remove(client); - ClientList::iterator it = _stacking.begin(); - const ClientList::iterator end = _stacking.end(); + std::list::iterator it = _stacking.begin(); + const std::list::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); /* @@ -694,7 +730,7 @@ void Screen::raiseWindow(Client *client) otherwise, we want to stack under the previous window in the stack. */ wins[0] = (it == _stacking.begin() ? _focuswindow : - ((*(--ClientList::const_iterator(it)))->frame->window())); + ((*(--std::list::const_iterator(it)))->frame->window())); wins[1] = client->frame->window(); _stacking.insert(it, client); @@ -719,7 +755,7 @@ void Screen::changeDesktop(unsigned int desktop) if (old == _desktop) return; - ClientList::iterator it, end = clients.end(); + std::list::iterator it, end = clients.end(); for (it = clients.begin(); it != end; ++it) (*it)->showhide(); @@ -735,7 +771,7 @@ void Screen::changeNumDesktops(unsigned int num) if (!(num > 0)) return; // move windows on desktops that will no longer exist! - ClientList::iterator it, end = clients.end(); + std::list::iterator it, end = clients.end(); for (it = clients.begin(); it != end; ++it) { unsigned int d = (*it)->desktop(); if (d >= num && d != 0xffffffff) { @@ -746,7 +782,7 @@ void Screen::changeNumDesktops(unsigned int num) ce.xclient.window = (*it)->window(); ce.xclient.format = 32; ce.xclient.data.l[0] = num - 1; - XSendEvent(**otk::display, _info->rootWindow(), False, + XSendEvent(**otk::display, _info->rootWindow(), false, SubstructureNotifyMask | SubstructureRedirectMask, &ce); } } @@ -770,6 +806,12 @@ void Screen::changeNumDesktops(unsigned int num) _struts.resize(_num_desktops + 1); updateStruts(); + // the number of rows/columns will differ + updateDesktopLayout(); + + // may be some unnamed desktops that we need to fill in with names + updateDesktopNames(); + // change our desktop if we're on one that no longer exists! if (_desktop >= _num_desktops) changeDesktop(_num_desktops - 1); @@ -778,7 +820,7 @@ void Screen::changeNumDesktops(unsigned int num) void Screen::updateDesktopNames() { - unsigned long num = (unsigned) -1; + unsigned long num; if (!otk::Property::get(_info->rootWindow(), otk::Property::atoms.net_desktop_names, @@ -789,18 +831,6 @@ void Screen::updateDesktopNames() } -void Screen::setDesktopName(unsigned int i, const otk::ustring &name) -{ - if (i >= _num_desktops) return; - - otk::Property::StringVect newnames = _desktop_names; - newnames[i] = name; - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_desktop_names, - otk::Property::utf8, newnames); -} - - const otk::Rect& Screen::area(unsigned int desktop) const { assert(desktop < _num_desktops || desktop == 0xffffffff); if (desktop < _num_desktops) @@ -817,6 +847,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; + + std::list::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) { @@ -836,6 +901,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(); } @@ -849,6 +916,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); } } @@ -866,8 +935,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); + } } }