- Fixed sloppy focus bug (Pawel S. Veselov <pv76716@druid.SFBay.Sun.COM>)
[wmaker-crm.git] / src / xinerama.c
blobc6e6f5c320b0610dd4ec8944ed5b41c476fee011
1 /*
2 * Window Maker window manager
3 *
4 * Copyright (c) 1997-2001 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 #include <X11/extensions/Xinerama.h>
36 #endif
38 void wInitXinerama(WScreen *scr)
40 scr->xine_screens = 0;
41 scr->xine_count = 0;
42 #ifdef XINERAMA
43 scr->xine_screens = XineramaQueryScreens(dpy, &scr->xine_count);
44 #endif
45 scr->xine_primary_head = 0;
49 int wGetRectPlacementInfo(WScreen *scr, WMRect rect, int *flags)
51 int best;
52 unsigned long area, totalArea;
53 int i;
54 int rx = rect.pos.x;
55 int ry = rect.pos.y;
56 int rw = rect.size.width;
57 int rh = rect.size.height;
59 wassertrv(flags!=NULL, 0);
61 best = -1;
62 area = 0;
63 totalArea = 0;
65 *flags = XFLAG_NONE;
67 if (scr->xine_count <= 1) {
68 unsigned long a;
70 a = calcIntersectionArea(rx, ry, rw, rh,
71 0, 0, scr->scr_width, scr->scr_height);
73 if (a == 0) {
74 *flags |= XFLAG_DEAD;
75 } else if (a != rw*rh) {
76 *flags |= XFLAG_PARTIAL;
79 return scr->xine_primary_head;
82 #ifdef XINERAMA
83 for (i = 0; i < scr->xine_count; i++) {
84 unsigned long a;
86 a = calcIntersectionArea(rx, ry, rw, rh,
87 scr->xine_screens[i].x_org,
88 scr->xine_screens[i].y_org,
89 scr->xine_screens[i].width,
90 scr->xine_screens[i].height);
92 totalArea += a;
93 if (a > area) {
94 if ( best != -1)
95 *flags |= XFLAG_MULTIPLE;
96 area = a;
97 best = i;
101 if ( best == -1) {
102 *flags |= XFLAG_DEAD;
103 best = wGetHeadForPointerLocation(scr);
104 } else if ( totalArea != rw*rh)
105 *flags |= XFLAG_PARTIAL;
107 return best;
108 #endif
113 /* get the head that covers most of the rectangle */
114 int wGetHeadForRect(WScreen *scr, WMRect rect)
116 int best;
117 unsigned long area;
118 int i;
119 int rx = rect.pos.x;
120 int ry = rect.pos.y;
121 int rw = rect.size.width;
122 int rh = rect.size.height;
124 if (!scr->xine_count)
125 return scr->xine_primary_head;
127 best = -1;
128 area = 0;
130 #ifdef XINERAMA
131 for (i = 0; i < scr->xine_count; i++) {
132 unsigned long a;
134 a = calcIntersectionArea(rx, ry, rw, rh,
135 scr->xine_screens[i].x_org,
136 scr->xine_screens[i].y_org,
137 scr->xine_screens[i].width,
138 scr->xine_screens[i].height);
140 if (a > area) {
141 area = a;
142 best = i;
147 * in case rect is in dead space, return valid head
149 if (best == -1)
150 best = wGetHeadForPointerLocation(scr);
152 return best;
153 #else /* !XINERAMA */
154 return scr->xine_primary_head;
155 #endif /* !XINERAMA */
159 int wGetHeadForWindow(WWindow *wwin)
161 WMRect rect;
163 rect.pos.x = wwin->frame_x;
164 rect.pos.y = wwin->frame_y;
165 rect.size.width = wwin->frame->core->width;
166 rect.size.height = wwin->frame->core->height;
168 return wGetHeadForRect(wwin->screen_ptr, rect);
173 int wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags)
175 int i;
177 // paranoia
178 if ( flags == NULL) {
179 static int tmp;
180 flags = &tmp;
182 *flags = XFLAG_NONE;
184 for (i = 0; i < scr->xine_count; i++) {
185 #if 0
186 int yy, xx;
188 xx = scr->xine_screens[i].x_org + scr->xine_screens[i].width;
189 yy = scr->xine_screens[i].y_org + scr->xine_screens[i].height;
190 if (point.x >= scr->xine_screens[i].x_org &&
191 point.y >= scr->xine_screens[i].y_org &&
192 point.x < xx && point.y < yy) {
193 return i;
195 #else
196 XineramaScreenInfo *xsi = &scr->xine_screens[i];
198 if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
199 (unsigned)(point.y - xsi->y_org) < xsi->height)
200 return i;
201 #endif
204 *flags |= XFLAG_DEAD;
206 return scr->xine_primary_head;
212 int wGetHeadForPoint(WScreen *scr, WMPoint point)
214 #ifdef XINERAMA
215 int i;
217 for (i = 0; i < scr->xine_count; i++) {
218 XineramaScreenInfo *xsi = &scr->xine_screens[i];
220 if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
221 (unsigned)(point.y - xsi->y_org) < xsi->height)
222 return i;
224 #endif /* XINERAMA */
225 return scr->xine_primary_head;
229 int wGetHeadForPointerLocation(WScreen *scr)
231 WMPoint point;
232 Window bla;
233 int ble;
234 unsigned int blo;
236 if (!scr->xine_count)
237 return scr->xine_primary_head;
239 if (!XQueryPointer(dpy, scr->root_win, &bla, &bla,
240 &point.x, &point.y,
241 &ble, &ble,
242 &blo))
243 return scr->xine_primary_head;
245 return wGetHeadForPoint(scr, point);
248 /* get the dimensions of the head */
249 WMRect
250 wGetRectForHead(WScreen *scr, int head)
252 WMRect rect;
254 #ifdef XINERAMA
255 if (head < scr->xine_count) {
256 rect.pos.x = scr->xine_screens[head].x_org;
257 rect.pos.y = scr->xine_screens[head].y_org;
258 rect.size.width = scr->xine_screens[head].width;
259 rect.size.height = scr->xine_screens[head].height;
260 } else
261 #endif /* XINERAMA */
263 rect.pos.x = 0;
264 rect.pos.y = 0;
265 rect.size.width = scr->scr_width;
266 rect.size.height = scr->scr_height;
269 return rect;
274 WArea wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr)
276 WArea totalArea, usableArea = scr->totalUsableArea;
277 WMRect rect = wGetRectForHead(scr, head);
279 totalArea.x1 = rect.pos.x;
280 totalArea.y1 = rect.pos.y;
281 totalArea.x2 = totalArea.x1 + rect.size.width;
282 totalArea.y2 = totalArea.y1 + rect.size.height;
284 if (totalAreaPtr != NULL) *totalAreaPtr = totalArea;
286 usableArea.x1 = WMAX(totalArea.x1, usableArea.x1);
287 usableArea.y1 = WMAX(totalArea.y1, usableArea.y1);
288 usableArea.x2 = WMIN(totalArea.x2, usableArea.x2);
289 usableArea.y2 = WMIN(totalArea.y2, usableArea.y2);
291 return usableArea;
295 WMPoint wGetPointToCenterRectInHead(WScreen *scr, int head, int width, int height)
297 WMPoint p;
298 WMRect rect = wGetRectForHead(scr, head);
300 p.x = rect.pos.x + (rect.size.width - width)/2;
301 p.y = rect.pos.y + (rect.size.height - height)/2;
303 return p;