chiark / gitweb /
Imported Debian patch 1.0.0-5
[e16] / src / screen.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2003-2008 Kim Woelders
4  *
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:
11  *
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.
16  *
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.
23  */
24 #include "E.h"
25 #include "ewins.h"
26 #include "ipc.h"
27 #include "screen.h"
28 #include "xwin.h"
29 #ifdef USE_XINERAMA
30 #include <X11/extensions/Xinerama.h>
31 #endif
32
33 typedef struct {
34    int                 type;
35    int                 head;
36    int                 x, y;
37    int                 w, h;
38 } EScreen;
39
40 static EScreen     *p_screens = NULL;
41 static int          n_screens = 0;
42
43 #ifdef USE_XINERAMA
44 static XineramaScreenInfo *
45 EXineramaQueryScreens(int *number)
46 {
47    int                 event_base, error_base;
48
49    *number = 0;
50
51    if (!XineramaQueryExtension(disp, &event_base, &error_base))
52       return NULL;
53
54    return XineramaQueryScreens(disp, number);
55 }
56 #endif
57
58 void
59 ScreenAdd(int type, int head, int x, int y, unsigned int w, unsigned int h)
60 {
61    EScreen            *es;
62
63    n_screens++;
64    p_screens = EREALLOC(EScreen, p_screens, n_screens);
65
66    es = p_screens + n_screens - 1;
67    es->type = type;
68    es->head = head;
69    es->x = x;
70    es->y = y;
71    es->w = w;
72    es->h = h;
73 }
74
75 void
76 ScreenInit(void)
77 {
78 #ifdef USE_XINERAMA
79    XineramaScreenInfo *screens;
80    int                 i, num_screens;
81 #endif
82
83    n_screens = 0;               /* Causes reconfiguration */
84
85 #ifdef USE_XINERAMA
86    if (Mode.wm.window)
87       return;
88
89    screens = EXineramaQueryScreens(&num_screens);
90
91    Mode.display.xinerama_active = (XineramaIsActive(disp)) ? 1 : 0;
92    if (!Mode.display.xinerama_active && num_screens > 1)
93       Mode.display.xinerama_active = 2;
94
95    if (num_screens > 1)
96      {
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);
100      }
101
102    if (screens)
103       XFree(screens);
104 #endif
105 }
106
107 void
108 ScreenSplit(unsigned int nx, unsigned int ny)
109 {
110    unsigned int        i, j;
111
112    if (nx > 8 || ny > 8)        /* At least some limit */
113       return;
114
115    if (nx == 0 || ny == 0)
116      {
117         ScreenInit();
118         return;
119      }
120
121    n_screens = 0;               /* Causes reconfiguration */
122
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);
128 }
129
130 void
131 ScreenShowInfo(const char *prm __UNUSED__)
132 {
133    int                 i;
134
135 #ifdef USE_XINERAMA
136    static const char  *const mt[] = { "Off", "On", "TV", "???" };
137    XineramaScreenInfo *scrns;
138    int                 num, mode;
139 #endif
140
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));
145
146 #ifdef USE_XINERAMA
147    scrns = EXineramaQueryScreens(&num);
148
149    mode = (XineramaIsActive(disp)) ? 1 : 0;
150    if (!mode && num > 1)
151       mode = 2;
152
153    IpcPrintf("Xinerama mode: %s\n", mt[mode]);
154
155    if (scrns)
156      {
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,
162                      scrns[i].height);
163         XFree(scrns);
164      }
165 #endif
166
167    if (n_screens)
168      {
169         IpcPrintf("E-screens:\n");
170         for (i = 0; i < n_screens; i++)
171           {
172              EScreen            *ps = p_screens + i;
173
174              IpcPrintf(" %2d     %2d       %5d     %5d     %5d     %5d\n",
175                        i, ps->head, ps->x, ps->y, ps->w, ps->h);
176           }
177      }
178 }
179
180 void
181 ScreenGetGeometryByHead(int head, int *px, int *py, int *pw, int *ph)
182 {
183    EScreen            *ps;
184    int                 x, y, w, h;
185
186    if (head >= 0 && head < n_screens)
187      {
188         ps = p_screens + head;
189         x = ps->x;
190         y = ps->y;
191         w = ps->w;
192         h = ps->h;
193      }
194    else
195      {
196         x = 0;
197         y = 0;
198         w = WinGetW(VROOT);
199         h = WinGetH(VROOT);
200      }
201
202    *px = x;
203    *py = y;
204    *pw = w;
205    *ph = h;
206 }
207
208 int
209 ScreenGetGeometry(int xi, int yi, int *px, int *py, int *pw, int *ph)
210 {
211    int                 i, dx, dy, dist, head;
212    EScreen            *ps;
213
214    head = 0;
215    dist = 2147483647;
216
217    if (n_screens > 1)
218      {
219         for (i = 0; i < n_screens; i++)
220           {
221              ps = p_screens + i;
222
223              if (xi >= ps->x && xi < ps->x + ps->w &&
224                  yi >= ps->y && yi < ps->y + ps->h)
225                {
226                   /* Inside - done */
227                   head = i;
228                   break;
229                }
230              dx = xi - (ps->x + ps->w / 2);
231              dy = yi - (ps->y + ps->h / 2);
232              dx = dx * dx + dy * dy;
233              if (dx >= dist)
234                 continue;
235              dist = dx;
236              head = i;
237           }
238      }
239
240    ScreenGetGeometryByHead(head, px, py, pw, ph);
241
242    return head;
243 }
244
245 static void
246 VRootGetAvailableArea(int *px, int *py, int *pw, int *ph)
247 {
248    EWin               *const *lst, *ewin;
249    int                 i, num, l, r, t, b;
250
251    l = r = t = b = 0;
252    lst = EwinListGetAll(&num);
253    for (i = 0; i < num; i++)
254      {
255         ewin = lst[i];
256
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)
262            t = ewin->strut.top;
263         if (b < ewin->strut.bottom)
264            b = ewin->strut.bottom;
265      }
266
267    *px = l;
268    *py = t;
269    *pw = WinGetW(VROOT) - (l + r);
270    *ph = WinGetH(VROOT) - (t + b);
271 }
272
273 int
274 ScreenGetAvailableArea(int xi, int yi, int *px, int *py, int *pw, int *ph)
275 {
276    int                 x1, y1, w1, h1, x2, y2, w2, h2, head;
277
278    head = ScreenGetGeometry(xi, yi, &x1, &y1, &w1, &h1);
279
280    if (!Conf.place.ignore_struts)
281      {
282         VRootGetAvailableArea(&x2, &y2, &w2, &h2);
283         if (x1 < x2)
284            x1 = x2;
285         if (y1 < y2)
286            y1 = y2;
287         if (w1 > w2)
288            w1 = w2;
289         if (h1 > h2)
290            h1 = h2;
291      }
292
293    *px = x1;
294    *py = y1;
295    *pw = w1;
296    *ph = h1;
297
298    return head;
299 }
300
301 int
302 ScreenGetGeometryByPointer(int *px, int *py, int *pw, int *ph)
303 {
304    int                 pointer_x, pointer_y;
305
306    EQueryPointer(NULL, &pointer_x, &pointer_y, NULL, NULL);
307
308    return ScreenGetGeometry(pointer_x, pointer_y, px, py, pw, ph);
309 }
310
311 int
312 ScreenGetAvailableAreaByPointer(int *px, int *py, int *pw, int *ph)
313 {
314    int                 pointer_x, pointer_y;
315
316    EQueryPointer(NULL, &pointer_x, &pointer_y, NULL, NULL);
317
318    return ScreenGetAvailableArea(pointer_x, pointer_y, px, py, pw, ph);
319 }