acquire and provide Xinerama information for the window manager. now we just gotta use it.

This commit is contained in:
Dana Jansens 2002-07-21 23:58:09 +00:00
parent a0cf45a0ef
commit bcb14a3ce9
5 changed files with 129 additions and 2 deletions

View file

@ -35,6 +35,10 @@ extern "C" {
# include <X11/extensions/shape.h> # include <X11/extensions/shape.h>
#endif // SHAPE #endif // SHAPE
#ifdef XINERAMA
# include <X11/extensions/Xinerama.h>
#endif // XINERAMA
#ifdef HAVE_FCNTL_H #ifdef HAVE_FCNTL_H
# include <fcntl.h> # include <fcntl.h>
#endif // HAVE_FCNTL_H #endif // HAVE_FCNTL_H
@ -232,6 +236,22 @@ BaseDisplay::BaseDisplay(const char *app_name, const char *dpy_name) {
shape.extensions = False; shape.extensions = False;
#endif // SHAPE #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); XSetErrorHandler((XErrorHandler) handleXErrors);
screenInfoList.reserve(ScreenCount(display)); screenInfoList.reserve(ScreenCount(display));
@ -462,4 +482,34 @@ ScreenInfo::ScreenInfo(BaseDisplay *d, unsigned int num) {
display_string = string("DISPLAY=") + default_string + '.' + display_string = string("DISPLAY=") + default_string + '.' +
itostring(static_cast<unsigned long>(screen_number)); 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
} }

View file

@ -50,6 +50,10 @@ private:
unsigned int screen_number; unsigned int screen_number;
std::string display_string; std::string display_string;
Rect rect; Rect rect;
#ifdef XINERAMA
RectList xinerama_areas;
bool xinerama_active;
#endif
public: public:
ScreenInfo(BaseDisplay *d, unsigned int num); ScreenInfo(BaseDisplay *d, unsigned int num);
@ -66,6 +70,10 @@ public:
inline unsigned int getHeight(void) const { return rect.height(); } inline unsigned int getHeight(void) const { return rect.height(); }
inline const std::string& displayString(void) const inline const std::string& displayString(void) const
{ return display_string; } { 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; 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]; unsigned int MaskList[8];
size_t MaskListLength; size_t MaskListLength;
@ -114,6 +131,10 @@ public:
inline bool hasShapeExtensions(void) const inline bool hasShapeExtensions(void) const
{ return shape.extensions; } { return shape.extensions; }
#ifdef XINERAMA
inline bool hasXineramaExtensions(void) const
{ return xinerama.extensions; }
#endif // XINERAMA
inline bool doShutdown(void) const inline bool doShutdown(void) const
{ return run_state == SHUTDOWN; } { return run_state == SHUTDOWN; }
inline bool isStartup(void) const inline bool isStartup(void) const
@ -130,6 +151,10 @@ public:
{ return screenInfoList.size(); } { return screenInfoList.size(); }
inline int getShapeEventBase(void) const inline int getShapeEventBase(void) const
{ return shape.event_basep; } { 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 shutdown(void) { run_state = SHUTDOWN; }
inline void run(void) { run_state = RUNNING; } inline void run(void) { run_state = RUNNING; }

View file

@ -29,6 +29,11 @@ extern "C" {
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#ifdef XINERAMA
# include <X11/Xlib.h>
# include <X11/extensions/Xinerama.h>
#endif // XINERAMA
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
# include <stdlib.h> # include <stdlib.h>
#endif // HAVE_STDLIB_H #endif // HAVE_STDLIB_H
@ -154,8 +159,7 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) {
XDefineCursor(blackbox->getXDisplay(), getRootWindow(), XDefineCursor(blackbox->getXDisplay(), getRootWindow(),
blackbox->getSessionCursor()); blackbox->getSessionCursor());
// start off full screen, top left. updateAvailableArea();
usableArea.setSize(getWidth(), getHeight());
image_control = image_control =
new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(), 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) { void BScreen::updateAvailableArea(void) {
Rect old_area = usableArea; Rect old_area = usableArea;
usableArea = getRect(); // reset to full screen 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 /* these values represent offsets from the screen edge
* we look for the biggest offset on each edge and then apply them * we look for the biggest offset on each edge and then apply them
* all at once * all at once
@ -2100,6 +2122,27 @@ void BScreen::updateAvailableArea(void) {
usableArea.setSize(usableArea.width() - (current_left + current_right), usableArea.setSize(usableArea.width() - (current_left + current_right),
usableArea.height() - (current_top + current_bottom)); 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) { if (old_area != usableArea) {
BlackboxWindowList::iterator it = windowList.begin(), BlackboxWindowList::iterator it = windowList.begin(),
end = windowList.end(); end = windowList.end();

View file

@ -131,6 +131,9 @@ private:
unsigned long event_mask; unsigned long event_mask;
Rect usableArea; Rect usableArea;
#ifdef XINERAMA
RectList xineramaUsableArea;
#endif // XINERAMA
typedef std::list<Strut*> StrutList; typedef std::list<Strut*> StrutList;
StrutList strutList; StrutList strutList;
@ -306,7 +309,10 @@ public:
BlackboxWindow *getIcon(unsigned int index); 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; const Rect& availableArea(void) const;
RectList allAvailableAreas(void) const;
void updateAvailableArea(void); void updateAvailableArea(void);
void addStrut(Strut *strut); void addStrut(Strut *strut);
void removeStrut(Strut *strut); void removeStrut(Strut *strut);

View file

@ -28,6 +28,7 @@
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <string> #include <string>
#include <list>
class Rect { class Rect {
public: public:
@ -76,6 +77,8 @@ private:
int _x1, _y1, _x2, _y2; int _x1, _y1, _x2, _y2;
}; };
typedef std::list<Rect> RectList;
struct Strut { struct Strut {
unsigned int top, bottom, left, right; unsigned int top, bottom, left, right;