changed indentation to use spaces only
[wmaker-crm.git] / src / xinerama.c
blob7be437b4185b8ee94bacef770eabc3b55bb78d5f
1 /*
2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
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.
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.
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.
23 #include "wconfig.h"
26 #include "xinerama.h"
28 #include "screen.h"
29 #include "window.h"
30 #include "framewin.h"
31 #include "wcore.h"
32 #include "funcs.h"
34 #ifdef XINERAMA
35 # ifdef SOLARIS_XINERAMA /* sucks */
36 # include <X11/extensions/xinerama.h>
37 # else
38 # include <X11/extensions/Xinerama.h>
39 # endif
40 #endif
42 extern WPreferences wPreferences;
44 void
45 wInitXinerama(WScreen *scr)
47 scr->xine_info.primary_head = 0;
48 scr->xine_info.screens = NULL;
49 scr->xine_info.count = 0;
50 #ifdef XINERAMA
51 # ifdef SOLARIS_XINERAMA
52 if (XineramaGetState(dpy, scr->screen)) {
53 WXineramaInfo *info = &scr->xine_info;
54 XRectangle head[MAXFRAMEBUFFERS];
55 unsigned char hints[MAXFRAMEBUFFERS];
56 int i;
58 if (XineramaGetInfo(dpy, scr->screen, head, hints, &info->count)) {
60 info->screens = wmalloc(sizeof(WMRect)*(info->count+1));
62 for (i=0; i<info->count; i++) {
63 info->screens[i].pos.x = head[i].x;
64 info->screens[i].pos.y = head[i].y;
65 info->screens[i].size.width = head[i].width;
66 info->screens[i].size.height = head[i].height;
70 # else /* !SOLARIS_XINERAMA */
71 if (XineramaIsActive(dpy)) {
72 XineramaScreenInfo *xine_screens;
73 WXineramaInfo *info = &scr->xine_info;
74 int i;
76 xine_screens = XineramaQueryScreens(dpy, &info->count);
78 info->screens = wmalloc(sizeof(WMRect)*(info->count+1));
80 for (i=0; i<info->count; i++) {
81 info->screens[i].pos.x = xine_screens[i].x_org;
82 info->screens[i].pos.y = xine_screens[i].y_org;
83 info->screens[i].size.width = xine_screens[i].width;
84 info->screens[i].size.height = xine_screens[i].height;
86 XFree(xine_screens);
88 # endif /* !SOLARIS_XINERAMA */
89 #endif /* XINERAMA */
93 int
94 wGetRectPlacementInfo(WScreen *scr, WMRect rect, int *flags)
96 int best;
97 unsigned long area, totalArea;
98 int i;
99 int rx = rect.pos.x;
100 int ry = rect.pos.y;
101 int rw = rect.size.width;
102 int rh = rect.size.height;
104 wassertrv(flags!=NULL, 0);
106 best = -1;
107 area = 0;
108 totalArea = 0;
110 *flags = XFLAG_NONE;
112 if (scr->xine_info.count <= 1) {
113 unsigned long a;
115 a = calcIntersectionArea(rx, ry, rw, rh,
116 0, 0, scr->scr_width, scr->scr_height);
118 if (a == 0) {
119 *flags |= XFLAG_DEAD;
120 } else if (a != rw*rh) {
121 *flags |= XFLAG_PARTIAL;
124 return scr->xine_info.primary_head;
127 for (i = 0; i < wXineramaHeads(scr); i++) {
128 unsigned long a;
130 a = calcIntersectionArea(rx, ry, rw, rh,
131 scr->xine_info.screens[i].pos.x,
132 scr->xine_info.screens[i].pos.y,
133 scr->xine_info.screens[i].size.width,
134 scr->xine_info.screens[i].size.height);
136 totalArea += a;
137 if (a > area) {
138 if (best != -1)
139 *flags |= XFLAG_MULTIPLE;
140 area = a;
141 best = i;
145 if (best == -1) {
146 *flags |= XFLAG_DEAD;
147 best = wGetHeadForPointerLocation(scr);
148 } else if (totalArea != rw*rh)
149 *flags |= XFLAG_PARTIAL;
151 return best;
156 /* get the head that covers most of the rectangle */
158 wGetHeadForRect(WScreen *scr, WMRect rect)
160 int best;
161 unsigned long area;
162 int i;
163 int rx = rect.pos.x;
164 int ry = rect.pos.y;
165 int rw = rect.size.width;
166 int rh = rect.size.height;
168 if (!scr->xine_info.count)
169 return scr->xine_info.primary_head;
171 best = -1;
172 area = 0;
174 for (i = 0; i < wXineramaHeads(scr); i++) {
175 unsigned long a;
177 a = calcIntersectionArea(rx, ry, rw, rh,
178 scr->xine_info.screens[i].pos.x,
179 scr->xine_info.screens[i].pos.y,
180 scr->xine_info.screens[i].size.width,
181 scr->xine_info.screens[i].size.height);
183 if (a > area) {
184 area = a;
185 best = i;
190 * in case rect is in dead space, return valid head
192 if (best == -1)
193 best = wGetHeadForPointerLocation(scr);
195 return best;
199 Bool
200 wWindowTouchesHead(WWindow *wwin, int head)
202 WScreen * scr;
203 WMRect rect;
204 int a;
206 if (!wwin || !wwin->frame)
207 return False;
209 scr = wwin->screen_ptr;
210 rect = wGetRectForHead(scr, head);
211 a = calcIntersectionArea(wwin->frame_x, wwin->frame_y,
212 wwin->frame->core->width,
213 wwin->frame->core->height,
214 rect.pos.x, rect.pos.y,
215 rect.size.width, rect.size.height);
217 return (a != 0);
222 wGetHeadForWindow(WWindow *wwin)
224 WMRect rect;
226 if (wwin == NULL || wwin->frame == NULL)
227 return 0;
229 rect.pos.x = wwin->frame_x;
230 rect.pos.y = wwin->frame_y;
231 rect.size.width = wwin->frame->core->width;
232 rect.size.height = wwin->frame->core->height;
234 return wGetHeadForRect(wwin->screen_ptr, rect);
240 wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags)
242 int i;
244 // paranoia
245 if (flags == NULL) {
246 static int tmp;
247 flags = &tmp;
249 *flags = XFLAG_NONE;
251 for (i = 0; i < scr->xine_info.count; i++) {
252 #if 0
253 int yy, xx;
255 xx = scr->xine_info.screens[i].pos.x + scr->xine_info.screens[i].size.width;
256 yy = scr->xine_info.screens[i].pos.y + scr->xine_info.screens[i].size.height;
257 if (point.x >= scr->xine_info.screens[i].pos.x &&
258 point.y >= scr->xine_info.screens[i].pos.y &&
259 point.x < xx && point.y < yy) {
260 return i;
262 #else
263 XineramaScreenInfo *xsi = &scr->xine_info.screens[i];
265 if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
266 (unsigned)(point.y - xsi->y_org) < xsi->height)
267 return i;
268 #endif
271 *flags |= XFLAG_DEAD;
273 return scr->xine_primary_head;
280 wGetHeadForPoint(WScreen *scr, WMPoint point)
282 int i;
284 for (i = 0; i < scr->xine_info.count; i++) {
285 WMRect *rect = &scr->xine_info.screens[i];
287 if ((unsigned)(point.x - rect->pos.x) < rect->size.width &&
288 (unsigned)(point.y - rect->pos.y) < rect->size.height)
289 return i;
291 return scr->xine_info.primary_head;
296 wGetHeadForPointerLocation(WScreen *scr)
298 WMPoint point;
299 Window bla;
300 int ble;
301 unsigned int blo;
303 if (!scr->xine_info.count)
304 return scr->xine_info.primary_head;
306 if (!XQueryPointer(dpy, scr->root_win, &bla, &bla,
307 &point.x, &point.y,
308 &ble, &ble,
309 &blo))
310 return scr->xine_info.primary_head;
312 return wGetHeadForPoint(scr, point);
315 /* get the dimensions of the head */
316 WMRect
317 wGetRectForHead(WScreen *scr, int head)
319 WMRect rect;
321 if (head < scr->xine_info.count) {
322 rect.pos.x = scr->xine_info.screens[head].pos.x;
323 rect.pos.y = scr->xine_info.screens[head].pos.y;
324 rect.size.width = scr->xine_info.screens[head].size.width;
325 rect.size.height = scr->xine_info.screens[head].size.height;
326 } else {
327 rect.pos.x = 0;
328 rect.pos.y = 0;
329 rect.size.width = scr->scr_width;
330 rect.size.height = scr->scr_height;
333 return rect;
337 WArea
338 wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr, Bool noicons)
340 WArea totalArea, usableArea;
341 WMRect rect = wGetRectForHead(scr, head);
343 totalArea.x1 = rect.pos.x;
344 totalArea.y1 = rect.pos.y;
345 totalArea.x2 = totalArea.x1 + rect.size.width;
346 totalArea.y2 = totalArea.y1 + rect.size.height;
348 if (totalAreaPtr != NULL) *totalAreaPtr = totalArea;
350 if (head < wXineramaHeads(scr)) {
351 usableArea = noicons ? scr->totalUsableArea[head] : scr->usableArea[head];
352 } else
353 usableArea = totalArea;
355 return usableArea;
359 WMPoint
360 wGetPointToCenterRectInHead(WScreen *scr, int head, int width, int height)
362 WMPoint p;
363 WMRect rect = wGetRectForHead(scr, head);
365 p.x = rect.pos.x + (rect.size.width - width)/2;
366 p.y = rect.pos.y + (rect.size.height - height)/2;
368 return p;