From 12eb79fbb08f2fe4efde795e7a35c879d3367f9c Mon Sep 17 00:00:00 2001 From: Timur Kristóf Date: Thu, 28 Apr 2011 16:10:54 +0200 Subject: This is an X client app that creates pointer barriers based on information from the Xinerama extension. --- XineramaBarriers.pro | 28 ++++++++ barriermanager.cpp | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++ barriermanager.h | 37 ++++++++++ main.cpp | 45 ++++++++++++ 4 files changed, 305 insertions(+) create mode 100644 XineramaBarriers.pro create mode 100644 barriermanager.cpp create mode 100644 barriermanager.h create mode 100644 main.cpp diff --git a/XineramaBarriers.pro b/XineramaBarriers.pro new file mode 100644 index 0000000..0ecd4cc --- /dev/null +++ b/XineramaBarriers.pro @@ -0,0 +1,28 @@ + +# XineramaBarriers +# ---------- +# Copyright (C) 2011, Timur Kristóf +# +# This X client application will create pointer barriers +# based on the Xinerama information of your current driver. +# Only works with XFixes v5 or higher and the Xorg server +# which has the pointer barriers patch. +# ---------- +# Licensed under the terms of the GPL +# ---------- + +TEMPLATE = app +TARGET = XineramaBarriers + +CONFIG += console link_pkgconfig +CONFIG -= QT app_bundle +PKGCONFIG += x11 xinerama xfixes + +SOURCES += main.cpp \ + barriermanager.cpp + +INSTALLS += target +target.path = /usr/bin + +HEADERS += \ + barriermanager.h diff --git a/barriermanager.cpp b/barriermanager.cpp new file mode 100644 index 0000000..4bce3fc --- /dev/null +++ b/barriermanager.cpp @@ -0,0 +1,195 @@ + +// XineramaBarriers +// ---------- +// Copyright (C) 2011, Timur Kristóf +// +// This X client application will create pointer barriers +// based on the Xinerama information of your current driver. +// Only works with XFixes v5 or higher and the Xorg server +// which has the pointer barriers patch. +// ---------- +// Licensed under the terms of the GPL +// ---------- + +#include "barriermanager.h" +#include +#include + +static std::ostream &operator<<(std::ostream &os, const XineramaScreenInfo &info) +{ + return os << info.screen_number << " " << info.width << " " << info.height << " " << info.x_org << " " << info.y_org; +} + +static std::vector fetchXineramaInfo(Display *d) +{ + std::vector result; + int a; + XineramaScreenInfo *info = XineramaQueryScreens(d, &a); + for (int i = 0; i < a; i++) + { + result.push_back(info[i]); + std::cout << info[i] << std::endl; + } + XFree(info); + return result; +} + +static bool compareY(const XineramaScreenInfo &i1, const XineramaScreenInfo &i2) +{ + return i1.y_org < i2.y_org; +} + +static bool compareX(const XineramaScreenInfo &i1, const XineramaScreenInfo &i2) +{ + return i1.x_org < i2.x_org; +} + +BarrierManager::BarrierManager(Display *d) + : d(d) +{ + updateBarriers(); +} + +BarrierManager::~BarrierManager() +{ + destroyBarriers(); +} + +void BarrierManager::destroyBarriers() +{ + for (std::vector::iterator i = barriers.begin(); i != barriers.end(); i++) + XFixesDestroyPointerBarrier(d, *i); + barriers.clear(); +} + +void BarrierManager::updateBarriers() +{ + destroyBarriers(); + XGetWindowAttributes(d, DefaultRootWindow(d), &attrs); + infos = fetchXineramaInfo(d); + + std::cout << "updating barriers" << std::endl; + + for (std::vector::iterator i = infos.begin(); i != infos.end(); i++) + { + if (i->x_org) + { + // Checking left neighbours + std::vector leftNeighbours; + for (std::vector::iterator j = infos.begin(); j != infos.end(); j++) + if (j->x_org + j->width == i->x_org) + leftNeighbours.push_back(*j); + + std::sort(leftNeighbours.begin(), leftNeighbours.end(), compareY); + int startY = i->y_org; + int x = i->x_org; + + // Adding barriers to the edge to the area where there are no neighbours + for (std::vector::iterator j = leftNeighbours.begin(); j != leftNeighbours.end(); j++) + { + if (j->y_org > startY) + { + barriers.push_back(XFixesCreatePointerBarrier(d, DefaultRootWindow(d), x, startY, x, j->y_org, BarrierPositiveX, 0, 0)); + std::cout << "left barrier created: x=" << x << " startY=" << startY << " y=" << j->y_org + j->height << std::endl; + } + startY = MIN(j->y_org + j->height, i->y_org + i->height); + } + if (startY < i->y_org + i->height) + { + // Adding a barrier to the remaining area where there are no more neighbours + barriers.push_back(XFixesCreatePointerBarrier(d, DefaultRootWindow(d), x, startY, x, i->y_org + i->height, BarrierPositiveX, 0, 0)); + std::cout << "left barrier created: x=" << x << " startY=" << startY << " y=" << i->y_org + i->height << std::endl; + } + } + + if (i->x_org + i->width != attrs.width) + { + // checking right neighbours + std::vector rightNeighbours; + for (std::vector::iterator j = infos.begin(); j != infos.end(); j++) + if (i->x_org + i->width == j->x_org) + rightNeighbours.push_back(*j); + + std::sort(rightNeighbours.begin(), rightNeighbours.end(), compareY); + int startY = i->y_org; + int x = i->x_org + i->width; + + // Adding barriers to the edge to the area where there are no neighbours + for (std::vector::iterator j = rightNeighbours.begin(); j != rightNeighbours.end(); j++) + { + if (j->y_org > startY) + { + barriers.push_back(XFixesCreatePointerBarrier(d, DefaultRootWindow(d), x, startY, x, j->y_org, BarrierNegativeX, 0, 0)); + std::cout << "right barrier created: x=" << x << " startY=" << startY << " y=" << j->y_org << std::endl; + } + startY = MIN(j->y_org + j->height, i->y_org + i->height); + } + if (startY < i->y_org + i->height) + { + // Adding a barrier to the remaining area where there are no more neighbours + barriers.push_back(XFixesCreatePointerBarrier(d, DefaultRootWindow(d), x, startY, x, i->y_org + i->height, BarrierNegativeX, 0, 0)); + std::cout << "right barrier created: x=" << x << " startY=" << startY << " y=" << i->y_org + i->height << std::endl; + } + } + + if (i->y_org) + { + // checking top neighbours + std::vector topNeighbours; + for (std::vector::iterator j = infos.begin(); j != infos.end(); j++) + if (j->y_org + j->height == i->y_org) + topNeighbours.push_back(*j); + + std::sort(topNeighbours.begin(), topNeighbours.end(), compareX); + int startX = i->x_org; + int y = i->y_org; + + // Adding barriers to the edge to the area where there are no neighbours + for (std::vector::iterator j = topNeighbours.begin(); j != topNeighbours.end(); j++) + { + if (j->x_org > startX) + { + barriers.push_back(XFixesCreatePointerBarrier(d, DefaultRootWindow(d), startX, y, j->x_org, y, BarrierPositiveY, 0, 0)); + std::cout << "top barrier created: y=" << y << " startX=" << startX << " X=" << j->x_org << std::endl; + } + startX = MIN(j->x_org + j->width, i->x_org + i->width); + } + if (startX < i->x_org + i->width) + { + // Adding a barrier to the remaining area where there are no more neighbours + barriers.push_back(XFixesCreatePointerBarrier(d, DefaultRootWindow(d), startX, y, i->x_org + i->width, y, BarrierPositiveY, 0, 0)); + std::cout << "top barrier created: y=" << y << " startX=" << startX << " X=" << i->x_org + i->width << std::endl; + } + } + + if (i->y_org + i->height != attrs.height) + { + // checking bottom neighbours + std::vector bottomNeighbours; + for (std::vector::iterator j = infos.begin(); j != infos.end(); j++) + if (i->y_org + i->height == j->y_org) + bottomNeighbours.push_back(*j); + + std::sort(bottomNeighbours.begin(), bottomNeighbours.end(), compareX); + int startX = i->x_org; + int y = i->y_org + i->height; + + // Adding barriers to the edge to the area where there are no neighbours + for (std::vector::iterator j = bottomNeighbours.begin(); j != bottomNeighbours.end(); j++) + { + if (j->x_org > startX) + { + barriers.push_back(XFixesCreatePointerBarrier(d, DefaultRootWindow(d), startX, y, j->x_org, y, BarrierNegativeY, 0, 0)); + std::cout << "bottom barrier created: y=" << y << " startX=" << startX << " X=" << j->x_org << std::endl; + } + startX = MIN(j->x_org + j->width, i->x_org + i->width); + } + if (startX < i->x_org + i->width) + { + // Adding a barrier to the remaining area where there are no more neighbours + barriers.push_back(XFixesCreatePointerBarrier(d, DefaultRootWindow(d), startX, y, i->x_org + i->width, y, BarrierNegativeY, 0, 0)); + std::cout << "bottom barrier created: y=" << y << " startX=" << startX << " X=" << i->x_org + i->width << std::endl; + } + } + } +} diff --git a/barriermanager.h b/barriermanager.h new file mode 100644 index 0000000..b5b4186 --- /dev/null +++ b/barriermanager.h @@ -0,0 +1,37 @@ + +// XineramaBarriers +// ---------- +// Copyright (C) 2011, Timur Kristóf +// +// This X client application will create pointer barriers +// based on the Xinerama information of your current driver. +// Only works with XFixes v5 or higher and the Xorg server +// which has the pointer barriers patch. +// ---------- +// Licensed under the terms of the GPL +// ---------- + +#ifndef BARRIERMANAGER_H +#define BARRIERMANAGER_H + +#include +#include +#include +#include + +#define MIN(a, b) (((a) < (b)) ? a : b) + +class BarrierManager { + std::vector barriers; + std::vector infos; + XWindowAttributes attrs; + Display *d; + +public: + explicit BarrierManager(Display *d); + ~BarrierManager(); + void updateBarriers(); + void destroyBarriers(); +}; + +#endif // BARRIERMANAGER_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..fa278ea --- /dev/null +++ b/main.cpp @@ -0,0 +1,45 @@ + +// XineramaBarriers +// ---------- +// Copyright (C) 2011, Timur Kristóf +// +// This X client application will create pointer barriers +// based on the Xinerama information of your current driver. +// Only works with XFixes v5 or higher and the Xorg server +// which has the pointer barriers patch. +// ---------- +// Licensed under the terms of the GPL +// ---------- + +#include "barriermanager.h" +#include + +int main() +{ + std::cout << "good morning!" << std::endl; + Display *d = XOpenDisplay(0); + + if (!XineramaIsActive(d)) + { + std::cout << "Xinerama is not active, bye!" << std::endl; + return -1; + } + + BarrierManager m(d); + XSelectInput(d, DefaultRootWindow(d), StructureNotifyMask); + XEvent ev; + + while (XNextEvent(d, &ev)) + { + switch (ev.type) + { + case ConfigureNotify: + std::cout << "configure event" << std::endl; + m.updateBarriers(); + break; + } + } + + XCloseDisplay(d); + return 0; +} -- cgit