summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/BaseDisplay.cc50
-rw-r--r--src/BaseDisplay.hh25
-rw-r--r--src/Screen.cc47
-rw-r--r--src/Screen.hh6
-rw-r--r--src/Util.hh3
5 files changed, 129 insertions, 2 deletions
diff --git a/src/BaseDisplay.cc b/src/BaseDisplay.cc
index 6bf290e2..8f3b39b1 100644
--- a/src/BaseDisplay.cc
+++ b/src/BaseDisplay.cc
@@ -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
}
diff --git a/src/BaseDisplay.hh b/src/BaseDisplay.hh
index 3ebe6e61..e4ef2387 100644
--- a/src/BaseDisplay.hh
+++ b/src/BaseDisplay.hh
@@ -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; }
diff --git a/src/Screen.cc b/src/Screen.cc
index 6b895644..92dd4a70 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -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();
diff --git a/src/Screen.hh b/src/Screen.hh
index c16bd077..06548d41 100644
--- a/src/Screen.hh
+++ b/src/Screen.hh
@@ -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);
diff --git a/src/Util.hh b/src/Util.hh
index 5453f225..d70eabc8 100644
--- a/src/Util.hh
+++ b/src/Util.hh
@@ -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;