2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2003-2008 Kim Woelders
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #include <X11/extensions/Xinerama.h>
40 static EScreen *p_screens = NULL;
41 static int n_screens = 0;
44 static XineramaScreenInfo *
45 EXineramaQueryScreens(int *number)
47 int event_base, error_base;
51 if (!XineramaQueryExtension(disp, &event_base, &error_base))
54 return XineramaQueryScreens(disp, number);
59 ScreenAdd(int type, int head, int x, int y, unsigned int w, unsigned int h)
64 p_screens = EREALLOC(EScreen, p_screens, n_screens);
66 es = p_screens + n_screens - 1;
79 XineramaScreenInfo *screens;
83 n_screens = 0; /* Causes reconfiguration */
89 screens = EXineramaQueryScreens(&num_screens);
91 Mode.display.xinerama_active = (XineramaIsActive(disp)) ? 1 : 0;
92 if (!Mode.display.xinerama_active && num_screens > 1)
93 Mode.display.xinerama_active = 2;
97 for (i = 0; i < num_screens; i++)
98 ScreenAdd(0, screens[i].screen_number, screens[i].x_org,
99 screens[i].y_org, screens[i].width, screens[i].height);
108 ScreenSplit(unsigned int nx, unsigned int ny)
112 if (nx > 8 || ny > 8) /* At least some limit */
115 if (nx == 0 || ny == 0)
121 n_screens = 0; /* Causes reconfiguration */
123 for (i = 0; i < nx; i++)
124 for (j = 0; j < ny; j++)
125 ScreenAdd(1, Dpy.screen,
126 i * WinGetW(VROOT) / nx, j * WinGetH(VROOT) / ny,
127 WinGetW(VROOT) / nx, WinGetH(VROOT) / ny);
131 ScreenShowInfo(const char *prm __UNUSED__)
136 static const char *const mt[] = { "Off", "On", "TV", "???" };
137 XineramaScreenInfo *scrns;
141 IpcPrintf("Head Screen X-Origin Y-Origin Width Height\n");
142 IpcPrintf("Screen:\n");
143 IpcPrintf(" %2d %2d %5d %5d %5d %5d\n",
144 0, Dpy.screen, 0, 0, WinGetW(VROOT), WinGetH(VROOT));
147 scrns = EXineramaQueryScreens(&num);
149 mode = (XineramaIsActive(disp)) ? 1 : 0;
150 if (!mode && num > 1)
153 IpcPrintf("Xinerama mode: %s\n", mt[mode]);
157 IpcPrintf("Xinerama screens:\n");
158 for (i = 0; i < num; i++)
159 IpcPrintf(" %2d %2d %5d %5d %5d %5d\n",
160 i, scrns[i].screen_number,
161 scrns[i].x_org, scrns[i].y_org, scrns[i].width,
169 IpcPrintf("E-screens:\n");
170 for (i = 0; i < n_screens; i++)
172 EScreen *ps = p_screens + i;
174 IpcPrintf(" %2d %2d %5d %5d %5d %5d\n",
175 i, ps->head, ps->x, ps->y, ps->w, ps->h);
181 ScreenGetGeometryByHead(int head, int *px, int *py, int *pw, int *ph)
186 if (head >= 0 && head < n_screens)
188 ps = p_screens + head;
209 ScreenGetGeometry(int xi, int yi, int *px, int *py, int *pw, int *ph)
211 int i, dx, dy, dist, head;
219 for (i = 0; i < n_screens; i++)
223 if (xi >= ps->x && xi < ps->x + ps->w &&
224 yi >= ps->y && yi < ps->y + ps->h)
230 dx = xi - (ps->x + ps->w / 2);
231 dy = yi - (ps->y + ps->h / 2);
232 dx = dx * dx + dy * dy;
240 ScreenGetGeometryByHead(head, px, py, pw, ph);
246 VRootGetAvailableArea(int *px, int *py, int *pw, int *ph)
248 EWin *const *lst, *ewin;
249 int i, num, l, r, t, b;
252 lst = EwinListGetAll(&num);
253 for (i = 0; i < num; i++)
257 if (l < ewin->strut.left)
258 l = ewin->strut.left;
259 if (r < ewin->strut.right)
260 r = ewin->strut.right;
261 if (t < ewin->strut.top)
263 if (b < ewin->strut.bottom)
264 b = ewin->strut.bottom;
269 *pw = WinGetW(VROOT) - (l + r);
270 *ph = WinGetH(VROOT) - (t + b);
274 ScreenGetAvailableArea(int xi, int yi, int *px, int *py, int *pw, int *ph)
276 int x1, y1, w1, h1, x2, y2, w2, h2, head;
278 head = ScreenGetGeometry(xi, yi, &x1, &y1, &w1, &h1);
280 if (!Conf.place.ignore_struts)
282 VRootGetAvailableArea(&x2, &y2, &w2, &h2);
302 ScreenGetGeometryByPointer(int *px, int *py, int *pw, int *ph)
304 int pointer_x, pointer_y;
306 EQueryPointer(NULL, &pointer_x, &pointer_y, NULL, NULL);
308 return ScreenGetGeometry(pointer_x, pointer_y, px, py, pw, ph);
312 ScreenGetAvailableAreaByPointer(int *px, int *py, int *pw, int *ph)
314 int pointer_x, pointer_y;
316 EQueryPointer(NULL, &pointer_x, &pointer_y, NULL, NULL);
318 return ScreenGetAvailableArea(pointer_x, pointer_y, px, py, pw, ph);