Improve dockapp recognition
[wmaker-crm.git] / src / xinerama.c
blob7e630335263f6d39f1939e45a72c232eb199f7b8
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 "funcs.h"
31 #ifdef XINERAMA
32 # ifdef SOLARIS_XINERAMA /* sucks */
33 # include <X11/extensions/xinerama.h>
34 # else
35 # include <X11/extensions/Xinerama.h>
36 # endif
37 #endif
39 void wInitXinerama(WScreen * scr)
41 scr->xine_info.primary_head = 0;
42 scr->xine_info.screens = NULL;
43 scr->xine_info.count = 0;
44 #ifdef XINERAMA
45 # ifdef SOLARIS_XINERAMA
46 if (XineramaGetState(dpy, scr->screen)) {
47 WXineramaInfo *info = &scr->xine_info;
48 XRectangle head[MAXFRAMEBUFFERS];
49 unsigned char hints[MAXFRAMEBUFFERS];
50 int i;
52 if (XineramaGetInfo(dpy, scr->screen, head, hints, &info->count)) {
54 info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
56 for (i = 0; i < info->count; i++) {
57 info->screens[i].pos.x = head[i].x;
58 info->screens[i].pos.y = head[i].y;
59 info->screens[i].size.width = head[i].width;
60 info->screens[i].size.height = head[i].height;
64 # else /* !SOLARIS_XINERAMA */
65 if (XineramaIsActive(dpy)) {
66 XineramaScreenInfo *xine_screens;
67 WXineramaInfo *info = &scr->xine_info;
68 int i;
70 xine_screens = XineramaQueryScreens(dpy, &info->count);
72 info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
74 for (i = 0; i < info->count; i++) {
75 info->screens[i].pos.x = xine_screens[i].x_org;
76 info->screens[i].pos.y = xine_screens[i].y_org;
77 info->screens[i].size.width = xine_screens[i].width;
78 info->screens[i].size.height = xine_screens[i].height;
80 XFree(xine_screens);
82 # endif /* !SOLARIS_XINERAMA */
83 #endif /* XINERAMA */
86 int wGetRectPlacementInfo(WScreen * scr, WMRect rect, int *flags)
88 int best;
89 unsigned long area, totalArea;
90 int i;
91 int rx = rect.pos.x;
92 int ry = rect.pos.y;
93 int rw = rect.size.width;
94 int rh = rect.size.height;
96 wassertrv(flags != NULL, 0);
98 best = -1;
99 area = 0;
100 totalArea = 0;
102 *flags = XFLAG_NONE;
104 if (scr->xine_info.count <= 1) {
105 unsigned long a;
107 a = calcIntersectionArea(rx, ry, rw, rh, 0, 0, scr->scr_width, scr->scr_height);
109 if (a == 0) {
110 *flags |= XFLAG_DEAD;
111 } else if (a != rw * rh) {
112 *flags |= XFLAG_PARTIAL;
115 return scr->xine_info.primary_head;
118 for (i = 0; i < wXineramaHeads(scr); i++) {
119 unsigned long a;
121 a = calcIntersectionArea(rx, ry, rw, rh,
122 scr->xine_info.screens[i].pos.x,
123 scr->xine_info.screens[i].pos.y,
124 scr->xine_info.screens[i].size.width,
125 scr->xine_info.screens[i].size.height);
127 totalArea += a;
128 if (a > area) {
129 if (best != -1)
130 *flags |= XFLAG_MULTIPLE;
131 area = a;
132 best = i;
136 if (best == -1) {
137 *flags |= XFLAG_DEAD;
138 best = wGetHeadForPointerLocation(scr);
139 } else if (totalArea != rw * rh)
140 *flags |= XFLAG_PARTIAL;
142 return best;
145 /* get the head that covers most of the rectangle */
146 int wGetHeadForRect(WScreen * scr, WMRect rect)
148 int best;
149 unsigned long area;
150 int i;
151 int rx = rect.pos.x;
152 int ry = rect.pos.y;
153 int rw = rect.size.width;
154 int rh = rect.size.height;
156 if (!scr->xine_info.count)
157 return scr->xine_info.primary_head;
159 best = -1;
160 area = 0;
162 for (i = 0; i < wXineramaHeads(scr); i++) {
163 unsigned long a;
165 a = calcIntersectionArea(rx, ry, rw, rh,
166 scr->xine_info.screens[i].pos.x,
167 scr->xine_info.screens[i].pos.y,
168 scr->xine_info.screens[i].size.width,
169 scr->xine_info.screens[i].size.height);
171 if (a > area) {
172 area = a;
173 best = i;
178 * in case rect is in dead space, return valid head
180 if (best == -1)
181 best = wGetHeadForPointerLocation(scr);
183 return best;
186 Bool wWindowTouchesHead(WWindow * wwin, int head)
188 WScreen *scr;
189 WMRect rect;
190 int a;
192 if (!wwin || !wwin->frame)
193 return False;
195 scr = wwin->screen_ptr;
196 rect = wGetRectForHead(scr, head);
197 a = calcIntersectionArea(wwin->frame_x, wwin->frame_y,
198 wwin->frame->core->width,
199 wwin->frame->core->height,
200 rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
202 return (a != 0);
205 int wGetHeadForWindow(WWindow * wwin)
207 WMRect rect;
209 if (wwin == NULL || wwin->frame == NULL)
210 return 0;
212 rect.pos.x = wwin->frame_x;
213 rect.pos.y = wwin->frame_y;
214 rect.size.width = wwin->frame->core->width;
215 rect.size.height = wwin->frame->core->height;
217 return wGetHeadForRect(wwin->screen_ptr, rect);
220 int wGetHeadForPoint(WScreen * scr, WMPoint point)
222 int i;
224 for (i = 0; i < scr->xine_info.count; i++) {
225 WMRect *rect = &scr->xine_info.screens[i];
227 if ((unsigned)(point.x - rect->pos.x) < rect->size.width &&
228 (unsigned)(point.y - rect->pos.y) < rect->size.height)
229 return i;
231 return scr->xine_info.primary_head;
234 int wGetHeadForPointerLocation(WScreen * scr)
236 WMPoint point;
237 Window bla;
238 int ble;
239 unsigned int blo;
241 if (!scr->xine_info.count)
242 return scr->xine_info.primary_head;
244 if (!XQueryPointer(dpy, scr->root_win, &bla, &bla, &point.x, &point.y, &ble, &ble, &blo))
245 return scr->xine_info.primary_head;
247 return wGetHeadForPoint(scr, point);
250 /* get the dimensions of the head */
251 WMRect wGetRectForHead(WScreen * scr, int head)
253 WMRect rect;
255 if (head < scr->xine_info.count) {
256 rect.pos.x = scr->xine_info.screens[head].pos.x;
257 rect.pos.y = scr->xine_info.screens[head].pos.y;
258 rect.size.width = scr->xine_info.screens[head].size.width;
259 rect.size.height = scr->xine_info.screens[head].size.height;
260 } else {
261 rect.pos.x = 0;
262 rect.pos.y = 0;
263 rect.size.width = scr->scr_width;
264 rect.size.height = scr->scr_height;
267 return rect;
270 WArea wGetUsableAreaForHead(WScreen * scr, int head, WArea * totalAreaPtr, Bool noicons)
272 WArea totalArea, usableArea;
273 WMRect rect = wGetRectForHead(scr, head);
275 totalArea.x1 = rect.pos.x;
276 totalArea.y1 = rect.pos.y;
277 totalArea.x2 = totalArea.x1 + rect.size.width;
278 totalArea.y2 = totalArea.y1 + rect.size.height;
280 if (totalAreaPtr != NULL)
281 *totalAreaPtr = totalArea;
283 if (head < wXineramaHeads(scr)) {
284 usableArea = noicons ? scr->totalUsableArea[head] : scr->usableArea[head];
285 } else
286 usableArea = totalArea;
288 return usableArea;
291 WMPoint wGetPointToCenterRectInHead(WScreen * scr, int head, int width, int height)
293 WMPoint p;
294 WMRect rect = wGetRectForHead(scr, head);
296 p.x = rect.pos.x + (rect.size.width - width) / 2;
297 p.y = rect.pos.y + (rect.size.height - height) / 2;
299 return p;