Change to the linux kernel coding style
[wmaker-crm.git] / src / xinerama.c
blob786c214d4102247fb7561be04a3c4f2174439057
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.
22 #include "wconfig.h"
24 #include "xinerama.h"
26 #include "screen.h"
27 #include "window.h"
28 #include "framewin.h"
29 #include "wcore.h"
30 #include "funcs.h"
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
40 extern WPreferences wPreferences;
42 void wInitXinerama(WScreen * scr)
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;
55 if (XineramaGetInfo(dpy, scr->screen, head, hints, &info->count)) {
57 info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
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;
67 # else /* !SOLARIS_XINERAMA */
68 if (XineramaIsActive(dpy)) {
69 XineramaScreenInfo *xine_screens;
70 WXineramaInfo *info = &scr->xine_info;
71 int i;
73 xine_screens = XineramaQueryScreens(dpy, &info->count);
75 info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
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;
83 XFree(xine_screens);
85 # endif /* !SOLARIS_XINERAMA */
86 #endif /* XINERAMA */
89 int wGetRectPlacementInfo(WScreen * scr, WMRect rect, int *flags)
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;
99 wassertrv(flags != NULL, 0);
101 best = -1;
102 area = 0;
103 totalArea = 0;
105 *flags = XFLAG_NONE;
107 if (scr->xine_info.count <= 1) {
108 unsigned long a;
110 a = calcIntersectionArea(rx, ry, rw, rh, 0, 0, scr->scr_width, scr->scr_height);
112 if (a == 0) {
113 *flags |= XFLAG_DEAD;
114 } else if (a != rw * rh) {
115 *flags |= XFLAG_PARTIAL;
118 return scr->xine_info.primary_head;
121 for (i = 0; i < wXineramaHeads(scr); i++) {
122 unsigned long a;
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);
130 totalArea += a;
131 if (a > area) {
132 if (best != -1)
133 *flags |= XFLAG_MULTIPLE;
134 area = a;
135 best = i;
139 if (best == -1) {
140 *flags |= XFLAG_DEAD;
141 best = wGetHeadForPointerLocation(scr);
142 } else if (totalArea != rw * rh)
143 *flags |= XFLAG_PARTIAL;
145 return best;
148 /* get the head that covers most of the rectangle */
149 int wGetHeadForRect(WScreen * scr, WMRect rect)
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;
159 if (!scr->xine_info.count)
160 return scr->xine_info.primary_head;
162 best = -1;
163 area = 0;
165 for (i = 0; i < wXineramaHeads(scr); i++) {
166 unsigned long a;
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);
174 if (a > area) {
175 area = a;
176 best = i;
181 * in case rect is in dead space, return valid head
183 if (best == -1)
184 best = wGetHeadForPointerLocation(scr);
186 return best;
189 Bool wWindowTouchesHead(WWindow * wwin, int head)
191 WScreen *scr;
192 WMRect rect;
193 int a;
195 if (!wwin || !wwin->frame)
196 return False;
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);
205 return (a != 0);
208 int wGetHeadForWindow(WWindow * wwin)
210 WMRect rect;
212 if (wwin == NULL || wwin->frame == NULL)
213 return 0;
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;
220 return wGetHeadForRect(wwin->screen_ptr, rect);
225 wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags)
227 int i;
229 // paranoia
230 if (flags == NULL) {
231 static int tmp;
232 flags = &tmp;
234 *flags = XFLAG_NONE;
236 for (i = 0; i < scr->xine_info.count; i++) {
237 #if 0
238 int yy, xx;
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;
247 #else
248 XineramaScreenInfo *xsi = &scr->xine_info.screens[i];
250 if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
251 (unsigned)(point.y - xsi->y_org) < xsi->height)
252 return i;
253 #endif
256 *flags |= XFLAG_DEAD;
258 return scr->xine_primary_head;
262 int wGetHeadForPoint(WScreen * scr, WMPoint point)
264 int i;
266 for (i = 0; i < scr->xine_info.count; i++) {
267 WMRect *rect = &scr->xine_info.screens[i];
269 if ((unsigned)(point.x - rect->pos.x) < rect->size.width &&
270 (unsigned)(point.y - rect->pos.y) < rect->size.height)
271 return i;
273 return scr->xine_info.primary_head;
276 int wGetHeadForPointerLocation(WScreen * scr)
278 WMPoint point;
279 Window bla;
280 int ble;
281 unsigned int blo;
283 if (!scr->xine_info.count)
284 return scr->xine_info.primary_head;
286 if (!XQueryPointer(dpy, scr->root_win, &bla, &bla, &point.x, &point.y, &ble, &ble, &blo))
287 return scr->xine_info.primary_head;
289 return wGetHeadForPoint(scr, point);
292 /* get the dimensions of the head */
293 WMRect wGetRectForHead(WScreen * scr, int head)
295 WMRect rect;
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;
309 return rect;
312 WArea wGetUsableAreaForHead(WScreen * scr, int head, WArea * totalAreaPtr, Bool noicons)
314 WArea totalArea, usableArea;
315 WMRect rect = wGetRectForHead(scr, head);
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;
322 if (totalAreaPtr != NULL)
323 *totalAreaPtr = totalArea;
325 if (head < wXineramaHeads(scr)) {
326 usableArea = noicons ? scr->totalUsableArea[head] : scr->usableArea[head];
327 } else
328 usableArea = totalArea;
330 return usableArea;
333 WMPoint wGetPointToCenterRectInHead(WScreen * scr, int head, int width, int height)
335 WMPoint p;
336 WMRect rect = wGetRectForHead(scr, head);
338 p.x = rect.pos.x + (rect.size.width - width) / 2;
339 p.y = rect.pos.y + (rect.size.height - height) / 2;
341 return p;