xinerama stuff for solaris
[wmaker-crm.git] / src / xinerama.c
blob202576e56c3bb8533d038c03d798f62570153007
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.
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 # define <X11/extensions/xinerama.h>
37 # else
38 # include <X11/extensions/Xinerama.h>
39 # endif
40 #endif
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 header[MAXFRAMEBUFFERS];
55 unsigned char hints[MAXFRAMEBUFFERS];
56 int i;
58 if (XineramaGetInfo(dpy, scr->screen, header, hints,
59 &info->count)) {
61 info->screens = wmalloc(sizeof(WMRect)*(info->count+1));
63 for (i=0; i<info->count; i++) {
64 info->screens[i].pos.x = head[i].x;
65 info->screens[i].pos.y = head[i].y;
66 info->screens[i].size.width = head[i].width;
67 info->screens[i].size.height = head[i].height;
71 # else /* !SOLARIS_XINERAMA */
72 if (XineramaIsActive(dpy)) {
73 XineramaInfo *xine_screens;
74 WXineramaInfo *info = &scr->xine_info;
75 int i;
77 xine_screens = XineramaQueryScreens(dpy, &info->count);
79 info->screens = wmalloc(sizeof(WMRect)*(info->count+1));
81 for (i=0; i<info->count; i++) {
82 info->screens[i].pos.x = info->screens[i].x_org;
83 info->screens[i].pos.y = info->screens[i].y_org;
84 info->screens[i].size.width = info->screens[i].width;
85 info->screens[i].size.height = info->screens[i].height;
87 XFree(xine_screens);
89 # endif /* !SOLARIS_XINERAMA */
90 #endif /* XINERAMA */
94 int
95 wGetRectPlacementInfo(WScreen *scr, WMRect rect, int *flags)
97 int best;
98 unsigned long area, totalArea;
99 int i;
100 int rx = rect.pos.x;
101 int ry = rect.pos.y;
102 int rw = rect.size.width;
103 int rh = rect.size.height;
105 wassertrv(flags!=NULL, 0);
107 best = -1;
108 area = 0;
109 totalArea = 0;
111 *flags = XFLAG_NONE;
113 if (scr->xine_info.count <= 1) {
114 unsigned long a;
116 a = calcIntersectionArea(rx, ry, rw, rh,
117 0, 0, scr->scr_width, scr->scr_height);
119 if (a == 0) {
120 *flags |= XFLAG_DEAD;
121 } else if (a != rw*rh) {
122 *flags |= XFLAG_PARTIAL;
125 return scr->xine_info.primary_head;
128 for (i = 0; i < scr->xine_info.count; i++) {
129 unsigned long a;
131 a = calcIntersectionArea(rx, ry, rw, rh,
132 scr->xine_info.screens[i].pos.x,
133 scr->xine_info.screens[i].pos.y,
134 scr->xine_info.screens[i].size.width,
135 scr->xine_info.screens[i].size.height);
137 totalArea += a;
138 if (a > area) {
139 if ( best != -1)
140 *flags |= XFLAG_MULTIPLE;
141 area = a;
142 best = i;
146 if ( best == -1) {
147 *flags |= XFLAG_DEAD;
148 best = wGetHeadForPointerLocation(scr);
149 } else if ( totalArea != rw*rh)
150 *flags |= XFLAG_PARTIAL;
152 return best;
157 /* get the head that covers most of the rectangle */
159 wGetHeadForRect(WScreen *scr, WMRect rect)
161 int best;
162 unsigned long area;
163 int i;
164 int rx = rect.pos.x;
165 int ry = rect.pos.y;
166 int rw = rect.size.width;
167 int rh = rect.size.height;
169 if (!scr->xine_info.count)
170 return scr->xine_info.primary_head;
172 best = -1;
173 area = 0;
175 for (i = 0; i < scr->xine_info.count; i++) {
176 unsigned long a;
178 a = calcIntersectionArea(rx, ry, rw, rh,
179 scr->xine_info.screens[i].pos.x,
180 scr->xine_info.screens[i].pos.y,
181 scr->xine_info.screens[i].size.width,
182 scr->xine_info.screens[i].size.height);
184 if (a > area) {
185 area = a;
186 best = i;
191 * in case rect is in dead space, return valid head
193 if (best == -1)
194 best = wGetHeadForPointerLocation(scr);
196 return best;
201 wGetHeadForWindow(WWindow *wwin)
203 WMRect rect;
205 rect.pos.x = wwin->frame_x;
206 rect.pos.y = wwin->frame_y;
207 rect.size.width = wwin->frame->core->width;
208 rect.size.height = wwin->frame->core->height;
210 return wGetHeadForRect(wwin->screen_ptr, rect);
215 int wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags)
217 int i;
219 // paranoia
220 if ( flags == NULL) {
221 static int tmp;
222 flags = &tmp;
224 *flags = XFLAG_NONE;
226 for (i = 0; i < scr->xine_info.count; i++) {
227 #if 0
228 int yy, xx;
230 xx = scr->xine_info.screens[i].pos.x + scr->xine_info.screens[i].size.width;
231 yy = scr->xine_info.screens[i].pos.y + scr->xine_info.screens[i].size.height;
232 if (point.x >= scr->xine_info.screens[i].pos.x &&
233 point.y >= scr->xine_info.screens[i].pos.y &&
234 point.x < xx && point.y < yy) {
235 return i;
237 #else
238 XineramaScreenInfo *xsi = &scr->xine_info.screens[i];
240 if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
241 (unsigned)(point.y - xsi->y_org) < xsi->height)
242 return i;
243 #endif
246 *flags |= XFLAG_DEAD;
248 return scr->xine_primary_head;
255 wGetHeadForPoint(WScreen *scr, WMPoint point)
257 int i;
259 for (i = 0; i < scr->xine_info.count; i++) {
260 WMRect *rect = &scr->xine_info.screens[i];
262 if ((unsigned)(point.x - rect->pos.x) < rect->size.width &&
263 (unsigned)(point.y - rect->pos.y) < rect->size.height)
264 return i;
266 return scr->xine_info.primary_head;
271 wGetHeadForPointerLocation(WScreen *scr)
273 WMPoint point;
274 Window bla;
275 int ble;
276 unsigned int blo;
278 if (!scr->xine_info.count)
279 return scr->xine_info.primary_head;
281 if (!XQueryPointer(dpy, scr->root_win, &bla, &bla,
282 &point.x, &point.y,
283 &ble, &ble,
284 &blo))
285 return scr->xine_info.primary_head;
287 return wGetHeadForPoint(scr, point);
290 /* get the dimensions of the head */
291 WMRect
292 wGetRectForHead(WScreen *scr, int head)
294 WMRect rect;
296 if (head < scr->xine_info.count) {
297 rect.pos.x = scr->xine_info.screens[head].pos.x;
298 rect.pos.y = scr->xine_info.screens[head].pos.y;
299 rect.size.width = scr->xine_info.screens[head].size.width;
300 rect.size.height = scr->xine_info.screens[head].size.height;
301 } 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;
314 WArea
315 wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr)
317 WArea totalArea, usableArea = scr->totalUsableArea;
318 WMRect rect = wGetRectForHead(scr, head);
320 totalArea.x1 = rect.pos.x;
321 totalArea.y1 = rect.pos.y;
322 totalArea.x2 = totalArea.x1 + rect.size.width;
323 totalArea.y2 = totalArea.y1 + rect.size.height;
325 if (totalAreaPtr != NULL) *totalAreaPtr = totalArea;
327 usableArea.x1 = WMAX(totalArea.x1, usableArea.x1);
328 usableArea.y1 = WMAX(totalArea.y1, usableArea.y1);
329 usableArea.x2 = WMIN(totalArea.x2, usableArea.x2);
330 usableArea.y2 = WMIN(totalArea.y2, usableArea.y2);
332 return usableArea;
336 WMPoint
337 wGetPointToCenterRectInHead(WScreen *scr, int head, int width, int height)
339 WMPoint p;
340 WMRect rect = wGetRectForHead(scr, head);
342 p.x = rect.pos.x + (rect.size.width - width)/2;
343 p.y = rect.pos.y + (rect.size.height - height)/2;
345 return p;