Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

ob::Screen Class Reference

#include <screen.hh>

Inheritance diagram for ob::Screen:

Inheritance graph
[legend]
Collaboration diagram for ob::Screen:

Collaboration graph
[legend]
List of all members.

Detailed Description

Manages a single screen.

Definition at line 32 of file screen.hh.

Public Types

typedef std::list< otk::Strut * > StrutList
 Holds a list of otk::Strut objects.

typedef std::list< Client * > ClientList
 Holds a list of Clients.


Public Methods

 Screen (int screen)
 Constructs a new Screen object.

virtual ~Screen ()
 Destroys the Screen object.

int number () const
bool managed () const
 Returns if the screen was successfully managed.

const otk::Rectarea () const
 Returns the area of the screen not reserved by applications' Struts.

const otk::RenderStylestyle () const
 Returns the style in use on the screen.

Window focuswindow () const
 An offscreen window which gets focus when nothing else has it.

long desktop () const
 Returns the desktop being displayed.

long numDesktops () const
 Returns the number of desktops.

void updateStrut ()
 Update's the screen's combined strut of all the clients.

void manageExisting ()
 Manage any pre-existing windows on the screen.

void manageWindow (Window window)
 Manage a client window.

void unmanageWindow (Client *client)
 Unmanage a client.

void raiseWindow (Client *client)
 Raises a client window above all others in its stacking layer.

void lowerWindow (Client *client)
 Lowers a client window below all others in its stacking layer.

void setDesktopName (long i, const otk::ustring &name)
 Sets the name of a desktop by changing the root window property.

void installColormap (bool install) const
virtual void propertyHandler (const XPropertyEvent &e)
 Called when a property of a window changes.

virtual void clientMessageHandler (const XClientMessageEvent &e)
 Called when a client calls XSendEvent.

virtual void mapRequestHandler (const XMapRequestEvent &e)
 Called when a different client tries to map a window.


Public Attributes

ClientList clients
 All managed clients on the screen (in order of being mapped).


Static Public Attributes

const unsigned long event_mask

Private Methods

void calcArea ()
 Calculate the Screen::_area member.

void changeSupportedAtoms ()
 Set the list of supported NETWM atoms on the root window.

void changeClientList ()
 Set the client list on the root window.

void changeStackingList ()
 Set the client stacking list on the root window.

void changeWorkArea ()
 Set the work area hint on the root window.

void updateDesktopNames ()
 Get desktop names from the root window property.

void changeDesktop (long desktop)
 Changes to the specified desktop, displaying windows on it and hiding windows on the others.

void changeNumDesktops (long num)
 Changes the number of desktops.


Private Attributes

bool _managed
 Was Openbox able to manage the screen?

int _number
 The number of the screen on the X server.

const otk::ScreenInfo_info
 Information about this screen.

otk::RenderStyle _style
 The style with which to render on the screen.

bool _root_cmap_installed
 Is the root colormap currently installed?

otk::Rect _area
 Area usable for placement etc (total - struts).

otk::Strut _strut
 Combined strut from all of the clients' struts.

Window _focuswindow
 An offscreen window which gets focus when nothing else has it.

Window _supportwindow
 An offscreen window which shows that a NETWM compliant window manager is running.

ClientList _stacking
 A list of all managed clients on the screen, in their stacking order.

long _desktop
 The desktop currently being displayed.

long _num_desktops
 The number of desktops.

otk::Property::StringVect _desktop_names
 The names of all desktops.


Member Typedef Documentation

typedef std::list<Client*> ob::Screen::ClientList
 

Holds a list of Clients.

Definition at line 47 of file screen.hh.

typedef std::list<otk::Strut*> ob::Screen::StrutList
 

Holds a list of otk::Strut objects.

Definition at line 35 of file screen.hh.


Constructor & Destructor Documentation

ob::Screen::Screen int    screen
 

Constructs a new Screen object.

Definition at line 49 of file screen.cc.

References _, _desktop, _focuswindow, _info, _managed, _num_desktops, _style, otk::Property::atoms, ob::Openbox::bindings(), calcArea(), changeClientList(), changeDesktop(), changeNumDesktops(), changeSupportedAtoms(), ob::Openbox::cursors(), otk::ScreenInfo::depth(), ob::Bindings::fireEvent(), otk::ScreenInfo::height(), ob::openbox, ob::python_get_long(), ob::python_get_stringlist(), otk::EventDispatcher::registerHandler(), otk::RenderStyle::rootColor(), otk::ScreenInfo::rootWindow(), ob::Cursors::session, otk::Property::set(), otk::Property::utf8, otk::ScreenInfo::visual(), and otk::ScreenInfo::width().

00050   : WidgetBase(WidgetBase::Type_Root),
00051     _number(screen),
00052     _style(screen, "")
00053 {
00054   assert(screen >= 0); assert(screen < ScreenCount(**otk::display));
00055   _info = otk::display->screenInfo(screen);
00056 
00057   ::running = false;
00058   XErrorHandler old = XSetErrorHandler(::anotherWMRunning);
00059   XSelectInput(**otk::display, _info->rootWindow(),
00060                Screen::event_mask);
00061   XSync(**otk::display, false);
00062   XSetErrorHandler(old);
00063 
00064   _managed = !::running;
00065   if (! _managed) return; // was unable to manage the screen
00066 
00067   printf(_("Managing screen %d: visual 0x%lx, depth %d\n"),
00068          _number, XVisualIDFromVisual(_info->visual()), _info->depth());
00069 
00070   otk::Property::set(_info->rootWindow(), otk::Property::atoms.openbox_pid,
00071                      otk::Property::atoms.cardinal, (unsigned long) getpid());
00072 
00073   // set the mouse cursor for the root window (the default cursor)
00074   XDefineCursor(**otk::display, _info->rootWindow(),
00075                 openbox->cursors().session);
00076 
00077   // XXX: initialize the screen's style
00078   /*
00079   otk::ustring stylepath;
00080   python_get_string("THEME", &stylepath);
00081   otk::Configuration sconfig(false);
00082   sconfig.setFile(otk::expandTilde(stylepath.c_str()));
00083   if (!sconfig.load()) {
00084     sconfig.setFile(otk::expandTilde(DEFAULTSTYLE));
00085     if (!sconfig.load()) {
00086       printf(_("Unable to load default style: %s. Aborting.\n"), DEFAULTSTYLE);
00087       ::exit(1);
00088     }
00089   }
00090   _style.load(sconfig);
00091   */
00092   otk::display->renderControl(_number)->drawRoot(*_style.rootColor());
00093 
00094   // set up notification of netwm support
00095   changeSupportedAtoms();
00096 
00097   // Set the netwm properties for geometry
00098   unsigned long geometry[] = { _info->width(),
00099                                _info->height() };
00100   otk::Property::set(_info->rootWindow(),
00101                      otk::Property::atoms.net_desktop_geometry,
00102                      otk::Property::atoms.cardinal, geometry, 2);
00103 
00104   // Set the net_desktop_names property
00105   std::vector<otk::ustring> names;
00106   python_get_stringlist("DESKTOP_NAMES", &names);
00107   otk::Property::set(_info->rootWindow(),
00108                      otk::Property::atoms.net_desktop_names,
00109                      otk::Property::utf8, names);
00110   // the above set() will cause the updateDesktopNames to fire right away so
00111   // we have a list of desktop names
00112 
00113   _desktop = 0;
00114   
00115   if (!python_get_long("NUMBER_OF_DESKTOPS", &_num_desktops))
00116     _num_desktops = 1;
00117   changeNumDesktops(_num_desktops); // set the hint
00118 
00119   changeDesktop(0); // set the hint
00120 
00121   // create the window which gets focus when no clients get it
00122   XSetWindowAttributes attr;
00123   attr.override_redirect = true;
00124   _focuswindow = XCreateWindow(**otk::display, _info->rootWindow(),
00125                                -100, -100, 1, 1, 0, 0, InputOnly,
00126                                _info->visual(), CWOverrideRedirect, &attr);
00127   XMapRaised(**otk::display, _focuswindow);
00128   
00129   // these may be further updated if any pre-existing windows are found in
00130   // the manageExising() function
00131   changeClientList();  // initialize the client lists, which will be empty
00132   calcArea();          // initialize the available working area
00133 
00134   // register this class as the event handler for the root window
00135   openbox->registerHandler(_info->rootWindow(), this);
00136 
00137   // call the python Startup callbacks
00138   EventData data(_number, 0, EventAction::Startup, 0);
00139   openbox->bindings()->fireEvent(&data);
00140 }

ob::Screen::~Screen   [virtual]
 

Destroys the Screen object.

Definition at line 143 of file screen.cc.

References _info, _managed, ob::Openbox::bindings(), clients, ob::Bindings::fireEvent(), ob::openbox, otk::ScreenInfo::rootWindow(), and unmanageWindow().

00144 {
00145   if (! _managed) return;
00146 
00147   XSelectInput(**otk::display, _info->rootWindow(), NoEventMask);
00148   
00149   // unmanage all windows
00150   while (!clients.empty())
00151     unmanageWindow(clients.front());
00152 
00153   // call the python Shutdown callbacks
00154   EventData data(_number, 0, EventAction::Shutdown, 0);
00155   openbox->bindings()->fireEvent(&data);
00156 
00157   XDestroyWindow(**otk::display, _focuswindow);
00158   XDestroyWindow(**otk::display, _supportwindow);
00159 }


Member Function Documentation

const otk::Rect& ob::Screen::area   const [inline]
 

Returns the area of the screen not reserved by applications' Struts.

Definition at line 148 of file screen.hh.

Referenced by ob::Client::fullscreen(), and ob::Client::maximize().

00148 { return _area; }

void ob::Screen::calcArea   [private]
 

Calculate the Screen::_area member.

Definition at line 226 of file screen.cc.

References _area, _info, _strut, otk::Strut::bottom, changeWorkArea(), clients, otk::ScreenInfo::height(), otk::Strut::left, otk::Strut::right, otk::Rect::setRect(), otk::Strut::top, and otk::ScreenInfo::width().

Referenced by Screen(), and updateStrut().

00227 {
00228   otk::Rect old_area = _area;
00229 
00230 /*
00231 #ifdef    XINERAMA
00232   // reset to the full areas
00233   if (isXineramaActive())
00234     xineramaUsableArea = getXineramaAreas();
00235 #endif // XINERAMA
00236 */
00237   
00238   _area.setRect(_strut.left, _strut.top,
00239                 _info->width() - (_strut.left + _strut.right),
00240                 _info->height() - (_strut.top + _strut.bottom));
00241 
00242 /*
00243 #ifdef    XINERAMA
00244   if (isXineramaActive()) {
00245     // keep each of the ximerama-defined areas inside the strut
00246     RectList::iterator xit, xend = xineramaUsableArea.end();
00247     for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
00248       if (xit->x() < usableArea.x()) {
00249         xit->setX(usableArea.x());
00250         xit->setWidth(xit->width() - usableArea.x());
00251       }
00252       if (xit->y() < usableArea.y()) {
00253         xit->setY(usableArea.y());
00254         xit->setHeight(xit->height() - usableArea.y());
00255       }
00256       if (xit->x() + xit->width() > usableArea.width())
00257         xit->setWidth(usableArea.width() - xit->x());
00258       if (xit->y() + xit->height() > usableArea.height())
00259         xit->setHeight(usableArea.height() - xit->y());
00260     }
00261   }
00262 #endif // XINERAMA
00263 */
00264  
00265   if (old_area != _area) {
00266     // the area has changed, adjust all the maximized windows
00267     ClientList::iterator it, end = clients.end();
00268     for (it = clients.begin(); it != end; ++it)
00269       (*it)->remaximize();
00270   }
00271 
00272   changeWorkArea();
00273 }

void ob::Screen::changeClientList   [private]
 

Set the client list on the root window.

Sets the _NET_CLIENT_LIST root window property.
Also calls Screen::updateStackingList.

Definition at line 363 of file screen.cc.

References _info, otk::Property::atoms, changeStackingList(), clients, otk::ScreenInfo::rootWindow(), and otk::Property::set().

Referenced by manageWindow(), Screen(), and unmanageWindow().

00364 {
00365   Window *windows;
00366   unsigned int size = clients.size();
00367 
00368   // create an array of the window ids
00369   if (size > 0) {
00370     Window *win_it;
00371     
00372     windows = new Window[size];
00373     win_it = windows;
00374     ClientList::const_iterator it = clients.begin();
00375     const ClientList::const_iterator end = clients.end();
00376     for (; it != end; ++it, ++win_it)
00377       *win_it = (*it)->window();
00378   } else
00379     windows = (Window*) 0;
00380 
00381   otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_client_list,
00382                      otk::Property::atoms.window, windows, size);
00383 
00384   if (size)
00385     delete [] windows;
00386 
00387   changeStackingList();
00388 }

void ob::Screen::changeDesktop long    desktop [private]
 

Changes to the specified desktop, displaying windows on it and hiding windows on the others.

Parameters:
desktop The number of the desktop to switch to (starts from 0). If the desktop is out of valid range, it is ignored.

Definition at line 704 of file screen.cc.

References _desktop, _info, _num_desktops, otk::Property::atoms, clients, ob::Openbox::focusedClient(), ob::openbox, otk::ScreenInfo::rootWindow(), otk::Property::set(), and ob::Openbox::setFocusedClient().

Referenced by changeNumDesktops(), clientMessageHandler(), and Screen().

00705 {
00706   if (!(desktop >= 0 && desktop < _num_desktops)) return;
00707 
00708   printf("Moving to desktop %ld\n", desktop);
00709   
00710   long old = _desktop;
00711   
00712   _desktop = desktop;
00713   otk::Property::set(_info->rootWindow(),
00714                      otk::Property::atoms.net_current_desktop,
00715                      otk::Property::atoms.cardinal, _desktop);
00716 
00717   if (old == _desktop) return;
00718 
00719   ClientList::iterator it, end = clients.end();
00720   for (it = clients.begin(); it != end; ++it) {
00721     if ((*it)->desktop() == old) {
00722       (*it)->frame->hide();
00723     } else if ((*it)->desktop() == _desktop) {
00724       (*it)->frame->show();
00725     }
00726   }
00727 
00728   // force the callbacks to fire
00729   if (!openbox->focusedClient())
00730     openbox->setFocusedClient(0);
00731 }

void ob::Screen::changeNumDesktops long    num [private]
 

Changes the number of desktops.

Parameters:
num The number of desktops that should exist. This value must be greater than 0 or it will be ignored.

Definition at line 733 of file screen.cc.

References _desktop, _info, _num_desktops, otk::Property::atoms, changeDesktop(), changeWorkArea(), clients, otk::ScreenInfo::rootWindow(), and otk::Property::set().

Referenced by clientMessageHandler(), and Screen().

00734 {
00735   assert(num > 0);
00736   
00737   if (!(num > 0)) return;
00738 
00739   // move windows on desktops that will no longer exist!
00740   ClientList::iterator it, end = clients.end();
00741   for (it = clients.begin(); it != end; ++it) {
00742     int d = (*it)->desktop();
00743     if (d >= num && !(d == (signed) 0xffffffff ||
00744                       d == Client::ICONIC_DESKTOP)) {
00745       XEvent ce;
00746       ce.xclient.type = ClientMessage;
00747       ce.xclient.message_type = otk::Property::atoms.net_wm_desktop;
00748       ce.xclient.display = **otk::display;
00749       ce.xclient.window = (*it)->window();
00750       ce.xclient.format = 32;
00751       ce.xclient.data.l[0] = num - 1;
00752       XSendEvent(**otk::display, _info->rootWindow(), False,
00753                  SubstructureNotifyMask | SubstructureRedirectMask, &ce);
00754     }
00755   }
00756 
00757   _num_desktops = num;
00758   otk::Property::set(_info->rootWindow(),
00759                      otk::Property::atoms.net_number_of_desktops,
00760                      otk::Property::atoms.cardinal, _num_desktops);
00761 
00762   // set the viewport hint
00763   unsigned long *viewport = new unsigned long[_num_desktops * 2];
00764   memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2);
00765   otk::Property::set(_info->rootWindow(),
00766                      otk::Property::atoms.net_desktop_viewport,
00767                      otk::Property::atoms.cardinal,
00768                      viewport, _num_desktops * 2);
00769   delete [] viewport;
00770 
00771   // update the work area hint
00772   changeWorkArea();
00773 
00774   // change our desktop if we're on one that no longer exists!
00775   if (_desktop >= num)
00776     changeDesktop(num - 1);
00777 }

void ob::Screen::changeStackingList   [private]
 

Set the client stacking list on the root window.

Set the _NET_CLIENT_LIST_STACKING root window property.

Definition at line 391 of file screen.cc.

References _info, _stacking, otk::Property::atoms, clients, otk::ScreenInfo::rootWindow(), and otk::Property::set().

Referenced by changeClientList(), lowerWindow(), and raiseWindow().

00392 {
00393   Window *windows;
00394   unsigned int size = _stacking.size();
00395 
00396   assert(size == clients.size()); // just making sure.. :)
00397 
00398   
00399   // create an array of the window ids (from bottom to top, reverse order!)
00400   if (size > 0) {
00401     Window *win_it;
00402     
00403     windows = new Window[size];
00404     win_it = windows;
00405     ClientList::const_reverse_iterator it = _stacking.rbegin();
00406     const ClientList::const_reverse_iterator end = _stacking.rend();
00407     for (; it != end; ++it, ++win_it)
00408       *win_it = (*it)->window();
00409   } else
00410     windows = (Window*) 0;
00411 
00412   otk::Property::set(_info->rootWindow(),
00413                      otk::Property::atoms.net_client_list_stacking,
00414                      otk::Property::atoms.window, windows, size);
00415 
00416   if (size)
00417     delete [] windows;
00418 }

void ob::Screen::changeSupportedAtoms   [private]
 

Set the list of supported NETWM atoms on the root window.

Definition at line 276 of file screen.cc.

References _info, _supportwindow, otk::Property::atoms, otk::ScreenInfo::rootWindow(), and otk::Property::set().

Referenced by Screen().

00277 {
00278   // create the netwm support window
00279   _supportwindow = XCreateSimpleWindow(**otk::display,
00280                                        _info->rootWindow(),
00281                                        0, 0, 1, 1, 0, 0, 0);
00282 
00283   // set supporting window
00284   otk::Property::set(_info->rootWindow(),
00285                      otk::Property::atoms.net_supporting_wm_check,
00286                      otk::Property::atoms.window, _supportwindow);
00287 
00288   //set properties on the supporting window
00289   otk::Property::set(_supportwindow, otk::Property::atoms.net_wm_name,
00290                      otk::Property::utf8, "Openbox");
00291   otk::Property::set(_supportwindow,
00292                      otk::Property::atoms.net_supporting_wm_check,
00293                      otk::Property::atoms.window, _supportwindow);
00294 
00295   
00296   Atom supported[] = {
00297     otk::Property::atoms.net_current_desktop,
00298     otk::Property::atoms.net_number_of_desktops,
00299     otk::Property::atoms.net_desktop_geometry,
00300     otk::Property::atoms.net_desktop_viewport,
00301     otk::Property::atoms.net_active_window,
00302     otk::Property::atoms.net_workarea,
00303     otk::Property::atoms.net_client_list,
00304     otk::Property::atoms.net_client_list_stacking,
00305     otk::Property::atoms.net_desktop_names,
00306     otk::Property::atoms.net_close_window,
00307     otk::Property::atoms.net_wm_name,
00308     otk::Property::atoms.net_wm_visible_name,
00309     otk::Property::atoms.net_wm_icon_name,
00310     otk::Property::atoms.net_wm_visible_icon_name,
00311 /*
00312     otk::Property::atoms.net_wm_desktop,
00313 */
00314     otk::Property::atoms.net_wm_strut,
00315     otk::Property::atoms.net_wm_window_type,
00316     otk::Property::atoms.net_wm_window_type_desktop,
00317     otk::Property::atoms.net_wm_window_type_dock,
00318     otk::Property::atoms.net_wm_window_type_toolbar,
00319     otk::Property::atoms.net_wm_window_type_menu,
00320     otk::Property::atoms.net_wm_window_type_utility,
00321     otk::Property::atoms.net_wm_window_type_splash,
00322     otk::Property::atoms.net_wm_window_type_dialog,
00323     otk::Property::atoms.net_wm_window_type_normal,
00324 /*
00325     otk::Property::atoms.net_wm_moveresize,
00326     otk::Property::atoms.net_wm_moveresize_size_topleft,
00327     otk::Property::atoms.net_wm_moveresize_size_topright,
00328     otk::Property::atoms.net_wm_moveresize_size_bottomleft,
00329     otk::Property::atoms.net_wm_moveresize_size_bottomright,
00330     otk::Property::atoms.net_wm_moveresize_move,
00331 */
00332     otk::Property::atoms.net_wm_allowed_actions,
00333     otk::Property::atoms.net_wm_action_move,
00334     otk::Property::atoms.net_wm_action_resize,
00335     otk::Property::atoms.net_wm_action_minimize,
00336     otk::Property::atoms.net_wm_action_shade,
00337 /*    otk::Property::atoms.net_wm_action_stick,*/
00338     otk::Property::atoms.net_wm_action_maximize_horz,
00339     otk::Property::atoms.net_wm_action_maximize_vert,
00340     otk::Property::atoms.net_wm_action_fullscreen,
00341     otk::Property::atoms.net_wm_action_change_desktop,
00342     otk::Property::atoms.net_wm_action_close,
00343 
00344     otk::Property::atoms.net_wm_state,
00345     otk::Property::atoms.net_wm_state_modal,
00346     otk::Property::atoms.net_wm_state_maximized_vert,
00347     otk::Property::atoms.net_wm_state_maximized_horz,
00348     otk::Property::atoms.net_wm_state_shaded,
00349     otk::Property::atoms.net_wm_state_skip_taskbar,
00350     otk::Property::atoms.net_wm_state_skip_pager,
00351     otk::Property::atoms.net_wm_state_hidden,
00352     otk::Property::atoms.net_wm_state_fullscreen,
00353     otk::Property::atoms.net_wm_state_above,
00354     otk::Property::atoms.net_wm_state_below,
00355   };
00356   const int num_supported = sizeof(supported)/sizeof(Atom);
00357 
00358   otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_supported,
00359                      otk::Property::atoms.atom, supported, num_supported);
00360 }

void ob::Screen::changeWorkArea   [private]
 

Set the work area hint on the root window.

Set the _NET_WORKAREA root window property.

Definition at line 421 of file screen.cc.

References _area, _info, _num_desktops, otk::Property::atoms, otk::Rect::height(), otk::ScreenInfo::rootWindow(), otk::Property::set(), otk::Rect::width(), otk::Rect::x(), and otk::Rect::y().

Referenced by calcArea(), and changeNumDesktops().

00421                             {
00422   unsigned long *dims = new unsigned long[4 * _num_desktops];
00423   for (long i = 0; i < _num_desktops; ++i) {
00424     dims[(i * 4) + 0] = _area.x();
00425     dims[(i * 4) + 1] = _area.y();
00426     dims[(i * 4) + 2] = _area.width();
00427     dims[(i * 4) + 3] = _area.height();
00428   }
00429   otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_workarea,
00430                      otk::Property::atoms.cardinal, dims, 4 * _num_desktops);
00431   delete [] dims;
00432 }

void ob::Screen::clientMessageHandler const XClientMessageEvent &    e [virtual]
 

Called when a client calls XSendEvent.

Some types of client messages are filtered out and sent to more specific event handler functions.

Reimplemented from otk::EventHandler.

Definition at line 837 of file screen.cc.

References otk::Property::atoms, changeDesktop(), changeNumDesktops(), and otk::EventHandler::clientMessageHandler().

00838 {
00839   otk::EventHandler::clientMessageHandler(e);
00840 
00841   if (e.format != 32) return;
00842 
00843   if (e.message_type == otk::Property::atoms.net_current_desktop) {
00844     changeDesktop(e.data.l[0]);
00845   } else if (e.message_type == otk::Property::atoms.net_number_of_desktops) {
00846     changeNumDesktops(e.data.l[0]);
00847   }
00848 }

long ob::Screen::desktop   const [inline]
 

Returns the desktop being displayed.

Definition at line 154 of file screen.hh.

Referenced by ob::Client::clientMessageHandler(), ob::Client::getDesktop(), ob::Client::mapRequestHandler(), ob::Client::setDesktop(), and ob::Client::setWMState().

00154 { return _desktop; }

Window ob::Screen::focuswindow   const [inline]
 

An offscreen window which gets focus when nothing else has it.

Definition at line 152 of file screen.hh.

Referenced by ob::Openbox::setFocusedClient().

00152 { return _focuswindow; }

void ob::Screen::installColormap bool    install const
 

Definition at line 807 of file screen.cc.

References _info, and otk::ScreenInfo::colormap().

Referenced by ob::Openbox::setFocusedClient().

00808 {
00809   if (install)
00810     XInstallColormap(**otk::display, _info->colormap());
00811   else
00812     XUninstallColormap(**otk::display, _info->colormap());
00813 }

void ob::Screen::lowerWindow Client   client
 

Lowers a client window below all others in its stacking layer.

Definition at line 634 of file screen.cc.

References _focuswindow, _stacking, changeStackingList(), ob::Client::frame, ob::Client::layer(), ob::Client::modal(), ob::Client::transientFor(), and otk::Widget::window().

Referenced by ob::Client::configureRequestHandler().

00635 {
00636   Window wins[2];  // only ever restack 2 windows.
00637 
00638   assert(!_stacking.empty()); // this would be bad
00639 
00640   ClientList::iterator it = --_stacking.end();
00641   const ClientList::iterator end = _stacking.begin();
00642 
00643   if (client->modal() && client->transientFor()) {
00644     // don't let a modal window lower below its transient_for
00645     it = std::find(_stacking.begin(), _stacking.end(), client->transientFor());
00646     assert(it != _stacking.end());
00647 
00648     wins[0] = (it == _stacking.begin() ? _focuswindow :
00649                ((*(--ClientList::const_iterator(it)))->frame->window()));
00650     wins[1] = client->frame->window();
00651     if (wins[0] == wins[1]) return; // already right above the window
00652 
00653     _stacking.remove(client);
00654     _stacking.insert(it, client);
00655   } else {
00656     for (; it != end && (*it)->layer() < client->layer(); --it);
00657     if (*it == client) return;          // already the bottom, return
00658 
00659     wins[0] = (*it)->frame->window();
00660     wins[1] = client->frame->window();
00661 
00662     _stacking.remove(client);
00663     _stacking.insert(++it, client);
00664   }
00665 
00666   XRestackWindows(**otk::display, wins, 2);
00667   changeStackingList();
00668 }

bool ob::Screen::managed   const [inline]
 

Returns if the screen was successfully managed.

If this is false, then the screen should be deleted and should NOT be used.

Definition at line 146 of file screen.hh.

Referenced by ob::Openbox::Openbox().

00146 { return _managed; }

void ob::Screen::manageExisting  
 

Manage any pre-existing windows on the screen.

Definition at line 162 of file screen.cc.

References _info, manageWindow(), and otk::ScreenInfo::rootWindow().

00163 {
00164   unsigned int i, j, nchild;
00165   Window r, p, *children;
00166   XQueryTree(**otk::display, _info->rootWindow(), &r, &p,
00167              &children, &nchild);
00168 
00169   // preen the window list of all icon windows... for better dockapp support
00170   for (i = 0; i < nchild; i++) {
00171     if (children[i] == None) continue;
00172 
00173     XWMHints *wmhints = XGetWMHints(**otk::display,
00174                                     children[i]);
00175 
00176     if (wmhints) {
00177       if ((wmhints->flags & IconWindowHint) &&
00178           (wmhints->icon_window != children[i])) {
00179         for (j = 0; j < nchild; j++) {
00180           if (children[j] == wmhints->icon_window) {
00181             children[j] = None;
00182             break;
00183           }
00184         }
00185       }
00186 
00187       XFree(wmhints);
00188     }
00189   }
00190 
00191   // manage shown windows
00192   for (i = 0; i < nchild; ++i) {
00193     if (children[i] == None)
00194       continue;
00195 
00196     XWindowAttributes attrib;
00197     if (XGetWindowAttributes(**otk::display, children[i], &attrib)) {
00198       if (attrib.override_redirect) continue;
00199 
00200       if (attrib.map_state != IsUnmapped) {
00201         manageWindow(children[i]);
00202       }
00203     }
00204   }
00205 
00206   XFree(children);
00207 }

void ob::Screen::manageWindow Window    window
 

Manage a client window.

This gives the window a frame, reparents it, selects events on it, etc.

Definition at line 435 of file screen.cc.

References _desktop, _stacking, ob::Openbox::addClient(), ob::Client::applyStartupState(), ob::Openbox::bindings(), ob::Frame::button_alldesk(), ob::Frame::button_close(), ob::Frame::button_iconify(), ob::Frame::button_max(), changeClientList(), otk::EventDispatcher::clearHandler(), clients, ob::Client::desktop(), ob::Bindings::fireEvent(), ob::Client::frame, ob::Bindings::grabButtons(), ob::Frame::grabClient(), ob::Frame::grip_left(), ob::Frame::grip_right(), ob::Frame::handle(), ob::Frame::label(), ob::openbox, ob::Frame::plate(), raiseWindow(), otk::EventDispatcher::registerHandler(), otk::Widget::show(), ob::Openbox::state(), ob::Frame::titlebar(), ob::Client::toggleClientBorder(), updateStrut(), and otk::Widget::window().

Referenced by manageExisting(), and mapRequestHandler().

00436 {
00437   Client *client = 0;
00438   XWMHints *wmhint;
00439   XSetWindowAttributes attrib_set;
00440   XEvent e;
00441   XWindowAttributes attrib;
00442 
00443   otk::display->grab();
00444 
00445   // check if it has already been unmapped by the time we started mapping
00446   // the grab does a sync so we don't have to here
00447   if (XCheckTypedWindowEvent(**otk::display, window, DestroyNotify, &e) ||
00448       XCheckTypedWindowEvent(**otk::display, window, UnmapNotify, &e)) {
00449     XPutBackEvent(**otk::display, &e);
00450     
00451     otk::display->ungrab();
00452     return; // don't manage it
00453   }
00454   
00455   if (!XGetWindowAttributes(**otk::display, window, &attrib) ||
00456       attrib.override_redirect) {
00457     otk::display->ungrab();
00458     return; // don't manage it
00459   }
00460   
00461   // is the window a docking app
00462   if ((wmhint = XGetWMHints(**otk::display, window))) {
00463     if ((wmhint->flags & StateHint) &&
00464         wmhint->initial_state == WithdrawnState) {
00465       //slit->addClient(w); // XXX: make dock apps work!
00466 
00467       otk::display->ungrab();
00468       XFree(wmhint);
00469       return;
00470     }
00471     XFree(wmhint);
00472   }
00473 
00474   // choose the events we want to receive on the CLIENT window
00475   attrib_set.event_mask = Client::event_mask;
00476   attrib_set.do_not_propagate_mask = Client::no_propagate_mask;
00477   XChangeWindowAttributes(**otk::display, window,
00478                           CWEventMask|CWDontPropagate, &attrib_set);
00479 
00480   // create the Client class, which gets all of the hints on the window
00481   client = new Client(_number, window);
00482   // register for events
00483   openbox->registerHandler(window, client);
00484   // add to the wm's map
00485   openbox->addClient(window, client);
00486 
00487   // we dont want a border on the client
00488   client->toggleClientBorder(false);
00489   
00490   // specify that if we exit, the window should not be destroyed and should be
00491   // reparented back to root automatically
00492   XChangeSaveSet(**otk::display, window, SetModeInsert);
00493 
00494   // create the decoration frame for the client window
00495   client->frame = new Frame(client, &_style);
00496   // register the plate for events (map req's)
00497   // this involves removing itself from the handler list first, since it is
00498   // auto added to the list, being a widget. we won't get any events on the
00499   // plate except for events for the client (SubstructureRedirectMask)
00500   openbox->clearHandler(client->frame->plate());
00501   openbox->registerHandler(client->frame->plate(), client);
00502 
00503   // add to the wm's map
00504   openbox->addClient(client->frame->window(), client);
00505   openbox->addClient(client->frame->plate(), client);
00506   openbox->addClient(client->frame->titlebar(), client);
00507   openbox->addClient(client->frame->label(), client);
00508   openbox->addClient(client->frame->button_max(), client);
00509   openbox->addClient(client->frame->button_iconify(), client);
00510   openbox->addClient(client->frame->button_alldesk(), client);
00511   openbox->addClient(client->frame->button_close(), client);
00512   openbox->addClient(client->frame->handle(), client);
00513   openbox->addClient(client->frame->grip_left(), client);
00514   openbox->addClient(client->frame->grip_right(), client);
00515 
00516   // reparent the client to the frame
00517   client->frame->grabClient();
00518 
00519   if (openbox->state() != Openbox::State_Starting) {
00520     // position the window intelligenty .. hopefully :)
00521     // call the python PLACEWINDOW binding
00522     EventData data(_number, client, EventAction::PlaceWindow, 0);
00523     openbox->bindings()->fireEvent(&data);
00524   }
00525 
00526   EventData ddata(_number, client, EventAction::DisplayingWindow, 0);
00527   openbox->bindings()->fireEvent(&ddata);
00528 
00529   // if on the current desktop.. (or all desktops)
00530   if (client->desktop() == _desktop ||
00531       client->desktop() == (signed)0xffffffff) {
00532     client->frame->show();
00533   }
00534 
00535   client->applyStartupState();
00536 
00537   otk::display->ungrab();
00538 
00539   // add to the screen's list
00540   clients.push_back(client);
00541   // once the client is in the list, update our strut to include the new
00542   // client's (it is good that this happens after window placement!)
00543   updateStrut();
00544   // this puts into the stacking order, then raises it
00545   _stacking.push_back(client);
00546   raiseWindow(client);
00547   // update the root properties
00548   changeClientList();
00549 
00550   openbox->bindings()->grabButtons(true, client);
00551 
00552   EventData ndata(_number, client, EventAction::NewWindow, 0);
00553   openbox->bindings()->fireEvent(&ndata);
00554 
00555 #ifdef DEBUG
00556   printf("Managed window 0x%lx frame 0x%lx\n",
00557          window, client->frame->window());
00558 #endif
00559 }

void ob::Screen::mapRequestHandler const XMapRequestEvent &    e [virtual]
 

Called when a different client tries to map a window.

Reimplemented from otk::EventHandler.

Definition at line 851 of file screen.cc.

References ob::Openbox::findClient(), manageWindow(), otk::EventHandler::mapRequestHandler(), and ob::openbox.

00852 {
00853   otk::EventHandler::mapRequestHandler(e);
00854 
00855 #ifdef    DEBUG
00856   printf("MapRequest for 0x%lx\n", e.window);
00857 #endif // DEBUG
00858 
00859   Client *c = openbox->findClient(e.window);
00860   if (c) {
00861 #ifdef DEBUG
00862     printf("DEBUG: MAP REQUEST CAUGHT IN SCREEN. IGNORED.\n");
00863 #endif
00864   } else
00865     manageWindow(e.window);
00866 }

int ob::Screen::number   const [inline]
 

Definition at line 139 of file screen.hh.

Referenced by ob::Openbox::setFocusedClient().

00139 { return _number; }

long ob::Screen::numDesktops   const [inline]
 

Returns the number of desktops.

Definition at line 156 of file screen.hh.

00156 { return _num_desktops; }

void ob::Screen::propertyHandler const XPropertyEvent &    e [virtual]
 

Called when a property of a window changes.

Reimplemented from otk::EventHandler.

Definition at line 816 of file screen.cc.

References _info, otk::Property::atoms, otk::EventHandler::propertyHandler(), otk::ScreenInfo::rootWindow(), and updateDesktopNames().

00817 {
00818   otk::EventHandler::propertyHandler(e);
00819 
00820   // compress changes to a single property into a single change
00821   XEvent ce;
00822   while (XCheckTypedWindowEvent(**otk::display, _info->rootWindow(),
00823                                 e.type, &ce)) {
00824     // XXX: it would be nice to compress ALL changes to a property, not just
00825     //      changes in a row without other props between.
00826     if (ce.xproperty.atom != e.atom) {
00827       XPutBackEvent(**otk::display, &ce);
00828       break;
00829     }
00830   }
00831 
00832   if (e.atom == otk::Property::atoms.net_desktop_names)
00833     updateDesktopNames();
00834 }

void ob::Screen::raiseWindow Client   client
 

Raises a client window above all others in its stacking layer.

raiseWindow has a couple of constraints that lowerWindow does not.
1) raiseWindow can be called after changing a Client's stack layer, and the list will be reorganized properly.
2) raiseWindow guarantees that XRestackWindows() will always be called for the specified client.

Definition at line 670 of file screen.cc.

References _focuswindow, _stacking, changeStackingList(), ob::Client::frame, ob::Client::layer(), ob::Client::modalChild(), and otk::Widget::window().

Referenced by ob::Client::calcLayer(), ob::Client::clientMessageHandler(), ob::Client::configureRequestHandler(), ob::Client::fullscreen(), and manageWindow().

00671 {
00672   Window wins[2];  // only ever restack 2 windows.
00673 
00674   assert(!_stacking.empty()); // this would be bad
00675 
00676   // remove the client before looking so we can't run into ourselves
00677   _stacking.remove(client);
00678   
00679   ClientList::iterator it = _stacking.begin();
00680   const ClientList::iterator end = _stacking.end();
00681 
00682   // the stacking list is from highest to lowest
00683   for (; it != end && (*it)->layer() > client->layer(); ++it);
00684 
00685   /*
00686     if our new position is the top, we want to stack under the _focuswindow
00687     otherwise, we want to stack under the previous window in the stack.
00688   */
00689   wins[0] = (it == _stacking.begin() ? _focuswindow :
00690              ((*(--ClientList::const_iterator(it)))->frame->window()));
00691   wins[1] = client->frame->window();
00692 
00693   _stacking.insert(it, client);
00694 
00695   XRestackWindows(**otk::display, wins, 2);
00696 
00697   // if the window has a modal child, then raise it after us to put it on top
00698   if (client->modalChild())
00699     raiseWindow(client->modalChild());
00700   else
00701     changeStackingList(); // no need to do this twice!
00702 }

void ob::Screen::setDesktopName long    i,
const otk::ustring   name
 

Sets the name of a desktop by changing the root window property.

Parameters:
i The index of the desktop to set the name for (starts at 0)
name The name to set for the desktop If the index is too large, it is simply ignored.

Definition at line 793 of file screen.cc.

References _desktop_names, _info, _num_desktops, otk::Property::atoms, otk::ScreenInfo::rootWindow(), otk::Property::set(), otk::Property::StringVect, and otk::Property::utf8.

00794 {
00795   assert(i >= 0);
00796 
00797   if (i >= _num_desktops) return;
00798 
00799   otk::Property::StringVect newnames = _desktop_names;
00800   newnames[i] = name;
00801   otk::Property::set(_info->rootWindow(),
00802                      otk::Property::atoms.net_desktop_names,
00803                      otk::Property::utf8, newnames);
00804 }

const otk::RenderStyle* ob::Screen::style   const [inline]
 

Returns the style in use on the screen.

Definition at line 150 of file screen.hh.

00150 { return &_style; }

void ob::Screen::unmanageWindow Client   client
 

Unmanage a client.

This removes the window's frame, reparents it to root, unselects events on it, etc.

Parameters:
client The client to unmanage

Definition at line 562 of file screen.cc.

References _stacking, ob::Openbox::bindings(), ob::Frame::button_alldesk(), ob::Frame::button_close(), ob::Frame::button_iconify(), ob::Frame::button_max(), changeClientList(), otk::EventDispatcher::clearHandler(), clients, ob::Bindings::fireEvent(), ob::Client::frame, ob::Bindings::grabButtons(), ob::Frame::grip_left(), ob::Frame::grip_right(), ob::Frame::handle(), otk::Widget::hide(), ob::Frame::label(), ob::openbox, ob::Frame::plate(), ob::Frame::releaseClient(), ob::Openbox::removeClient(), ob::Client::setModal(), ob::Frame::titlebar(), ob::Client::toggleClientBorder(), ob::Client::unfocus(), updateStrut(), otk::Widget::window(), and ob::Client::window().

Referenced by ob::Client::destroyHandler(), ob::Client::reparentHandler(), ob::Client::unmapHandler(), and ~Screen().

00563 {
00564   Frame *frame = client->frame;
00565 
00566   // call the python CLOSEWINDOW binding 
00567   EventData data(_number, client, EventAction::CloseWindow, 0);
00568   openbox->bindings()->fireEvent(&data);
00569 
00570   openbox->bindings()->grabButtons(false, client);
00571 
00572   // remove from the wm's map
00573   openbox->removeClient(client->window());
00574   openbox->removeClient(frame->window());
00575   openbox->removeClient(frame->plate());
00576   openbox->removeClient(frame->titlebar());
00577   openbox->removeClient(frame->label());
00578   openbox->removeClient(frame->button_max());
00579   openbox->removeClient(frame->button_iconify());
00580   openbox->removeClient(frame->button_alldesk());
00581   openbox->removeClient(frame->button_close());
00582   openbox->removeClient(frame->handle());
00583   openbox->removeClient(frame->grip_left());
00584   openbox->removeClient(frame->grip_right());
00585   // unregister for handling events
00586   openbox->clearHandler(client->window());
00587   
00588   // remove the window from our save set
00589   XChangeSaveSet(**otk::display, client->window(), SetModeDelete);
00590 
00591   // we dont want events no more
00592   XSelectInput(**otk::display, client->window(), NoEventMask);
00593 
00594   frame->hide();
00595 
00596   // give the client its border back
00597   client->toggleClientBorder(true);
00598 
00599   // reparent the window out of the frame
00600   frame->releaseClient();
00601 
00602 #ifdef DEBUG
00603   Window framewin = client->frame->window();
00604 #endif
00605   delete client->frame;
00606   client->frame = 0;
00607 
00608   // remove from the stacking order
00609   _stacking.remove(client);
00610 
00611   // remove from the screen's list
00612   clients.remove(client);
00613 
00614   // once the client is out of the list, update our strut to remove it's
00615   // influence
00616   updateStrut();
00617 
00618   // unset modal before dropping our focus
00619   client->setModal(false);
00620   
00621   // unfocus the client (calls the focus callbacks)
00622   client->unfocus();
00623 
00624 #ifdef DEBUG
00625   printf("Unmanaged window 0x%lx frame 0x%lx\n", client->window(), framewin);
00626 #endif
00627   
00628   delete client;
00629 
00630   // update the root properties
00631   changeClientList();
00632 }

void ob::Screen::updateDesktopNames   [private]
 

Get desktop names from the root window property.

Definition at line 780 of file screen.cc.

References _desktop_names, _info, _num_desktops, otk::Property::atoms, otk::Property::get(), otk::ScreenInfo::rootWindow(), and otk::Property::utf8.

Referenced by propertyHandler().

00781 {
00782   unsigned long num = (unsigned) -1;
00783   
00784   if (!otk::Property::get(_info->rootWindow(),
00785                           otk::Property::atoms.net_desktop_names,
00786                           otk::Property::utf8, &num, &_desktop_names))
00787     _desktop_names.clear();
00788   while ((long)_desktop_names.size() < _num_desktops)
00789     _desktop_names.push_back("Unnamed");
00790 }

void ob::Screen::updateStrut  
 

Update's the screen's combined strut of all the clients.

Clients should call this whenever they change their strut.

Definition at line 210 of file screen.cc.

References _strut, otk::Strut::bottom, calcArea(), clients, otk::Strut::left, otk::Strut::right, and otk::Strut::top.

Referenced by manageWindow(), unmanageWindow(), and ob::Client::updateStrut().

00211 {
00212   _strut.left = _strut.right = _strut.top = _strut.bottom = 0;
00213 
00214   ClientList::iterator it, end = clients.end();
00215   for (it = clients.begin(); it != end; ++it) {
00216     const otk::Strut &s = (*it)->strut();
00217     _strut.left = std::max(_strut.left, s.left);
00218     _strut.right = std::max(_strut.right, s.right);
00219     _strut.top = std::max(_strut.top, s.top);
00220     _strut.bottom = std::max(_strut.bottom, s.bottom);
00221   }
00222   calcArea();
00223 }


Member Data Documentation

otk::Rect ob::Screen::_area [private]
 

Area usable for placement etc (total - struts).

Definition at line 68 of file screen.hh.

Referenced by calcArea(), and changeWorkArea().

long ob::Screen::_desktop [private]
 

The desktop currently being displayed.

Definition at line 84 of file screen.hh.

Referenced by changeDesktop(), changeNumDesktops(), manageWindow(), and Screen().

otk::Property::StringVect ob::Screen::_desktop_names [private]
 

The names of all desktops.

Definition at line 90 of file screen.hh.

Referenced by setDesktopName(), and updateDesktopNames().

Window ob::Screen::_focuswindow [private]
 

An offscreen window which gets focus when nothing else has it.

Definition at line 74 of file screen.hh.

Referenced by lowerWindow(), raiseWindow(), and Screen().

const otk::ScreenInfo* ob::Screen::_info [private]
 

Information about this screen.

Definition at line 59 of file screen.hh.

Referenced by calcArea(), changeClientList(), changeDesktop(), changeNumDesktops(), changeStackingList(), changeSupportedAtoms(), changeWorkArea(), installColormap(), manageExisting(), propertyHandler(), Screen(), setDesktopName(), updateDesktopNames(), and ~Screen().

bool ob::Screen::_managed [private]
 

Was Openbox able to manage the screen?

Definition at line 53 of file screen.hh.

Referenced by Screen(), and ~Screen().

long ob::Screen::_num_desktops [private]
 

The number of desktops.

Definition at line 87 of file screen.hh.

Referenced by changeDesktop(), changeNumDesktops(), changeWorkArea(), Screen(), setDesktopName(), and updateDesktopNames().

int ob::Screen::_number [private]
 

The number of the screen on the X server.

Definition at line 56 of file screen.hh.

bool ob::Screen::_root_cmap_installed [private]
 

Is the root colormap currently installed?

Definition at line 65 of file screen.hh.

ClientList ob::Screen::_stacking [private]
 

A list of all managed clients on the screen, in their stacking order.

Definition at line 81 of file screen.hh.

Referenced by changeStackingList(), lowerWindow(), manageWindow(), raiseWindow(), and unmanageWindow().

otk::Strut ob::Screen::_strut [private]
 

Combined strut from all of the clients' struts.

Definition at line 71 of file screen.hh.

Referenced by calcArea(), and updateStrut().

otk::RenderStyle ob::Screen::_style [private]
 

The style with which to render on the screen.

Definition at line 62 of file screen.hh.

Referenced by Screen().

Window ob::Screen::_supportwindow [private]
 

An offscreen window which shows that a NETWM compliant window manager is running.

Definition at line 78 of file screen.hh.

Referenced by changeSupportedAtoms().

ClientList ob::Screen::clients
 

All managed clients on the screen (in order of being mapped).

Definition at line 49 of file screen.hh.

Referenced by ob::Bindings::addButton(), calcArea(), changeClientList(), changeDesktop(), changeNumDesktops(), changeStackingList(), manageWindow(), ob::Bindings::removeAllButtons(), unmanageWindow(), updateStrut(), and ~Screen().

const unsigned long ob::Screen::event_mask [static]
 

Initial value:

 ColormapChangeMask |
                                          EnterWindowMask |
                                          LeaveWindowMask |
                                          PropertyChangeMask |
                                          SubstructureNotifyMask |
                                          SubstructureRedirectMask |
                                          ButtonPressMask |
                                          ButtonReleaseMask

Definition at line 37 of file screen.hh.


The documentation for this class was generated from the following files:
Generated on Tue Feb 4 23:00:21 2003 for Openbox by doxygen1.3-rc2