From: Dana Jansens Date: Sun, 21 Jul 2002 23:58:09 +0000 (+0000) Subject: acquire and provide Xinerama information for the window manager. now we just gotta... X-Git-Url: https://git.dogcows.com/gitweb?a=commitdiff_plain;h=bcb14a3ce94ee4b4cba07de7a297470719390331;p=chaz%2Fopenbox acquire and provide Xinerama information for the window manager. now we just gotta use it. --- 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 #endif // SHAPE +#ifdef XINERAMA +# include +#endif // XINERAMA + #ifdef HAVE_FCNTL_H # include #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(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 #include +#ifdef XINERAMA +# include +# include +#endif // XINERAMA + #ifdef HAVE_STDLIB_H # include #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 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 #include +#include class Rect { public: @@ -76,6 +77,8 @@ private: int _x1, _y1, _x2, _y2; }; +typedef std::list RectList; + struct Strut { unsigned int top, bottom, left, right;