AppIcon helper functions.
[wmaker-crm.git] / src / xinerama.c
blob4bd9ca44e2a53620a10cf53e1422ad8d83e62cad
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 along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "wconfig.h"
23 #include "xinerama.h"
25 #include "screen.h"
26 #include "window.h"
27 #include "framewin.h"
28 #include "funcs.h"
30 #ifdef XINERAMA
31 # ifdef SOLARIS_XINERAMA /* sucks */
32 # include <X11/extensions/xinerama.h>
33 # else
34 # include <X11/extensions/Xinerama.h>
35 # endif
36 #endif
38 void wInitXinerama(WScreen * scr)
40 scr->xine_info.primary_head = 0;
41 scr->xine_info.screens = NULL;
42 scr->xine_info.count = 0;
43 #ifdef XINERAMA
44 # ifdef SOLARIS_XINERAMA
45 if (XineramaGetState(dpy, scr->screen)) {
46 WXineramaInfo *info = &scr->xine_info;
47 XRectangle head[MAXFRAMEBUFFERS];
48 unsigned char hints[MAXFRAMEBUFFERS];
49 int i;
51 if (XineramaGetInfo(dpy, scr->screen, head, hints, &info->count)) {
53 info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
55 for (i = 0; i < info->count; i++) {
56 info->screens[i].pos.x = head[i].x;
57 info->screens[i].pos.y = head[i].y;
58 info->screens[i].size.width = head[i].width;
59 info->screens[i].size.height = head[i].height;
63 # else /* !SOLARIS_XINERAMA */
64 if (XineramaIsActive(dpy)) {
65 XineramaScreenInfo *xine_screens;
66 WXineramaInfo *info = &scr->xine_info;
67 int i;
69 xine_screens = XineramaQueryScreens(dpy, &info->count);
71 info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
73 for (i = 0; i < info->count; i++) {
74 info->screens[i].pos.x = xine_screens[i].x_org;
75 info->screens[i].pos.y = xine_screens[i].y_org;
76 info->screens[i].size.width = xine_screens[i].width;
77 info->screens[i].size.height = xine_screens[i].height;
79 XFree(xine_screens);
81 # endif /* !SOLARIS_XINERAMA */
82 #endif /* XINERAMA */
85 int wGetRectPlacementInfo(WScreen * scr, WMRect rect, int *flags)
87 int best;
88 unsigned long area, totalArea;
89 int i;
90 int rx = rect.pos.x;
91 int ry = rect.pos.y;
92 int rw = rect.size.width;
93 int rh = rect.size.height;
95 wassertrv(flags != NULL, 0);
97 best = -1;
98 area = 0;
99 totalArea = 0;
101 *flags = XFLAG_NONE;
103 if (scr->xine_info.count <= 1) {
104 unsigned long a;
106 a = calcIntersectionArea(rx, ry, rw, rh, 0, 0, scr->scr_width, scr->scr_height);
108 if (a == 0) {
109 *flags |= XFLAG_DEAD;
110 } else if (a != rw * rh) {
111 *flags |= XFLAG_PARTIAL;
114 return scr->xine_info.primary_head;
117 for (i = 0; i < wXineramaHeads(scr); i++) {
118 unsigned long a;
120 a = calcIntersectionArea(rx, ry, rw, rh,
121 scr->xine_info.screens[i].pos.x,
122 scr->xine_info.screens[i].pos.y,
123 scr->xine_info.screens[i].size.width,
124 scr->xine_info.screens[i].size.height);
126 totalArea += a;
127 if (a > area) {
128 if (best != -1)
129 *flags |= XFLAG_MULTIPLE;
130 area = a;
131 best = i;
135 if (best == -1) {
136 *flags |= XFLAG_DEAD;
137 best = wGetHeadForPointerLocation(scr);
138 } else if (totalArea != rw * rh)
139 *flags |= XFLAG_PARTIAL;
141 return best;
144 /* get the head that covers most of the rectangle */
145 int wGetHeadForRect(WScreen * scr, WMRect rect)
147 int best;
148 unsigned long area;
149 int i;
150 int rx = rect.pos.x;
151 int ry = rect.pos.y;
152 int rw = rect.size.width;
153 int rh = rect.size.height;
155 if (!scr->xine_info.count)
156 return scr->xine_info.primary_head;
158 best = -1;
159 area = 0;
161 for (i = 0; i < wXineramaHeads(scr); i++) {
162 unsigned long a;
164 a = calcIntersectionArea(rx, ry, rw, rh,
165 scr->xine_info.screens[i].pos.x,
166 scr->xine_info.screens[i].pos.y,
167 scr->xine_info.screens[i].size.width,
168 scr->xine_info.screens[i].size.height);
170 if (a > area) {
171 area = a;
172 best = i;
177 * in case rect is in dead space, return valid head
179 if (best == -1)
180 best = wGetHeadForPointerLocation(scr);
182 return best;
185 Bool wWindowTouchesHead(WWindow * wwin, int head)
187 WScreen *scr;
188 WMRect rect;
189 int a;
191 if (!wwin || !wwin->frame)
192 return False;
194 scr = wwin->screen_ptr;
195 rect = wGetRectForHead(scr, head);
196 a = calcIntersectionArea(wwin->frame_x, wwin->frame_y,
197 wwin->frame->core->width,
198 wwin->frame->core->height,
199 rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
201 return (a != 0);
204 Bool wAppIconTouchesHead(WAppIcon * aicon, int head)
206 WScreen *scr;
207 WMRect rect;
208 int a;
210 if (!aicon || !aicon->icon)
211 return False;
213 scr = aicon->icon->core->screen_ptr;
214 rect = wGetRectForHead(scr, head);
215 a = calcIntersectionArea(aicon->x_pos, aicon->y_pos,
216 aicon->icon->core->width,
217 aicon->icon->core->height,
218 rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
220 return (a != 0);
223 int wGetHeadForWindow(WWindow * wwin)
225 WMRect rect;
227 if (wwin == NULL || wwin->frame == NULL)
228 return 0;
230 rect.pos.x = wwin->frame_x;
231 rect.pos.y = wwin->frame_y;
232 rect.size.width = wwin->frame->core->width;
233 rect.size.height = wwin->frame->core->height;
235 return wGetHeadForRect(wwin->screen_ptr, rect);
238 int wGetHeadForPoint(WScreen * scr, WMPoint point)
240 int i;
242 for (i = 0; i < scr->xine_info.count; i++) {
243 WMRect *rect = &scr->xine_info.screens[i];
245 if ((unsigned)(point.x - rect->pos.x) < rect->size.width &&
246 (unsigned)(point.y - rect->pos.y) < rect->size.height)
247 return i;
249 return scr->xine_info.primary_head;
252 int wGetHeadForPointerLocation(WScreen * scr)
254 WMPoint point;
255 Window bla;
256 int ble;
257 unsigned int blo;
259 if (!scr->xine_info.count)
260 return scr->xine_info.primary_head;
262 if (!XQueryPointer(dpy, scr->root_win, &bla, &bla, &point.x, &point.y, &ble, &ble, &blo))
263 return scr->xine_info.primary_head;
265 return wGetHeadForPoint(scr, point);
268 /* get the dimensions of the head */
269 WMRect wGetRectForHead(WScreen * scr, int head)
271 WMRect rect;
273 if (head < scr->xine_info.count) {
274 rect.pos.x = scr->xine_info.screens[head].pos.x;
275 rect.pos.y = scr->xine_info.screens[head].pos.y;
276 rect.size.width = scr->xine_info.screens[head].size.width;
277 rect.size.height = scr->xine_info.screens[head].size.height;
278 } else {
279 rect.pos.x = 0;
280 rect.pos.y = 0;
281 rect.size.width = scr->scr_width;
282 rect.size.height = scr->scr_height;
285 return rect;
288 WArea wGetUsableAreaForHead(WScreen * scr, int head, WArea * totalAreaPtr, Bool noicons)
290 WArea totalArea, usableArea;
291 WMRect rect = wGetRectForHead(scr, head);
293 totalArea.x1 = rect.pos.x;
294 totalArea.y1 = rect.pos.y;
295 totalArea.x2 = totalArea.x1 + rect.size.width;
296 totalArea.y2 = totalArea.y1 + rect.size.height;
298 if (totalAreaPtr != NULL)
299 *totalAreaPtr = totalArea;
301 if (head < wXineramaHeads(scr)) {
302 usableArea = noicons ? scr->totalUsableArea[head] : scr->usableArea[head];
303 } else
304 usableArea = totalArea;
306 return usableArea;
309 WMPoint wGetPointToCenterRectInHead(WScreen * scr, int head, int width, int height)
311 WMPoint p;
312 WMRect rect = wGetRectForHead(scr, head);
314 p.x = rect.pos.x + (rect.size.width - width) / 2;
315 p.y = rect.pos.y + (rect.size.height - height) / 2;
317 return p;