1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-23 22:52:34 +01:00
Files
wmaker/src/xinerama.c
Amadeusz Sławiński 0faff93cf7 move dock/icons size adjustments, to fix window placement
Functions placing windows (PlaceWindow - src/placement.c, wMaximizeWindow -
src/actions.c) need to calculate area differently than ones placing icons
(PlaceIcon - src/placement.c, wArrangeIcons - src/actions.c).
So this patch puts adjustment code in wGetUsableAreaForHead which is
used by all those functions but called with different 'bool noicons'
argument depending on if it's called in window or icon placement
function.

Reported-by: Carlos R. Mafra <crmafra@gmail.com>
Signed-off-by: Amadeusz Sławiński <amade@asmblr.net>
2013-12-30 18:11:07 +00:00

343 lines
8.2 KiB
C

/*
* Window Maker window manager
*
* Copyright (c) 1997-2003 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "wconfig.h"
#include "xinerama.h"
#include "screen.h"
#include "window.h"
#include "framewin.h"
#include "placement.h"
#include "dock.h"
#ifdef USE_XINERAMA
# ifdef SOLARIS_XINERAMA /* sucks */
# include <X11/extensions/xinerama.h>
# else
# include <X11/extensions/Xinerama.h>
# endif
#endif
void wInitXinerama(WScreen * scr)
{
scr->xine_info.primary_head = 0;
scr->xine_info.screens = NULL;
scr->xine_info.count = 0;
#ifdef USE_XINERAMA
# ifdef SOLARIS_XINERAMA
if (XineramaGetState(dpy, scr->screen)) {
WXineramaInfo *info = &scr->xine_info;
XRectangle head[MAXFRAMEBUFFERS];
unsigned char hints[MAXFRAMEBUFFERS];
int i;
if (XineramaGetInfo(dpy, scr->screen, head, hints, &info->count)) {
info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
for (i = 0; i < info->count; i++) {
info->screens[i].pos.x = head[i].x;
info->screens[i].pos.y = head[i].y;
info->screens[i].size.width = head[i].width;
info->screens[i].size.height = head[i].height;
}
}
}
# else /* !SOLARIS_XINERAMA */
if (XineramaIsActive(dpy)) {
XineramaScreenInfo *xine_screens;
WXineramaInfo *info = &scr->xine_info;
int i;
xine_screens = XineramaQueryScreens(dpy, &info->count);
info->screens = wmalloc(sizeof(WMRect) * (info->count + 1));
for (i = 0; i < info->count; i++) {
info->screens[i].pos.x = xine_screens[i].x_org;
info->screens[i].pos.y = xine_screens[i].y_org;
info->screens[i].size.width = xine_screens[i].width;
info->screens[i].size.height = xine_screens[i].height;
}
XFree(xine_screens);
}
# endif /* !SOLARIS_XINERAMA */
#endif /* USE_XINERAMA */
}
int wGetRectPlacementInfo(WScreen * scr, WMRect rect, int *flags)
{
int best;
unsigned long area, totalArea;
int i;
int rx = rect.pos.x;
int ry = rect.pos.y;
int rw = rect.size.width;
int rh = rect.size.height;
wassertrv(flags != NULL, 0);
best = -1;
area = 0;
totalArea = 0;
*flags = XFLAG_NONE;
if (scr->xine_info.count <= 1) {
unsigned long a;
a = calcIntersectionArea(rx, ry, rw, rh, 0, 0, scr->scr_width, scr->scr_height);
if (a == 0) {
*flags |= XFLAG_DEAD;
} else if (a != rw * rh) {
*flags |= XFLAG_PARTIAL;
}
return scr->xine_info.primary_head;
}
for (i = 0; i < wXineramaHeads(scr); i++) {
unsigned long a;
a = calcIntersectionArea(rx, ry, rw, rh,
scr->xine_info.screens[i].pos.x,
scr->xine_info.screens[i].pos.y,
scr->xine_info.screens[i].size.width,
scr->xine_info.screens[i].size.height);
totalArea += a;
if (a > area) {
if (best != -1)
*flags |= XFLAG_MULTIPLE;
area = a;
best = i;
}
}
if (best == -1) {
*flags |= XFLAG_DEAD;
best = wGetHeadForPointerLocation(scr);
} else if (totalArea != rw * rh)
*flags |= XFLAG_PARTIAL;
return best;
}
/* get the head that covers most of the rectangle */
int wGetHeadForRect(WScreen * scr, WMRect rect)
{
int best;
unsigned long area;
int i;
int rx = rect.pos.x;
int ry = rect.pos.y;
int rw = rect.size.width;
int rh = rect.size.height;
if (!scr->xine_info.count)
return scr->xine_info.primary_head;
best = -1;
area = 0;
for (i = 0; i < wXineramaHeads(scr); i++) {
unsigned long a;
a = calcIntersectionArea(rx, ry, rw, rh,
scr->xine_info.screens[i].pos.x,
scr->xine_info.screens[i].pos.y,
scr->xine_info.screens[i].size.width,
scr->xine_info.screens[i].size.height);
if (a > area) {
area = a;
best = i;
}
}
/*
* in case rect is in dead space, return valid head
*/
if (best == -1)
best = wGetHeadForPointerLocation(scr);
return best;
}
Bool wWindowTouchesHead(WWindow * wwin, int head)
{
WScreen *scr;
WMRect rect;
int a;
if (!wwin || !wwin->frame)
return False;
scr = wwin->screen_ptr;
rect = wGetRectForHead(scr, head);
a = calcIntersectionArea(wwin->frame_x, wwin->frame_y,
wwin->frame->core->width,
wwin->frame->core->height,
rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
return (a != 0);
}
Bool wAppIconTouchesHead(WAppIcon * aicon, int head)
{
WScreen *scr;
WMRect rect;
int a;
if (!aicon || !aicon->icon)
return False;
scr = aicon->icon->core->screen_ptr;
rect = wGetRectForHead(scr, head);
a = calcIntersectionArea(aicon->x_pos, aicon->y_pos,
aicon->icon->core->width,
aicon->icon->core->height,
rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
return (a != 0);
}
int wGetHeadForWindow(WWindow * wwin)
{
WMRect rect;
if (wwin == NULL || wwin->frame == NULL)
return 0;
rect.pos.x = wwin->frame_x;
rect.pos.y = wwin->frame_y;
rect.size.width = wwin->frame->core->width;
rect.size.height = wwin->frame->core->height;
return wGetHeadForRect(wwin->screen_ptr, rect);
}
int wGetHeadForPoint(WScreen * scr, WMPoint point)
{
int i;
for (i = 0; i < scr->xine_info.count; i++) {
WMRect *rect = &scr->xine_info.screens[i];
if ((unsigned)(point.x - rect->pos.x) < rect->size.width &&
(unsigned)(point.y - rect->pos.y) < rect->size.height)
return i;
}
return scr->xine_info.primary_head;
}
int wGetHeadForPointerLocation(WScreen * scr)
{
WMPoint point;
Window bla;
int ble;
unsigned int blo;
if (!scr->xine_info.count)
return scr->xine_info.primary_head;
if (!XQueryPointer(dpy, scr->root_win, &bla, &bla, &point.x, &point.y, &ble, &ble, &blo))
return scr->xine_info.primary_head;
return wGetHeadForPoint(scr, point);
}
/* get the dimensions of the head */
WMRect wGetRectForHead(WScreen * scr, int head)
{
WMRect rect;
if (head < scr->xine_info.count) {
rect.pos.x = scr->xine_info.screens[head].pos.x;
rect.pos.y = scr->xine_info.screens[head].pos.y;
rect.size.width = scr->xine_info.screens[head].size.width;
rect.size.height = scr->xine_info.screens[head].size.height;
} else {
rect.pos.x = 0;
rect.pos.y = 0;
rect.size.width = scr->scr_width;
rect.size.height = scr->scr_height;
}
return rect;
}
WArea wGetUsableAreaForHead(WScreen * scr, int head, WArea * totalAreaPtr, Bool noicons)
{
WArea totalArea, usableArea;
WMRect rect = wGetRectForHead(scr, head);
totalArea.x1 = rect.pos.x;
totalArea.y1 = rect.pos.y;
totalArea.x2 = totalArea.x1 + rect.size.width;
totalArea.y2 = totalArea.y1 + rect.size.height;
if (totalAreaPtr != NULL)
*totalAreaPtr = totalArea;
if (head < wXineramaHeads(scr)) {
usableArea = noicons ? scr->totalUsableArea[head] : scr->usableArea[head];
} else
usableArea = totalArea;
if (noicons) {
/* check if user wants dock covered */
if (scr->dock && (!scr->dock->lowered || wPreferences.no_window_over_dock)) {
int offset = wPreferences.icon_size + DOCK_EXTRA_SPACE;
if (scr->dock->on_right_side)
usableArea.x2 -= offset;
else
usableArea.x1 += offset;
}
/* check if icons are on the same side as dock, and adjust if not done already */
if (scr->dock && wPreferences.no_window_over_icons && !wPreferences.no_window_over_dock && (wPreferences.icon_yard & IY_VERT)) {
int offset = wPreferences.icon_size + DOCK_EXTRA_SPACE;
if (scr->dock->on_right_side && (wPreferences.icon_yard & IY_RIGHT))
usableArea.x2 -= offset;
/* can't use IY_LEFT in if, it's 0 ... */
if (!scr->dock->on_right_side && !(wPreferences.icon_yard & IY_RIGHT))
usableArea.x1 += offset;
}
}
return usableArea;
}
WMPoint wGetPointToCenterRectInHead(WScreen * scr, int head, int width, int height)
{
WMPoint p;
WMRect rect = wGetRectForHead(scr, head);
p.x = rect.pos.x + (rect.size.width - width) / 2;
p.y = rect.pos.y + (rect.size.height - height) / 2;
return p;
}