# 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
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));
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
}
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);
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
};
};
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;
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
{ 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; }
#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
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(),
}
+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
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();
unsigned long event_mask;
Rect usableArea;
+#ifdef XINERAMA
+ RectList xineramaUsableArea;
+#endif // XINERAMA
typedef std::list<Strut*> StrutList;
StrutList strutList;
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);
#include <X11/Xutil.h>
#include <string>
+#include <list>
class Rect {
public:
int _x1, _y1, _x2, _y2;
};
+typedef std::list<Rect> RectList;
+
struct Strut {
unsigned int top, bottom, left, right;