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,
35 # ifdef SOLARIS_XINERAMA /* sucks */
36 # include <X11/extensions/xinerama.h>
38 # include <X11/extensions/Xinerama.h>
42 extern WPreferences wPreferences
;
45 wInitXinerama(WScreen
*scr
)
47 scr
->xine_info
.primary_head
= 0;
48 scr
->xine_info
.screens
= NULL
;
49 scr
->xine_info
.count
= 0;
51 # ifdef SOLARIS_XINERAMA
52 if (XineramaGetState(dpy
, scr
->screen
)) {
53 WXineramaInfo
*info
= &scr
->xine_info
;
54 XRectangle head
[MAXFRAMEBUFFERS
];
55 unsigned char hints
[MAXFRAMEBUFFERS
];
58 if (XineramaGetInfo(dpy
, scr
->screen
, head
, hints
, &info
->count
)) {
60 info
->screens
= wmalloc(sizeof(WMRect
)*(info
->count
+1));
62 for (i
=0; i
<info
->count
; i
++) {
63 info
->screens
[i
].pos
.x
= head
[i
].x
;
64 info
->screens
[i
].pos
.y
= head
[i
].y
;
65 info
->screens
[i
].size
.width
= head
[i
].width
;
66 info
->screens
[i
].size
.height
= head
[i
].height
;
70 # else /* !SOLARIS_XINERAMA */
71 if (XineramaIsActive(dpy
)) {
72 XineramaScreenInfo
*xine_screens
;
73 WXineramaInfo
*info
= &scr
->xine_info
;
76 xine_screens
= XineramaQueryScreens(dpy
, &info
->count
);
78 info
->screens
= wmalloc(sizeof(WMRect
)*(info
->count
+1));
80 for (i
=0; i
<info
->count
; i
++) {
81 info
->screens
[i
].pos
.x
= xine_screens
[i
].x_org
;
82 info
->screens
[i
].pos
.y
= xine_screens
[i
].y_org
;
83 info
->screens
[i
].size
.width
= xine_screens
[i
].width
;
84 info
->screens
[i
].size
.height
= xine_screens
[i
].height
;
88 # endif /* !SOLARIS_XINERAMA */
94 wGetRectPlacementInfo(WScreen
*scr
, WMRect rect
, int *flags
)
97 unsigned long area
, totalArea
;
101 int rw
= rect
.size
.width
;
102 int rh
= rect
.size
.height
;
104 wassertrv(flags
!=NULL
, 0);
112 if (scr
->xine_info
.count
<= 1) {
115 a
= calcIntersectionArea(rx
, ry
, rw
, rh
,
116 0, 0, scr
->scr_width
, scr
->scr_height
);
119 *flags
|= XFLAG_DEAD
;
120 } else if (a
!= rw
*rh
) {
121 *flags
|= XFLAG_PARTIAL
;
124 return scr
->xine_info
.primary_head
;
127 for (i
= 0; i
< wXineramaHeads(scr
); i
++) {
130 a
= calcIntersectionArea(rx
, ry
, rw
, rh
,
131 scr
->xine_info
.screens
[i
].pos
.x
,
132 scr
->xine_info
.screens
[i
].pos
.y
,
133 scr
->xine_info
.screens
[i
].size
.width
,
134 scr
->xine_info
.screens
[i
].size
.height
);
139 *flags
|= XFLAG_MULTIPLE
;
146 *flags
|= XFLAG_DEAD
;
147 best
= wGetHeadForPointerLocation(scr
);
148 } else if (totalArea
!= rw
*rh
)
149 *flags
|= XFLAG_PARTIAL
;
156 /* get the head that covers most of the rectangle */
158 wGetHeadForRect(WScreen
*scr
, WMRect rect
)
165 int rw
= rect
.size
.width
;
166 int rh
= rect
.size
.height
;
168 if (!scr
->xine_info
.count
)
169 return scr
->xine_info
.primary_head
;
174 for (i
= 0; i
< wXineramaHeads(scr
); i
++) {
177 a
= calcIntersectionArea(rx
, ry
, rw
, rh
,
178 scr
->xine_info
.screens
[i
].pos
.x
,
179 scr
->xine_info
.screens
[i
].pos
.y
,
180 scr
->xine_info
.screens
[i
].size
.width
,
181 scr
->xine_info
.screens
[i
].size
.height
);
190 * in case rect is in dead space, return valid head
193 best
= wGetHeadForPointerLocation(scr
);
200 wWindowTouchesHead(WWindow
*wwin
, int head
)
206 if (!wwin
|| !wwin
->frame
)
209 scr
= wwin
->screen_ptr
;
210 rect
= wGetRectForHead(scr
, head
);
211 a
= calcIntersectionArea(wwin
->frame_x
, wwin
->frame_y
,
212 wwin
->frame
->core
->width
,
213 wwin
->frame
->core
->height
,
214 rect
.pos
.x
, rect
.pos
.y
,
215 rect
.size
.width
, rect
.size
.height
);
222 wGetHeadForWindow(WWindow
*wwin
)
226 if (wwin
== NULL
|| wwin
->frame
== NULL
)
229 rect
.pos
.x
= wwin
->frame_x
;
230 rect
.pos
.y
= wwin
->frame_y
;
231 rect
.size
.width
= wwin
->frame
->core
->width
;
232 rect
.size
.height
= wwin
->frame
->core
->height
;
234 return wGetHeadForRect(wwin
->screen_ptr
, rect
);
240 wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags)
251 for (i = 0; i < scr->xine_info.count; i++) {
255 xx = scr->xine_info.screens[i].pos.x + scr->xine_info.screens[i].size.width;
256 yy = scr->xine_info.screens[i].pos.y + scr->xine_info.screens[i].size.height;
257 if (point.x >= scr->xine_info.screens[i].pos.x &&
258 point.y >= scr->xine_info.screens[i].pos.y &&
259 point.x < xx && point.y < yy) {
263 XineramaScreenInfo *xsi = &scr->xine_info.screens[i];
265 if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
266 (unsigned)(point.y - xsi->y_org) < xsi->height)
271 *flags |= XFLAG_DEAD;
273 return scr->xine_primary_head;
280 wGetHeadForPoint(WScreen
*scr
, WMPoint point
)
284 for (i
= 0; i
< scr
->xine_info
.count
; i
++) {
285 WMRect
*rect
= &scr
->xine_info
.screens
[i
];
287 if ((unsigned)(point
.x
- rect
->pos
.x
) < rect
->size
.width
&&
288 (unsigned)(point
.y
- rect
->pos
.y
) < rect
->size
.height
)
291 return scr
->xine_info
.primary_head
;
296 wGetHeadForPointerLocation(WScreen
*scr
)
303 if (!scr
->xine_info
.count
)
304 return scr
->xine_info
.primary_head
;
306 if (!XQueryPointer(dpy
, scr
->root_win
, &bla
, &bla
,
310 return scr
->xine_info
.primary_head
;
312 return wGetHeadForPoint(scr
, point
);
315 /* get the dimensions of the head */
317 wGetRectForHead(WScreen
*scr
, int head
)
321 if (head
< scr
->xine_info
.count
) {
322 rect
.pos
.x
= scr
->xine_info
.screens
[head
].pos
.x
;
323 rect
.pos
.y
= scr
->xine_info
.screens
[head
].pos
.y
;
324 rect
.size
.width
= scr
->xine_info
.screens
[head
].size
.width
;
325 rect
.size
.height
= scr
->xine_info
.screens
[head
].size
.height
;
329 rect
.size
.width
= scr
->scr_width
;
330 rect
.size
.height
= scr
->scr_height
;
338 wGetUsableAreaForHead(WScreen
*scr
, int head
, WArea
*totalAreaPtr
, Bool noicons
)
340 WArea totalArea
, usableArea
;
341 WMRect rect
= wGetRectForHead(scr
, head
);
343 totalArea
.x1
= rect
.pos
.x
;
344 totalArea
.y1
= rect
.pos
.y
;
345 totalArea
.x2
= totalArea
.x1
+ rect
.size
.width
;
346 totalArea
.y2
= totalArea
.y1
+ rect
.size
.height
;
348 if (totalAreaPtr
!= NULL
) *totalAreaPtr
= totalArea
;
350 if (head
< wXineramaHeads(scr
)) {
351 usableArea
= noicons
? scr
->totalUsableArea
[head
] : scr
->usableArea
[head
];
353 usableArea
= totalArea
;
360 wGetPointToCenterRectInHead(WScreen
*scr
, int head
, int width
, int height
)
363 WMRect rect
= wGetRectForHead(scr
, head
);
365 p
.x
= rect
.pos
.x
+ (rect
.size
.width
- width
)/2;
366 p
.y
= rect
.pos
.y
+ (rect
.size
.height
- height
)/2;