]> Dogcows Code - chaz/openbox/commitdiff
adding the new OBScreen class actually!
authorDana Jansens <danakj@orodu.net>
Sun, 10 Nov 2002 12:50:18 +0000 (12:50 +0000)
committerDana Jansens <danakj@orodu.net>
Sun, 10 Nov 2002 12:50:18 +0000 (12:50 +0000)
src/screen.cc [new file with mode: 0644]
src/screen.hh [new file with mode: 0644]

diff --git a/src/screen.cc b/src/screen.cc
new file mode 100644 (file)
index 0000000..37a3871
--- /dev/null
@@ -0,0 +1,303 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+
+#ifdef HAVE_CONFIG_H
+# include "../config.h"
+#endif
+
+extern "C" {
+#include "gettext.h"
+#define _(str) gettext(str)
+}
+
+#include "screen.hh"
+#include "client.hh"
+#include "openbox.hh"
+#include "otk/display.hh"
+
+static bool running;
+static int anotherWMRunning(Display *display, XErrorEvent *) {
+  printf(_("Another window manager already running on display %s.\n"),
+         DisplayString(display));
+  running = true;
+  return -1;
+}
+
+
+namespace ob {
+
+
+OBScreen::OBScreen(int screen)
+  : _number(screen)
+{
+  assert(screen >= 0); assert(screen < ScreenCount(otk::OBDisplay::display));
+  _info = otk::OBDisplay::screenInfo(screen);
+
+  ::running = false;
+  XErrorHandler old = XSetErrorHandler(::anotherWMRunning);
+  XSelectInput(otk::OBDisplay::display, _info->getRootWindow(),
+               OBScreen::event_mask);
+  XSync(otk::OBDisplay::display, false);
+  XSetErrorHandler(old);
+
+  _managed = !::running;
+  if (! _managed) return; // was unable to manage the screen
+
+  printf(_("Managing screen %d: visual 0x%lx, depth %d\n"),
+         _number, XVisualIDFromVisual(_info->getVisual()), _info->getDepth());
+
+#ifdef    HAVE_GETPID
+  Openbox::instance->property()->set(_info->getRootWindow(),
+                                     otk::OBProperty::openbox_pid,
+                                     otk::OBProperty::Atom_Cardinal,
+                                     (unsigned long) getpid());
+#endif // HAVE_GETPID
+
+  // set the mouse cursor for the root window (the default cursor)
+  XDefineCursor(otk::OBDisplay::display, _info->getRootWindow(),
+                Openbox::instance->cursors().session);
+  
+  _image_control = new otk::BImageControl(Openbox::instance->timerManager(),
+                                          _info, true);
+  _image_control->installRootColormap();
+  _root_cmap_installed = True;
+
+  
+  // Set the netwm atoms for geomtery and viewport
+  unsigned long geometry[] = { _size.x(),
+                               _size.y() };
+  Openbox::instance->property()->set(_info->getRootWindow(),
+                                     otk::OBProperty::net_desktop_geometry,
+                                     otk::OBProperty::Atom_Cardinal,
+                                     geometry, 2);
+  unsigned long viewport[] = { 0, 0 };
+  Openbox::instance->property()->set(_info->getRootWindow(),
+                                     otk::OBProperty::net_desktop_viewport,
+                                     otk::OBProperty::Atom_Cardinal,
+                                     viewport, 2);
+
+  // these may be further updated if any pre-existing windows are found in
+  // the manageExising() function
+  setClientList();     // initialize the client lists, which will be empty
+  calcArea();          // initialize the available working area
+
+  manageExisting();
+
+  // XXX: "change to" the first workspace to initialize stuff
+}
+
+
+OBScreen::~OBScreen()
+{
+  if (! _managed) return;
+
+  delete _image_control;
+}
+
+
+void OBScreen::manageExisting()
+{
+  unsigned int i, j, nchild;
+  Window r, p, *children;
+  XQueryTree(otk::OBDisplay::display, _info->getRootWindow(), &r, &p,
+             &children, &nchild);
+
+  // preen the window list of all icon windows... for better dockapp support
+  for (i = 0; i < nchild; i++) {
+    if (children[i] == None) continue;
+
+    XWMHints *wmhints = XGetWMHints(otk::OBDisplay::display,
+                                    children[i]);
+
+    if (wmhints) {
+      if ((wmhints->flags & IconWindowHint) &&
+          (wmhints->icon_window != children[i])) {
+        for (j = 0; j < nchild; j++) {
+          if (children[j] == wmhints->icon_window) {
+            children[j] = None;
+            break;
+          }
+        }
+      }
+
+      XFree(wmhints);
+    }
+  }
+
+  // manage shown windows
+  for (i = 0; i < nchild; ++i) {
+    if (children[i] == None)
+      continue;
+
+    XWindowAttributes attrib;
+    if (XGetWindowAttributes(otk::OBDisplay::display, children[i], &attrib)) {
+      if (attrib.override_redirect) continue;
+
+      if (attrib.map_state != IsUnmapped) {
+        // XXX: manageWindow(children[i]);
+      }
+    }
+  }
+
+  XFree(children);
+}
+
+
+//! Adds a window's strut to the screen's list of reserved spaces
+void OBScreen::addStrut(otk::Strut *strut)
+{
+  _struts.push_back(strut);
+}
+
+
+//! Removes a window's strut from the screen's list of reserved spaces
+void OBScreen::removeStrut(otk::Strut *strut)
+{
+  _struts.remove(strut);
+}
+
+
+void OBScreen::calcArea()
+{
+  otk::Rect old_area = _area;
+
+/*
+#ifdef    XINERAMA
+  // reset to the full areas
+  if (isXineramaActive())
+    xineramaUsableArea = getXineramaAreas();
+#endif // XINERAMA
+*/
+  
+  /* these values represent offsets from the screen edge
+   * we look for the biggest offset on each edge and then apply them
+   * all at once
+   * do not be confused by the similarity to the names of Rect's members
+   */
+  unsigned int current_left = 0, current_right = 0, current_top = 0,
+    current_bottom = 0;
+
+  StrutList::const_iterator it = _struts.begin(), end = _struts.end();
+
+  for(; it != end; ++it) {
+    otk::Strut *strut = *it;
+    if (strut->left > current_left)
+      current_left = strut->left;
+    if (strut->top > current_top)
+      current_top = strut->top;
+    if (strut->right > current_right)
+      current_right = strut->right;
+    if (strut->bottom > current_bottom)
+      current_bottom = strut->bottom;
+  }
+
+  _area.setRect(current_left, current_top,
+                _info->getWidth() - (current_left + current_right),
+                _info->getHeight() - (current_top + current_bottom));
+
+/*
+#ifdef    XINERAMA
+  if (isXineramaActive()) {
+    // keep each of the ximerama-defined areas inside the strut
+    RectList::iterator xit, xend = xineramaUsableArea.end();
+    for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
+      if (xit->x() < usableArea.x()) {
+        xit->setX(usableArea.x());
+        xit->setWidth(xit->width() - usableArea.x());
+      }
+      if (xit->y() < usableArea.y()) {
+        xit->setY(usableArea.y());
+        xit->setHeight(xit->height() - usableArea.y());
+      }
+      if (xit->x() + xit->width() > usableArea.width())
+        xit->setWidth(usableArea.width() - xit->x());
+      if (xit->y() + xit->height() > usableArea.height())
+        xit->setHeight(usableArea.height() - xit->y());
+    }
+  }
+#endif // XINERAMA
+*/
+  
+  if (old_area != _area)
+    // XXX: re-maximize windows
+
+  setWorkArea();
+}
+
+
+void OBScreen::setClientList()
+{
+  Window *windows;
+
+  // create an array of the window ids
+  if (_clients.size() > 0) {
+    Window *win_it;
+    
+    windows = new Window[_clients.size()];
+    win_it = windows;
+    ClientList::const_iterator it = _clients.begin();
+    const ClientList::const_iterator end = _clients.end();
+    for (; it != end; ++it, ++win_it)
+      *win_it = (*it)->window();
+  } else
+    windows = (Window*) 0;
+
+  Openbox::instance->property()->set(_info->getRootWindow(),
+                                     otk::OBProperty::net_client_list,
+                                     otk::OBProperty::Atom_Window,
+                                     windows, _clients.size());
+
+  if (_clients.size())
+    delete [] windows;
+
+  setStackingList();
+}
+
+
+void OBScreen::setStackingList()
+{
+  // The below comment is wrong now hopefully :> but ill keep it here for
+  // reference anyways
+  /*
+    Get the stacking order from all of the workspaces.
+    We start with the current workspace so that the sticky windows will be
+    in the right order on the current workspace.
+  */
+  /*
+  Openbox::instance->property()->set(_info->getRootWindow(),
+                                     otk::OBProperty::net_client_list_stacking,
+                                     otk::OBProperty::Atom_Window,
+                                     _stacking, _stacking.size());
+  */
+}
+
+
+void OBScreen::setWorkArea() {
+  unsigned long area[] = { _area.x(), _area.y(),
+                           _area.width(), _area.height() };
+  Openbox::instance->property()->set(_info->getRootWindow(),
+                                     otk::OBProperty::net_workarea,
+                                     otk::OBProperty::Atom_Cardinal,
+                                     area, 4);
+  /*
+  if (workspacesList.size() > 0) {
+    unsigned long *dims = new unsigned long[4 * workspacesList.size()];
+    for (unsigned int i = 0, m = workspacesList.size(); i < m; ++i) {
+      // XXX: this could be different for each workspace
+      const otk::Rect &area = availableArea();
+      dims[(i * 4) + 0] = area.x();
+      dims[(i * 4) + 1] = area.y();
+      dims[(i * 4) + 2] = area.width();
+      dims[(i * 4) + 3] = area.height();
+    }
+    xatom->set(getRootWindow(), otk::OBProperty::net_workarea,
+               otk::OBProperty::Atom_Cardinal,
+               dims, 4 * workspacesList.size());
+    delete [] dims;
+  } else
+    xatom->set(getRootWindow(), otk::OBProperty::net_workarea,
+               otk::OBProperty::Atom_Cardinal, 0, 0);
+  */
+}
+
+
+}
diff --git a/src/screen.hh b/src/screen.hh
new file mode 100644 (file)
index 0000000..6068e04
--- /dev/null
@@ -0,0 +1,115 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+#ifndef   __screen_hh
+#define   __screen_hh
+
+/*! @file screen.hh
+  @brief OBScreen manages a single screen
+*/
+
+extern "C" {
+#include <X11/Xlib.h>
+}
+
+#include "otk/image.hh"
+#include "otk/strut.hh"
+#include "otk/rect.hh"
+#include "otk/point.hh"
+
+#include <string>
+
+namespace ob {
+
+class OBClient;
+
+//! Manages a single screen
+/*!
+*/
+class OBScreen {
+public:
+  //! Holds a list of OBClient objects
+  typedef std::vector<OBClient*> ClientList;
+  //! Holds a list of otk::Strut objects
+  typedef std::list<otk::Strut*> StrutList;
+
+  static const unsigned long event_mask = ColormapChangeMask |
+                                          EnterWindowMask |
+                                          LeaveWindowMask |
+                                          PropertyChangeMask |
+                                          SubstructureNotifyMask |
+                                          SubstructureRedirectMask |
+                                          ButtonPressMask |
+                                          ButtonReleaseMask;
+
+private:
+  //! Was %Openbox able to manage the screen?
+  bool _managed;
+
+  //! The number of the screen on the X server
+  int _number;
+
+  //! Information about this screen
+  const otk::ScreenInfo *_info;
+  
+  //! The Image Control used for rendering on the screen
+  otk::BImageControl *_image_control;
+
+  //! Is the root colormap currently installed?
+  bool _root_cmap_installed;
+
+  //! The dimentions of the screen
+  otk::Point _size;
+
+  //! All managed clients on the screen
+  ClientList _clients;
+
+  //! Area usable for placement etc (total - struts)
+  otk::Rect _area;
+
+  //! Areas of the screen reserved by applications
+  StrutList _struts;
+
+
+  //! Manage any pre-existing windows on the screen
+  void manageExisting();
+  //! Calculate the OBScreen::_area member
+  void calcArea();
+  //! Set the client list on the root window
+  /*!
+    Sets the _NET_CLIENT_LIST root window property.<br>
+    Also calls OBScreen::updateStackingList.
+  */
+  void setClientList();
+  //! Set the client stacking list on the root window
+  /*!
+    Set the _NET_CLIENT_LIST_STACKING root window property.
+  */
+  void setStackingList();
+  //! Set the work area hint on the root window
+  /*!
+    Set the _NET_WORKAREA root window property.
+  */
+  void setWorkArea();
+  
+public:
+  //! Constructs a new OBScreen object
+  OBScreen(int screen);
+  //! Destroys the OBScreen object
+  virtual ~OBScreen();
+
+  //! Returns the Image Control used for rendering on the screen
+  inline otk::BImageControl *imageControl() { return _image_control; }
+  //! Returns the dimentions of the screen
+  inline const otk::Point &size() const { return _size; }
+  //! Returns the area of the screen not reserved by applications' Struts
+  inline const otk::Rect &area() const { return _area; }
+
+  //! Adds a window's strut to the screen's list of reserved spaces
+  void addStrut(otk::Strut *strut);
+  //! Removes a window's strut from the screen's list of reserved spaces
+  void removeStrut(otk::Strut *strut);
+  
+};
+
+}
+
+#endif// __screen_hh
This page took 0.031864 seconds and 4 git commands to generate.