// 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. // ---------- // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #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; } } } }