acquire and provide Xinerama information for the window manager. now we just gotta...
authorDana Jansens <danakj@orodu.net>
Sun, 21 Jul 2002 23:58:09 +0000 (23:58 +0000)
committerDana Jansens <danakj@orodu.net>
Sun, 21 Jul 2002 23:58:09 +0000 (23:58 +0000)
src/BaseDisplay.cc
src/BaseDisplay.hh
src/Screen.cc
src/Screen.hh
src/Util.hh

index 6bf290e..8f3b39b 100644 (file)
@@ -35,6 +35,10 @@ extern "C" {
 #  include <X11/extensions/shape.h>
 #endif // SHAPE
 
+#ifdef    XINERAMA
+#  include <X11/extensions/Xinerama.h>
+#endif // XINERAMA
+
 #ifdef    HAVE_FCNTL_H
 #  include <fcntl.h>
 #endif // HAVE_FCNTL_H
@@ -232,6 +236,22 @@ BaseDisplay::BaseDisplay(const char *app_name, const char *dpy_name) {
   shape.extensions = False;
 #endif // SHAPE
 
+  xinerama.extensions = False;
+#ifdef    XINERAMA
+  if (XineramaQueryExtension(display, &xinerama.event_basep,
+                             &xinerama.error_basep)) {
+    if (XineramaQueryVersion(display, &xinerama.major,
+                             &xinerama.minor)) {
+#ifdef    DEBUG
+      fprintf(stderr,
+              "BaseDisplay::BaseDisplay: Found Xinerama version %d.%d\n",
+              xinerama.major, xinerama.minor);
+#endif // DEBUG
+      xinerama.extensions = True;
+    }
+  }
+#endif // XINERAMA
+
   XSetErrorHandler((XErrorHandler) handleXErrors);
 
   screenInfoList.reserve(ScreenCount(display));
@@ -462,4 +482,34 @@ ScreenInfo::ScreenInfo(BaseDisplay *d, unsigned int num) {
 
   display_string = string("DISPLAY=") + default_string + '.' +
     itostring(static_cast<unsigned long>(screen_number));
+  
+#ifdef    XINERAMA
+  if (d->hasXineramaExtensions()) {
+    if (d->getXineramaMajorVersion() == 1) {
+      // we know the version 1(.1?) protocol
+
+      /*
+         in this version of Xinerama, we can't query on a per-screen basis, but
+         in future versions we should be able, so the 'activeness' is checked
+         on a pre-screen basis anyways.
+      */
+      xinerama_active = XineramaIsActive(d->getXDisplay());
+      /*
+         If Xinerama is being used, there there is only going to be one screen
+         present. We still, of course, want to use the screen class, but that is
+         why no screen number is used in this function call. There should never
+         be more than one screen present with Xinerama active.
+      */
+      int num;
+      XineramaScreenInfo *info = XineramaQueryScreens(d->getXDisplay(), &num);
+      if (num > 0 && info) {
+        for (int i = 0; i < num; ++i) {
+          xinerama_areas.push_back(Rect(info[i].x_org, info[i].y_org,
+                                        info[i].width, info[i].height));
+        }
+        XFree(info);
+      }
+    }
+  }
+#endif // XINERAMA
 }
index 3ebe6e6..e4ef238 100644 (file)
@@ -50,6 +50,10 @@ private:
   unsigned int screen_number;
   std::string display_string;
   Rect rect;
+#ifdef XINERAMA
+  RectList xinerama_areas;
+  bool xinerama_active;
+#endif
 
 public:
   ScreenInfo(BaseDisplay *d, unsigned int num);
@@ -66,6 +70,10 @@ public:
   inline unsigned int getHeight(void) const { return rect.height(); }
   inline const std::string& displayString(void) const
   { return display_string; }
+#ifdef XINERAMA
+  inline const RectList &getXineramaAreas(void) const { return xinerama_areas; }
+  inline bool isXineramaActive(void) const { return xinerama_active; }
+#endif
 };
 
 
@@ -77,6 +85,15 @@ private:
   };
   BShape shape;
 
+#ifdef    XINERAMA
+  struct BXinerama {
+    bool extensions;
+    int event_basep, error_basep;
+    int major, minor; // version
+  };
+  BXinerama xinerama;
+#endif // XINERAMA
+
   unsigned int MaskList[8];
   size_t MaskListLength;
 
@@ -114,6 +131,10 @@ public:
 
   inline bool hasShapeExtensions(void) const
     { return shape.extensions; }
+#ifdef    XINERAMA
+  inline bool hasXineramaExtensions(void) const
+    { return xinerama.extensions; }
+#endif // XINERAMA
   inline bool doShutdown(void) const
     { return run_state == SHUTDOWN; }
   inline bool isStartup(void) const
@@ -130,6 +151,10 @@ public:
     { return screenInfoList.size(); }
   inline int getShapeEventBase(void) const
     { return shape.event_basep; }
+#ifdef    XINERAMA
+  inline int getXineramaMajorVersion(void) const
+    { return xinerama.major; }
+#endif // XINERAMA
 
   inline void shutdown(void) { run_state = SHUTDOWN; }
   inline void run(void) { run_state = RUNNING; }
index 6b89564..92dd4a7 100644 (file)
@@ -29,6 +29,11 @@ extern "C" {
 #include <X11/Xatom.h>
 #include <X11/keysym.h>
 
+#ifdef    XINERAMA
+#  include <X11/Xlib.h>
+#  include <X11/extensions/Xinerama.h>
+#endif // XINERAMA
+
 #ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif // HAVE_STDLIB_H
@@ -154,8 +159,7 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) {
   XDefineCursor(blackbox->getXDisplay(), getRootWindow(),
                 blackbox->getSessionCursor());
 
-  // start off full screen, top left.
-  usableArea.setSize(getWidth(), getHeight());
+  updateAvailableArea();
 
   image_control =
     new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(),
@@ -2070,10 +2074,28 @@ const Rect& BScreen::availableArea(void) const {
 }
 
 
+RectList BScreen::allAvailableAreas(void) const {
+#ifdef    XINERAMA
+  if (isXineramaActive())
+    return xineramaUsableArea;
+#endif // XINERAMA
+
+  RectList list;
+  list.push_back(availableArea());
+  return list;
+}
+
+
 void BScreen::updateAvailableArea(void) {
   Rect old_area = usableArea;
   usableArea = getRect(); // reset to full screen
 
+#ifdef    XINERAMA
+  // reset to the full areas
+  if (isXineramaActive())
+    xineramaUsableArea = allAvailableAreas();
+#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
@@ -2100,6 +2122,27 @@ void BScreen::updateAvailableArea(void) {
   usableArea.setSize(usableArea.width() - (current_left + current_right),
                      usableArea.height() - (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 != usableArea) {
     BlackboxWindowList::iterator it = windowList.begin(),
       end = windowList.end();
index c16bd07..06548d4 100644 (file)
@@ -131,6 +131,9 @@ private:
   unsigned long event_mask;
 
   Rect usableArea;
+#ifdef    XINERAMA
+  RectList xineramaUsableArea;
+#endif // XINERAMA
 
   typedef std::list<Strut*> StrutList;
   StrutList strutList;
@@ -306,7 +309,10 @@ public:
 
   BlackboxWindow *getIcon(unsigned int index);
 
+  // allAvailableAreas should be used whenever possible instead of this function
+  // as then Xinerama will work correctly.
   const Rect& availableArea(void) const;
+  RectList allAvailableAreas(void) const;
   void updateAvailableArea(void);
   void addStrut(Strut *strut);
   void removeStrut(Strut *strut);
index 5453f22..d70eabc 100644 (file)
@@ -28,6 +28,7 @@
 #include <X11/Xutil.h>
 
 #include <string>
+#include <list>
 
 class Rect {
 public:
@@ -76,6 +77,8 @@ private:
   int _x1, _y1, _x2, _y2;
 };
 
+typedef std::list<Rect> RectList;
+
 struct Strut {
   unsigned int top, bottom, left, right;