wrlib: return NULL if XImage could not be taken, for consistency
[wmaker-crm.git] / src / xinerama.c
blobe1e47ee5ab21653665caaea4ee21990b32cdbbfd
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 "placement.h"
29 #include "dock.h"
31 #ifdef USE_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 USE_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 /* USE_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 Bool wAppIconTouchesHead(WAppIcon * aicon, int head)
207 WScreen *scr;
208 WMRect rect;
209 int a;
211 if (!aicon || !aicon->icon)
212 return False;
214 scr = aicon->icon->core->screen_ptr;
215 rect = wGetRectForHead(scr, head);
216 a = calcIntersectionArea(aicon->x_pos, aicon->y_pos,
217 aicon->icon->core->width,
218 aicon->icon->core->height,
219 rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
221 return (a != 0);
224 int wGetHeadForWindow(WWindow * wwin)
226 WMRect rect;
228 if (wwin == NULL || wwin->frame == NULL)
229 return 0;
231 rect.pos.x = wwin->frame_x;
232 rect.pos.y = wwin->frame_y;
233 rect.size.width = wwin->frame->core->width;
234 rect.size.height = wwin->frame->core->height;
236 return wGetHeadForRect(wwin->screen_ptr, rect);
239 int wGetHeadForPoint(WScreen * scr, WMPoint point)
241 int i;
243 for (i = 0; i < scr->xine_info.count; i++) {
244 WMRect *rect = &scr->xine_info.screens[i];
246 if ((unsigned)(point.x - rect->pos.x) < rect->size.width &&
247 (unsigned)(point.y - rect->pos.y) < rect->size.height)
248 return i;
250 return scr->xine_info.primary_head;
253 int wGetHeadForPointerLocation(WScreen * scr)
255 WMPoint point;
256 Window bla;
257 int ble;
258 unsigned int blo;
260 if (!scr->xine_info.count)
261 return scr->xine_info.primary_head;
263 if (!XQueryPointer(dpy, scr->root_win, &bla, &bla, &point.x, &point.y, &ble, &ble, &blo))
264 return scr->xine_info.primary_head;
266 return wGetHeadForPoint(scr, point);
269 /* get the dimensions of the head */
270 WMRect wGetRectForHead(WScreen * scr, int head)
272 WMRect rect;
274 if (head < scr->xine_info.count) {
275 rect.pos.x = scr->xine_info.screens[head].pos.x;
276 rect.pos.y = scr->xine_info.screens[head].pos.y;
277 rect.size.width = scr->xine_info.screens[head].size.width;
278 rect.size.height = scr->xine_info.screens[head].size.height;
279 } else {
280 rect.pos.x = 0;
281 rect.pos.y = 0;
282 rect.size.width = scr->scr_width;
283 rect.size.height = scr->scr_height;
286 return rect;
289 WArea wGetUsableAreaForHead(WScreen * scr, int head, WArea * totalAreaPtr, Bool noicons)
291 WArea totalArea, usableArea;
292 WMRect rect = wGetRectForHead(scr, head);
294 totalArea.x1 = rect.pos.x;
295 totalArea.y1 = rect.pos.y;
296 totalArea.x2 = totalArea.x1 + rect.size.width;
297 totalArea.y2 = totalArea.y1 + rect.size.height;
299 if (totalAreaPtr != NULL)
300 *totalAreaPtr = totalArea;
302 if (head < wXineramaHeads(scr)) {
303 usableArea = noicons ? scr->totalUsableArea[head] : scr->usableArea[head];
304 } else
305 usableArea = totalArea;
307 if (noicons) {
308 /* check if user wants dock covered */
309 if (scr->dock && (!scr->dock->lowered || wPreferences.no_window_over_dock)) {
310 int offset = wPreferences.icon_size + DOCK_EXTRA_SPACE;
312 if (scr->dock->on_right_side)
313 usableArea.x2 -= offset;
314 else
315 usableArea.x1 += offset;
318 /* check if icons are on the same side as dock, and adjust if not done already */
319 if (scr->dock && wPreferences.no_window_over_icons && !wPreferences.no_window_over_dock && (wPreferences.icon_yard & IY_VERT)) {
320 int offset = wPreferences.icon_size + DOCK_EXTRA_SPACE;
322 if (scr->dock->on_right_side && (wPreferences.icon_yard & IY_RIGHT))
323 usableArea.x2 -= offset;
324 /* can't use IY_LEFT in if, it's 0 ... */
325 if (!scr->dock->on_right_side && !(wPreferences.icon_yard & IY_RIGHT))
326 usableArea.x1 += offset;
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;