Change to the linux kernel coding style
[wmaker-crm.git] / src / xinerama.c
1 /*
2 * Window Maker window manager
3 *
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 * USA.
20 */
21
22 #include "wconfig.h"
23
24 #include "xinerama.h"
25
26 #include "screen.h"
27 #include "window.h"
28 #include "framewin.h"
29 #include "wcore.h"
30 #include "funcs.h"
31
32 #ifdef XINERAMA
33 # ifdef SOLARIS_XINERAMA /* sucks */
34 # include <X11/extensions/xinerama.h>
35 # else
36 # include <X11/extensions/Xinerama.h>
37 # endif
38 #endif
39
40 extern WPreferences wPreferences;
41
42 void wInitXinerama(WScreen * scr)
43 {
44 scr->xine_info.primary_head = 0;
45 scr->xine_info.screens = NULL;
46 scr->xine_info.count = 0;
47 #ifdef XINERAMA
48 # ifdef SOLARIS_XINERAMA
49 if (XineramaGetState(dpy, scr->screen)) {
50 WXineramaInfo *info = &scr->xine_info;
51 XRectangle head[MAXFRAMEBUFFERS];
52 unsigned char hints[MAXFRAMEBUFFERS];
53 int i;
54
55 if (XineramaGetInfo(dpy, scr->screen, head, hints, &info->count)) {
56
57 info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
58
59 for (i = 0; i < info->count; i++) {
60 info->screens[i].pos.x = head[i].x;
61 info->screens[i].pos.y = head[i].y;
62 info->screens[i].size.width = head[i].width;
63 info->screens[i].size.height = head[i].height;
64 }
65 }
66 }
67 # else /* !SOLARIS_XINERAMA */
68 if (XineramaIsActive(dpy)) {
69 XineramaScreenInfo *xine_screens;
70 WXineramaInfo *info = &scr->xine_info;
71 int i;
72
73 xine_screens = XineramaQueryScreens(dpy, &info->count);
74
75 info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
76
77 for (i = 0; i < info->count; i++) {
78 info->screens[i].pos.x = xine_screens[i].x_org;
79 info->screens[i].pos.y = xine_screens[i].y_org;
80 info->screens[i].size.width = xine_screens[i].width;
81 info->screens[i].size.height = xine_screens[i].height;
82 }
83 XFree(xine_screens);
84 }
85 # endif /* !SOLARIS_XINERAMA */
86 #endif /* XINERAMA */
87 }
88
89 int wGetRectPlacementInfo(WScreen * scr, WMRect rect, int *flags)
90 {
91 int best;
92 unsigned long area, totalArea;
93 int i;
94 int rx = rect.pos.x;
95 int ry = rect.pos.y;
96 int rw = rect.size.width;
97 int rh = rect.size.height;
98
99 wassertrv(flags != NULL, 0);
100
101 best = -1;
102 area = 0;
103 totalArea = 0;
104
105 *flags = XFLAG_NONE;
106
107 if (scr->xine_info.count <= 1) {
108 unsigned long a;
109
110 a = calcIntersectionArea(rx, ry, rw, rh, 0, 0, scr->scr_width, scr->scr_height);
111
112 if (a == 0) {
113 *flags |= XFLAG_DEAD;
114 } else if (a != rw * rh) {
115 *flags |= XFLAG_PARTIAL;
116 }
117
118 return scr->xine_info.primary_head;
119 }
120
121 for (i = 0; i < wXineramaHeads(scr); i++) {
122 unsigned long a;
123
124 a = calcIntersectionArea(rx, ry, rw, rh,
125 scr->xine_info.screens[i].pos.x,
126 scr->xine_info.screens[i].pos.y,
127 scr->xine_info.screens[i].size.width,
128 scr->xine_info.screens[i].size.height);
129
130 totalArea += a;
131 if (a > area) {
132 if (best != -1)
133 *flags |= XFLAG_MULTIPLE;
134 area = a;
135 best = i;
136 }
137 }
138
139 if (best == -1) {
140 *flags |= XFLAG_DEAD;
141 best = wGetHeadForPointerLocation(scr);
142 } else if (totalArea != rw * rh)
143 *flags |= XFLAG_PARTIAL;
144
145 return best;
146 }
147
148 /* get the head that covers most of the rectangle */
149 int wGetHeadForRect(WScreen * scr, WMRect rect)
150 {
151 int best;
152 unsigned long area;
153 int i;
154 int rx = rect.pos.x;
155 int ry = rect.pos.y;
156 int rw = rect.size.width;
157 int rh = rect.size.height;
158
159 if (!scr->xine_info.count)
160 return scr->xine_info.primary_head;
161
162 best = -1;
163 area = 0;
164
165 for (i = 0; i < wXineramaHeads(scr); i++) {
166 unsigned long a;
167
168 a = calcIntersectionArea(rx, ry, rw, rh,
169 scr->xine_info.screens[i].pos.x,
170 scr->xine_info.screens[i].pos.y,
171 scr->xine_info.screens[i].size.width,
172 scr->xine_info.screens[i].size.height);
173
174 if (a > area) {
175 area = a;
176 best = i;
177 }
178 }
179
180 /*
181 * in case rect is in dead space, return valid head
182 */
183 if (best == -1)
184 best = wGetHeadForPointerLocation(scr);
185
186 return best;
187 }
188
189 Bool wWindowTouchesHead(WWindow * wwin, int head)
190 {
191 WScreen *scr;
192 WMRect rect;
193 int a;
194
195 if (!wwin || !wwin->frame)
196 return False;
197
198 scr = wwin->screen_ptr;
199 rect = wGetRectForHead(scr, head);
200 a = calcIntersectionArea(wwin->frame_x, wwin->frame_y,
201 wwin->frame->core->width,
202 wwin->frame->core->height,
203 rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
204
205 return (a != 0);
206 }
207
208 int wGetHeadForWindow(WWindow * wwin)
209 {
210 WMRect rect;
211
212 if (wwin == NULL || wwin->frame == NULL)
213 return 0;
214
215 rect.pos.x = wwin->frame_x;
216 rect.pos.y = wwin->frame_y;
217 rect.size.width = wwin->frame->core->width;
218 rect.size.height = wwin->frame->core->height;
219
220 return wGetHeadForRect(wwin->screen_ptr, rect);
221 }
222
223 /*
224 int
225 wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags)
226 {
227 int i;
228
229 // paranoia
230 if (flags == NULL) {
231 static int tmp;
232 flags = &tmp;
233 }
234 *flags = XFLAG_NONE;
235
236 for (i = 0; i < scr->xine_info.count; i++) {
237 #if 0
238 int yy, xx;
239
240 xx = scr->xine_info.screens[i].pos.x + scr->xine_info.screens[i].size.width;
241 yy = scr->xine_info.screens[i].pos.y + scr->xine_info.screens[i].size.height;
242 if (point.x >= scr->xine_info.screens[i].pos.x &&
243 point.y >= scr->xine_info.screens[i].pos.y &&
244 point.x < xx && point.y < yy) {
245 return i;
246 }
247 #else
248 XineramaScreenInfo *xsi = &scr->xine_info.screens[i];
249
250 if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
251 (unsigned)(point.y - xsi->y_org) < xsi->height)
252 return i;
253 #endif
254 }
255
256 *flags |= XFLAG_DEAD;
257
258 return scr->xine_primary_head;
259 }
260 */
261
262 int wGetHeadForPoint(WScreen * scr, WMPoint point)
263 {
264 int i;
265
266 for (i = 0; i < scr->xine_info.count; i++) {
267 WMRect *rect = &scr->xine_info.screens[i];
268
269 if ((unsigned)(point.x - rect->pos.x) < rect->size.width &&
270 (unsigned)(point.y - rect->pos.y) < rect->size.height)
271 return i;
272 }
273 return scr->xine_info.primary_head;
274 }
275
276 int wGetHeadForPointerLocation(WScreen * scr)
277 {
278 WMPoint point;
279 Window bla;
280 int ble;
281 unsigned int blo;
282
283 if (!scr->xine_info.count)
284 return scr->xine_info.primary_head;
285
286 if (!XQueryPointer(dpy, scr->root_win, &bla, &bla, &point.x, &point.y, &ble, &ble, &blo))
287 return scr->xine_info.primary_head;
288
289 return wGetHeadForPoint(scr, point);
290 }
291
292 /* get the dimensions of the head */
293 WMRect wGetRectForHead(WScreen * scr, int head)
294 {
295 WMRect rect;
296
297 if (head < scr->xine_info.count) {
298 rect.pos.x = scr->xine_info.screens[head].pos.x;
299 rect.pos.y = scr->xine_info.screens[head].pos.y;
300 rect.size.width = scr->xine_info.screens[head].size.width;
301 rect.size.height = scr->xine_info.screens[head].size.height;
302 } else {
303 rect.pos.x = 0;
304 rect.pos.y = 0;
305 rect.size.width = scr->scr_width;
306 rect.size.height = scr->scr_height;
307 }
308
309 return rect;
310 }
311
312 WArea wGetUsableAreaForHead(WScreen * scr, int head, WArea * totalAreaPtr, Bool noicons)
313 {
314 WArea totalArea, usableArea;
315 WMRect rect = wGetRectForHead(scr, head);
316
317 totalArea.x1 = rect.pos.x;
318 totalArea.y1 = rect.pos.y;
319 totalArea.x2 = totalArea.x1 + rect.size.width;
320 totalArea.y2 = totalArea.y1 + rect.size.height;
321
322 if (totalAreaPtr != NULL)
323 *totalAreaPtr = totalArea;
324
325 if (head < wXineramaHeads(scr)) {
326 usableArea = noicons ? scr->totalUsableArea[head] : scr->usableArea[head];
327 } else
328 usableArea = totalArea;
329
330 return usableArea;
331 }
332
333 WMPoint wGetPointToCenterRectInHead(WScreen * scr, int head, int width, int height)
334 {
335 WMPoint p;
336 WMRect rect = wGetRectForHead(scr, head);
337
338 p.x = rect.pos.x + (rect.size.width - width) / 2;
339 p.y = rect.pos.y + (rect.size.height - height) / 2;
340
341 return p;
342 }