1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-31 11:02:35 +01:00

- Fixed sloppy focus bug (Pawel S. Veselov <pv76716@druid.SFBay.Sun.COM>)

- Applied Xinerama patch (after fixes) from (Peter Zijlstra
  <a.p.zijlstra@chello.nl>)
This commit is contained in:
kojima
2002-11-28 22:04:07 +00:00
parent 0fe70d2b4e
commit a10214a502
21 changed files with 909 additions and 403 deletions

View File

@@ -412,7 +412,6 @@ wMaximizeWindow(WWindow *wwin, int directions)
WArea usableArea = wwin->screen_ptr->totalUsableArea;
WArea totalArea;
if (WFLAGP(wwin, no_resizable))
return;
@@ -421,24 +420,28 @@ wMaximizeWindow(WWindow *wwin, int directions)
totalArea.x2 = wwin->screen_ptr->scr_width;
totalArea.y2 = wwin->screen_ptr->scr_height;
#ifdef XINERAMA
if (wwin->screen_ptr->xine_count > 0
&& !(directions & MAX_IGNORE_XINERAMA)) {
WScreen *scr = wwin->screen_ptr;
WMRect rect;
int head;
rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
totalArea.x1 = rect.pos.x;
totalArea.y1 = rect.pos.y;
totalArea.x2 = totalArea.x1 + rect.size.width;
totalArea.y2 = totalArea.y1 + rect.size.height;
/* XXX:
if ( keyboard) {
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;
usableArea.x1 = WMAX(totalArea.x1, usableArea.x1);
usableArea.y1 = WMAX(totalArea.y1, usableArea.y1);
usableArea.x2 = WMIN(totalArea.x2, usableArea.x2);
usableArea.y2 = WMIN(totalArea.y2, usableArea.y2);
head = wGetHeadForRect(scr, rect);
} else
*/
head = wGetHeadForPointerLocation(scr);
rect = wGetRectForHead(scr, head);
usableArea = wGetUsableAreaForHead(scr, head, &totalArea);
}
#endif /* XINERAMA */
if (WFLAGP(wwin, full_maximize)) {
usableArea = totalArea;
@@ -1502,10 +1505,18 @@ wArrangeIcons(WScreen *scr, Bool arrangeAll)
/*
* Find out screen boundaries.
*/
sx1 = 0;
sy1 = 0;
sx2 = scr->scr_width;
sy2 = scr->scr_height;
/*
* Allows each head to have miniwindows
*/
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
sx1 = rect.pos.x;
sy1 = rect.pos.y;
sw = rect.size.width;
sh = rect.size.height;
sx2 = sx1 + sw;
sy2 = sy1 + sh;
if (scr->dock) {
if (scr->dock->on_right_side)
sx2 -= isize + DOCK_EXTRA_SPACE;
@@ -1513,8 +1524,14 @@ wArrangeIcons(WScreen *scr, Bool arrangeAll)
sx1 += isize + DOCK_EXTRA_SPACE;
}
#if 0
sw = isize * (scr->scr_width/isize);
sh = isize * (scr->scr_height/isize);
#else
sw = isize * (sw/isize);
sh = isize * (sh/isize);
#endif
fullW = (sx2-sx1)/isize;
fullW = (sx2-sx1)/isize;
fullH = (sy2-sy1)/isize;

View File

@@ -47,6 +47,7 @@
#include "kwm.h"
#endif
/****** Global Variables ******/
/* contexts */
@@ -179,6 +180,8 @@ wClientConfigure(WWindow *wwin, XConfigureRequestEvent *xcre)
int nx, ny, nwidth, nheight;
int ofs_x, ofs_y;
/* printf( "configure event: %d %d %d %d\n", xcre->x, xcre->y, xcre->width, xcre->height);*/
if (wwin==NULL) {
/*
* configure a window that was not mapped by us

View File

@@ -36,6 +36,7 @@
#include "actions.h"
#include "stacking.h"
#include "funcs.h"
#include "xinerama.h"
/* Globals */
extern WPreferences wPreferences;
@@ -303,9 +304,16 @@ StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next)
}
scr->flags.doing_alt_tab = 0;
if (openedSwitchMenu)
OpenSwitchMenu(scr, scr->scr_width/2, scr->scr_height/2, False);
if (openedSwitchMenu) {
/*
* place window in center of current head
*/
WMPoint center = wGetPointToCenterRectInHead(scr,
wGetHeadForPointerLocation(scr),
0, 0);
OpenSwitchMenu(scr, center.x, center.y, False);
}
if (somethingElse) {
WMHandleEvent(&ev);
}

View File

@@ -69,23 +69,10 @@ extern WPreferences wPreferences;
static WMPoint getCenter(WScreen *scr, int width, int height)
{
WMPoint pt;
#ifdef XINERAMA
WMRect rect;
rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
pt.x = rect.pos.x + (rect.size.width - width)/2;
pt.y = rect.pos.y + (rect.size.height - height)/2;
#else
pt.x = (scr->scr_width - width) / 2;
pt.y = (scr->scr_height - height) / 2;
#endif
return pt;
return wGetPointToCenterRectInHead(scr,
wGetHeadForPointerLocation(scr),
width, height);
}
int
@@ -146,6 +133,7 @@ wExitDialog(WScreen *scr, char *title, char *message,
WMButton *saveSessionBtn;
Window parent;
WWindow *wwin;
WMPoint center;
int result;
panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message,
@@ -165,9 +153,10 @@ wExitDialog(WScreen *scr, char *title, char *message,
XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
center = getCenter(scr, 400, 180);
wwin = wManageInternalWindow(scr, parent, None, NULL,
(scr->scr_width - 400)/2,
(scr->scr_height - 180)/2, 400, 180);
center.x, center.y, 400, 180);
wwin->client_leader = WMWidgetXID(panel->win);
WMMapWidget(panel->win);

View File

@@ -54,7 +54,7 @@
#include "framewin.h"
#include "superfluous.h"
#include "wsound.h"
#include "xinerama.h"
@@ -1712,20 +1712,22 @@ wClipRestoreState(WScreen *scr, WMPropList *clip_state)
if (!WMIsPLString(value))
COMPLAIN("Position");
else {
WMRect rect;
int flags;
if (sscanf(WMGetFromPLString(value), "%i,%i", &icon->x_pos,
&icon->y_pos)!=2)
COMPLAIN("Position");
/* check position sanity */
if (icon->y_pos < 0)
icon->y_pos = 0;
else if (icon->y_pos > scr->scr_height-ICON_SIZE)
icon->y_pos = scr->scr_height-ICON_SIZE;
if (icon->x_pos < 0)
icon->x_pos = 0;
else if (icon->x_pos > scr->scr_width-ICON_SIZE)
icon->x_pos = scr->scr_width-ICON_SIZE;
rect.pos.x = icon->x_pos;
rect.pos.y = icon->y_pos;
rect.size.width = rect.size.height = ICON_SIZE;
wGetRectPlacementInfo(scr, rect, &flags);
if (flags & (XFLAG_DEAD | XFLAG_PARTIAL))
wScreenKeepInside(scr, &icon->x_pos, &icon->y_pos,
ICON_SIZE, ICON_SIZE);
}
}
@@ -1772,15 +1774,23 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type)
if (!WMIsPLString(value))
COMPLAIN("Position");
else {
WMRect rect;
int flags;
if (sscanf(WMGetFromPLString(value), "%i,%i", &dock->x_pos,
&dock->y_pos)!=2)
COMPLAIN("Position");
/* check position sanity */
if (dock->y_pos < 0)
dock->y_pos = 0;
else if (dock->y_pos > scr->scr_height-ICON_SIZE)
dock->y_pos = scr->scr_height - ICON_SIZE;
rect.pos.x = dock->x_pos;
rect.pos.y = dock->y_pos;
rect.size.width = rect.size.height = ICON_SIZE;
wGetRectPlacementInfo(scr, rect, &flags);
if (flags & (XFLAG_DEAD | XFLAG_PARTIAL)) {
int x = dock->x_pos;
wScreenKeepInside(scr, &x, &dock->y_pos, ICON_SIZE, ICON_SIZE);
}
/* This is no more needed. ??? */
if (type == WM_CLIP) {
@@ -2464,6 +2474,7 @@ wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y,
WAppIcon *nicon = NULL;
int max_y_icons, max_x_icons;
/* TODO: XINERAMA, for these */
max_x_icons = scr->scr_width/ICON_SIZE;
max_y_icons = scr->scr_height/ICON_SIZE-1;
@@ -2491,11 +2502,18 @@ wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y,
ex_x = (req_x + offset - dx)/ICON_SIZE;
/* check if the icon is outside the screen boundaries */
if (dx + ex_x*ICON_SIZE < -ICON_SIZE+2 ||
dx + ex_x*ICON_SIZE >= scr->scr_width-1 ||
dy + ex_y*ICON_SIZE < -ICON_SIZE+2 ||
dy + ex_y*ICON_SIZE >= scr->scr_height-1)
return False;
{
WMRect rect;
int flags;
rect.pos.x = dx + ex_x*ICON_SIZE;
rect.pos.y = dy + ex_y*ICON_SIZE;
rect.size.width = rect.size.height = ICON_SIZE;
wGetRectPlacementInfo(scr, rect, &flags);
if (flags & (XFLAG_DEAD | XFLAG_PARTIAL))
return False;
}
if (dock->type == WM_DOCK) {
if (icon->dock != dock && ex_x != 0)
@@ -2623,9 +2641,17 @@ wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y,
}
#define ON_SCREEN(x, y, sx, ex, sy, ey) \
((((x)+ICON_SIZE/2) >= (sx)) && (((y)+ICON_SIZE/2) >= (sy)) && \
(((x) + (ICON_SIZE/2)) <= (ex)) && (((y) + (ICON_SIZE/2)) <= ey))
static int onScreen(WScreen *scr, int x, int y, int sx, int ex, int sy, int ey)
{
WMRect rect = { (x), (y), (ICON_SIZE), (ICON_SIZE) };
int flags;
wGetRectPlacementInfo(scr, rect, &flags);
return !(flags & (XFLAG_DEAD | XFLAG_PARTIAL));
}
#define ON_SCREEN(x, y, sx, ex, sy, ey) onScreen(scr, x, y, sx, ex, sy, ey)
/*
@@ -3662,22 +3688,10 @@ handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event)
break;
}
if (dock->type == WM_CLIP) {
if (ev.xmotion.x_root - ofs_x < 0) {
x = 0;
} else if (ev.xmotion.x_root - ofs_x + ICON_SIZE >
scr->scr_width) {
x = scr->scr_width - ICON_SIZE;
} else {
x = ev.xmotion.x_root - ofs_x;
}
if (ev.xmotion.y_root - ofs_y < 0) {
y = 0;
} else if (ev.xmotion.y_root - ofs_y + ICON_SIZE >
scr->scr_height) {
y = scr->scr_height - ICON_SIZE;
} else {
y = ev.xmotion.y_root - ofs_y;
}
x = ev.xmotion.x_root - ofs_x;
y = ev.xmotion.y_root - ofs_y;
wScreenKeepInside(scr, &x, &y, ICON_SIZE, ICON_SIZE);
moveDock(dock, x, y);
} else {
/* move vertically if pointer is inside the dock*/
@@ -3686,14 +3700,9 @@ handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event)
|| (!dock->on_right_side &&
ev.xmotion.x_root <= dock->x_pos + ICON_SIZE*2)) {
if (ev.xmotion.y_root - ofs_y < 0) {
y = 0;
} else if (ev.xmotion.y_root - ofs_y + ICON_SIZE >
scr->scr_height) {
y = scr->scr_height - ICON_SIZE;
} else {
y = ev.xmotion.y_root - ofs_y;
}
x = ev.xmotion.x_root - ofs_x;
y = ev.xmotion.y_root - ofs_y;
wScreenKeepInside(scr, &x, &y, ICON_SIZE, ICON_SIZE);
moveDock(dock, dock->x_pos, y);
}
/* move horizontally to change sides */

View File

@@ -38,6 +38,7 @@
#include "funcs.h"
#include "defaults.h"
#include "framewin.h"
#include "xinerama.h"
/**** Global variables ****/
@@ -448,20 +449,28 @@ ShowDockAppSettingsPanel(WAppIcon *aicon)
XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
y = aicon->y_pos;
if (y < 0)
y = 0;
else if (y + PHEIGHT > scr->scr_height)
y = scr->scr_height - PHEIGHT - 30;
/*
* make things relative to head
*/
{
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
if (aicon->dock && aicon->dock->type == WM_DOCK) {
if (aicon->dock->on_right_side)
x = scr->scr_width/2;
else
x = scr->scr_width/2 - PWIDTH - 2;
} else {
x = (scr->scr_width - PWIDTH)/2;
y = aicon->y_pos;
if (y < 0)
y = 0;
else if (y + PHEIGHT > rect.pos.y + rect.size.height)
y = rect.pos.y + rect.size.height - PHEIGHT - 30;
if (aicon->dock && aicon->dock->type == WM_DOCK) {
if (aicon->dock->on_right_side)
x = rect.pos.x + rect.size.width/2;
else
x = rect.pos.x + rect.size.width/2 - PWIDTH - 2;
} else {
x = rect.pos.x + (rect.size.width - PWIDTH)/2;
}
}
panel->wwin = wManageInternalWindow(scr, parent, None,
_("Docked Application Settings"),
x, y, PWIDTH, PHEIGHT);

View File

@@ -58,6 +58,7 @@
#include "framewin.h"
#include "properties.h"
#include "balloon.h"
#include "xinerama.h"
#ifdef GNOME_STUFF
# include "gnome.h"
@@ -1140,11 +1141,11 @@ handleEnterNotify(XEvent *event)
}
if (event->xcrossing.window == event->xcrossing.root
&& event->xcrossing.detail == NotifyNormal
&& event->xcrossing.detail != NotifyInferior
&& (event->xcrossing.mode == NotifyNormal ||
event->xcrossing.mode == NotifyUngrab )
&& event->xcrossing.detail == NotifyInferior
&& wPreferences.focus_mode != WKF_CLICK) {
wSetFocusTo(scr, scr->focused_window);
wSetFocusTo(scr, NULL);
}
#ifdef BALLOON_TEXT
@@ -1163,15 +1164,6 @@ handleLeaveNotify(XEvent *event)
if(desc->handle_leavenotify)
(*desc->handle_leavenotify)(desc, event);
}
if (event->xcrossing.window == event->xcrossing.root
&& event->xcrossing.mode == NotifyNormal
&& event->xcrossing.detail != NotifyInferior
&& wPreferences.focus_mode != WKF_CLICK) {
WScreen *scr = wScreenForRootWindow(event->xcrossing.root);
wSetFocusTo(scr, NULL);
}
}
@@ -1403,10 +1395,16 @@ handleKeyPress(XEvent *event)
#ifndef LITE
case WKBD_ROOTMENU:
/*OpenRootMenu(scr, event->xkey.x_root, event->xkey.y_root, True);*/
OpenRootMenu(scr, scr->scr_width/2, scr->scr_height/2, True);
{
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
OpenRootMenu(scr, rect.pos.x + rect.size.width/2, rect.pos.y + rect.size.height/2, True);
}
break;
case WKBD_WINDOWLIST:
OpenSwitchMenu(scr, scr->scr_width/2, scr->scr_height/2, True);
{
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
OpenSwitchMenu(scr, rect.pos.x + rect.size.width/2, rect.pos.y + rect.size.height/2, True);
}
break;
#endif /* !LITE */
case WKBD_WINDOWMENU:
@@ -1719,15 +1717,18 @@ handleKeyPress(XEvent *event)
static void
handleMotionNotify(XEvent *event)
{
WMenu *menu;
WScreen *scr = wScreenForRootWindow(event->xmotion.root);
if (wPreferences.scrollable_menus) {
if (scr->flags.jump_back_pending ||
event->xmotion.x_root <= 1 ||
event->xmotion.x_root >= (scr->scr_width - 2) ||
event->xmotion.y_root <= 1 ||
event->xmotion.y_root >= (scr->scr_height - 2)) {
WMPoint p = { event->xmotion.x_root, event->xmotion.y_root };
WMRect rect = wGetRectForHead(scr, wGetHeadForPoint(scr, p));
if (scr->flags.jump_back_pending ||
p.x <= (rect.pos.x + 1) ||
p.x >= (rect.pos.x + rect.size.width - 2) ||
p.y <= (rect.pos.y + 1) ||
p.y >= (rect.pos.y + rect.size.height - 2)) {
WMenu *menu;
#ifdef DEBUG
L("pointer at screen edge");
#endif

View File

@@ -85,6 +85,9 @@ Pixmap LoadIcon(WScreen *scr, char *path, char *mask, int title_height);
void PlaceIcon(WScreen *scr, int *x_ret, int *y_ret);
int calcIntersectionArea(int x1, int y1, int w1, int h1,
int x2, int y2, int w2, int h2);
void PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
unsigned int width, unsigned int height);

View File

@@ -42,6 +42,7 @@
#include "funcs.h"
#include "stacking.h"
#include "text.h"
#include "xinerama.h"
/****** Global Variables ******/
@@ -869,6 +870,7 @@ makeVisible(WMenu *menu)
{
WScreen *scr = menu->frame->screen_ptr;
int x1, y1, x2, y2, new_x, new_y, move;
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
if (menu->entry_no<0) return;
@@ -882,20 +884,21 @@ makeVisible(WMenu *menu)
new_y = y1;
move = 0;
if (x1 < 0) {
new_x = 0;
move = 1;
} else if (x2 >= scr->scr_width) {
new_x = scr->scr_width - MENUW(menu) - 1;
move = 1;
}
if (y1 < 0) {
new_y = 0;
move = 1;
} else if (y2 >= scr->scr_height) {
new_y = scr->scr_height - menu->entry_height - 1;
move = 1;
if (x1 < rect.pos.x) {
new_x = rect.pos.x;
move = 1;
} else if (x2 >= rect.pos.x + rect.size.width) {
new_x = rect.pos.x + rect.size.width - MENUW(menu) - 1;
move = 1;
}
if (y1 < rect.pos.y) {
new_y = rect.pos.y;
move = 1;
} else if (y2 >= rect.pos.y + rect.size.height) {
new_y = rect.pos.y + rect.size.height - menu->entry_height - 1;
move = 1;
}
new_y = new_y - menu->frame->top_width
@@ -943,8 +946,8 @@ keyboardMenu(WMenu *menu)
int old_pos_x = menu->frame_x;
int old_pos_y = menu->frame_y;
int new_x = old_pos_x, new_y = old_pos_y;
int scr_width = menu->frame->screen_ptr->scr_width;
int scr_height = menu->frame->screen_ptr->scr_height;
WMRect rect = wGetRectForHead(menu->frame->screen_ptr,
wGetHeadForPointerLocation(menu->frame->screen_ptr));
if (menu->flags.editing)
return False;
@@ -953,11 +956,12 @@ keyboardMenu(WMenu *menu)
XGrabKeyboard(dpy, menu->frame->core->window, True, GrabModeAsync,
GrabModeAsync, CurrentTime);
if (menu->frame_y+menu->frame->top_width >= scr_height)
new_y = scr_height - menu->frame->top_width;
if (menu->frame_x+MENUW(menu) >= scr_width)
new_x = scr_width-MENUW(menu)-1;
if (menu->frame_y+menu->frame->top_width >= rect.pos.y + rect.size.height)
new_y = rect.pos.y + rect.size.height - menu->frame->top_width;
if (menu->frame_x+MENUW(menu) >= rect.pos.x + rect.size.width)
new_x = rect.pos.x + rect.size.width - MENUW(menu) - 1;
move_menus(menu, new_x, new_y);
@@ -1132,8 +1136,8 @@ keyboardMenu(WMenu *menu)
void
wMenuMapAt(WMenu *menu, int x, int y, int keyboard)
{
int scr_width = menu->frame->screen_ptr->scr_width;
int scr_height = menu->frame->screen_ptr->scr_height;
WMRect rect = wGetRectForHead(menu->frame->screen_ptr,
wGetHeadForPointerLocation(menu->frame->screen_ptr));
if (!menu->flags.realized) {
menu->flags.realized=1;
@@ -1141,12 +1145,12 @@ wMenuMapAt(WMenu *menu, int x, int y, int keyboard)
}
if (!menu->flags.mapped) {
if (wPreferences.wrap_menus) {
if (x<0) x = 0;
if (y<0) y = 0;
if (x+MENUW(menu) > scr_width)
x = scr_width - MENUW(menu);
if (y+MENUH(menu) > scr_height)
y = scr_height - MENUH(menu);
if (x<rect.pos.x) x = rect.pos.x;
if (y<rect.pos.y) y = rect.pos.y;
if (x+MENUW(menu) > rect.pos.x + rect.size.width)
x = rect.pos.x + rect.size.width - MENUW(menu);
if (y+MENUH(menu) > rect.pos.y + rect.size.height)
y = rect.pos.y + rect.size.height - MENUH(menu);
}
XMoveWindow(dpy, menu->frame->core->window, x, y);
@@ -1618,39 +1622,40 @@ getScrollAmount(WMenu *menu, int *hamount, int *vamount)
int menuY1 = menu->frame_y;
int menuX2 = menu->frame_x + MENUW(menu);
int menuY2 = menu->frame_y + MENUH(menu);
int screenW = scr->scr_width;
int screenH = scr->scr_height;
int xroot, yroot;
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
*hamount = 0;
*vamount = 0;
getPointerPosition(scr, &xroot, &yroot);
if (xroot <= 1 && menuX1 < 0) {
/* scroll to the right */
*hamount = WMIN(MENU_SCROLL_STEP, abs(menuX1));
} else if (xroot >= screenW-2 && menuX2 > screenW-1) {
/* scroll to the left */
*hamount = WMIN(MENU_SCROLL_STEP, abs(menuX2-screenW-1));
if (*hamount==0)
*hamount = 1;
*hamount = -*hamount;
if (xroot <= (rect.pos.x + 1) && menuX1 < rect.pos.x) {
/* scroll to the right */
*hamount = WMIN(MENU_SCROLL_STEP, abs(menuX1));
} else if (xroot >= (rect.pos.x + rect.size.width - 2) &&
menuX2 > (rect.pos.x + rect.size.width - 1)) {
/* scroll to the left */
*hamount = WMIN(MENU_SCROLL_STEP, abs(menuX2-rect.pos.x-rect.size.width-1));
if (*hamount==0)
*hamount = 1;
*hamount = -*hamount;
}
if (yroot <= 1 && menuY1 < 0) {
/* scroll down */
*vamount = WMIN(MENU_SCROLL_STEP, abs(menuY1));
} else if (yroot >= screenH-2 && menuY2 > screenH-1) {
/* scroll up */
*vamount = WMIN(MENU_SCROLL_STEP, abs(menuY2-screenH-2));
*vamount = -*vamount;
if (yroot <= (rect.pos.y + 1) && menuY1 < rect.pos.y) {
/* scroll down */
*vamount = WMIN(MENU_SCROLL_STEP, abs(menuY1));
} else if (yroot >= (rect.pos.y + rect.size.height - 2) &&
menuY2 > (rect.pos.y + rect.size.height - 1)) {
/* scroll up */
*vamount = WMIN(MENU_SCROLL_STEP, abs(menuY2-rect.pos.y-rect.size.height-2));
*vamount = -*vamount;
}
}
@@ -1740,16 +1745,19 @@ isPointNearBoder(WMenu *menu, int x, int y)
int menuY1 = menu->frame_y;
int menuX2 = menu->frame_x + MENUW(menu);
int menuY2 = menu->frame_y + MENUH(menu);
int scrXe = menu->menu->screen_ptr->scr_width-1;
int scrYe = menu->menu->screen_ptr->scr_height-1;
int flag = 0;
if (x >= menuX1 && x <= menuX2 && (y < MENU_SCROLL_BORDER
|| y > scrYe-MENU_SCROLL_BORDER))
flag = 1;
else if (y >= menuY1 && y <= menuY2 && (x < MENU_SCROLL_BORDER
|| x > scrXe-MENU_SCROLL_BORDER))
flag = 1;
/* XXX: handle screen joins proper !! */
WMRect rect = wGetRectForHead(menu->frame->screen_ptr,
wGetHeadForPoint(menu->frame->screen_ptr, (WMPoint){ x, y}));
if (x >= menuX1 && x <= menuX2 &&
(y < rect.pos.y + MENU_SCROLL_BORDER ||
y >= rect.pos.y + rect.size.height + MENU_SCROLL_BORDER))
flag = 1;
else if (y >= menuY1 && y <= menuY2 &&
(x < rect.pos.x + MENU_SCROLL_BORDER ||
x >= rect.pos.x + rect.size.width + MENU_SCROLL_BORDER))
flag = 1;
return flag;
}
@@ -1803,6 +1811,7 @@ wMenuScroll(WMenu *menu, XEvent *event)
while(!done) {
int x, y, on_border, on_x_edge, on_y_edge, on_title;
WMRect rect;
WMNextEvent(dpy, &ev);
switch (ev.type) {
@@ -1823,8 +1832,9 @@ wMenuScroll(WMenu *menu, XEvent *event)
break;
}
on_x_edge = x <= 1 || x >= scr->scr_width - 2;
on_y_edge = y <= 1 || y >= scr->scr_height - 2;
rect = wGetRectForHead(scr, wGetHeadForPoint(scr, (WMPoint){ x, y }));
on_x_edge = x <= rect.pos.x + 1 || x >= rect.pos.x + rect.size.width - 2;
on_y_edge = y <= rect.pos.y + 1 || y >= rect.pos.y + rect.size.height - 2;
on_border = on_x_edge || on_y_edge;
if (!on_border && !jump_back) {
@@ -2631,15 +2641,17 @@ restoreMenu(WScreen *scr, WMPropList *menu, int which)
if (pmenu) {
int width = MENUW(pmenu);
int height = MENUH(pmenu);
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
if (lowered) {
changeMenuLevels(pmenu, True);
}
x = (x < -width) ? 0 : x;
x = (x > scr->scr_width) ? scr->scr_width - width : x;
y = (y < 0) ? 0 : y;
y = (y > scr->scr_height) ? scr->scr_height - height : y;
if (x < rect.pos.x - width) x = rect.pos.x;
if (x > rect.pos.x + rect.size.width) x = rect.pos.x + rect.size.width - width;
if (y < rect.pos.y) y = rect.pos.y;
if (y > rect.pos.y + rect.size.height) y = rect.pos.y + rect.size.height - height;
wMenuMove(pmenu, x, y, True);
pmenu->flags.buttoned = 1;
wFrameWindowShowButton(pmenu->frame, WFF_RIGHT_BUTTON);
@@ -2671,6 +2683,7 @@ restoreMenuRecurs(WScreen *scr, WMPropList *menus, WMenu *menu, char *path)
if (!menu->flags.mapped) {
int width = MENUW(menu);
int height = MENUH(menu);
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
wMenuMapAt(menu, x, y, False);
@@ -2686,10 +2699,12 @@ restoreMenuRecurs(WScreen *scr, WMPropList *menus, WMenu *menu, char *path)
if (lowered) {
changeMenuLevels(menu, True);
}
x = (x < -width) ? 0 : x;
x = (x > scr->scr_width) ? scr->scr_width - width : x;
y = (y < 0) ? 0 : y;
y = (y > scr->scr_height) ? scr->scr_height - height : y;
if (x < rect.pos.x - width) x = rect.pos.x;
if (x > rect.pos.x + rect.size.width) x = rect.pos.x + rect.size.width - width;
if (y < rect.pos.y) y = rect.pos.y;
if (y > rect.pos.y + rect.size.height) y = rect.pos.y + rect.size.height - height;
wMenuMove(menu, x, y, True);
menu->flags.buttoned = 1;
wFrameWindowShowButton(menu->frame, WFF_RIGHT_BUTTON);

View File

@@ -41,6 +41,8 @@
#include "workspace.h"
#include "geomview.h"
#include "screen.h"
#include "xinerama.h"
#include <WINGs/WINGsP.h>
@@ -110,19 +112,45 @@ moveGeometryDisplayCentered(WScreen *scr, int x, int y)
{
unsigned int w = WMWidgetWidth(scr->gview);
unsigned int h = WMWidgetHeight(scr->gview);
unsigned int x1 = 0, y1 = 0, x2 = scr->scr_width, y2 = scr->scr_height;
x -= w / 2;
y -= h / 2;
if (x < 1)
x = 1;
else if (x > (scr->scr_width - w - 3))
x = scr->scr_width - w - 3;
if (y < 1)
y = 1;
else if (y > (scr->scr_height - h - 3))
y = scr->scr_height - h - 3;
/*
* dead area check
*/
if (scr->xine_count) {
WMRect rect;
int head, flags;
rect.pos.x = x;
rect.pos.y = y;
rect.size.width = w;
rect.size.height = h;
head = wGetRectPlacementInfo(scr, rect, &flags);
if (flags & (XFLAG_DEAD | XFLAG_PARTIAL)) {
rect = wGetRectForHead(scr, head);
x1 = rect.pos.x;
y1 = rect.pos.y;
x2 = x1 + rect.size.width;
y2 = y1 + rect.size.height;
}
}
if (x < x1 + 1)
x = x1 + 1;
else if (x > (x2 - w))
x = x2 - w;
if (y < y1 + 1)
y = y1 + 1;
else if (y > (y2 - h))
y = y2 - h;
WMMoveWidget(scr->gview, x, y);
}
@@ -178,8 +206,10 @@ cyclePositionDisplay(WWindow *wwin, int x, int y, int w, int h)
WMUnmapWidget(scr->gview);
} else {
if (wPreferences.move_display == WDIS_CENTER) {
moveGeometryDisplayCentered(scr,
scr->scr_width/2, scr->scr_height/2);
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
moveGeometryDisplayCentered(scr,
rect.pos.x + rect.size.width/2,
rect.pos.y + rect.size.width/2);
} else if (wPreferences.move_display == WDIS_TOPLEFT) {
moveGeometryDisplayCentered(scr, 1, 1);
} else if (wPreferences.move_display == WDIS_FRAME_CENTER) {
@@ -199,8 +229,10 @@ mapPositionDisplay(WWindow *wwin, int x, int y, int w, int h)
|| wPreferences.move_display == WDIS_NONE) {
return;
} else if (wPreferences.move_display == WDIS_CENTER) {
moveGeometryDisplayCentered(scr, scr->scr_width / 2,
scr->scr_height / 2);
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
moveGeometryDisplayCentered(scr,
rect.pos.x + rect.size.width/2,
rect.pos.y + rect.size.width/2);
} else if (wPreferences.move_display == WDIS_TOPLEFT) {
moveGeometryDisplayCentered(scr, 1, 1);
} else if (wPreferences.move_display == WDIS_FRAME_CENTER) {
@@ -383,8 +415,10 @@ cycleGeometryDisplay(WWindow *wwin, int x, int y, int w, int h, int dir)
WMUnmapWidget(scr->gview);
} else {
if (wPreferences.size_display == WDIS_CENTER) {
moveGeometryDisplayCentered(scr,
scr->scr_width / 2, scr->scr_height / 2);
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
moveGeometryDisplayCentered(scr,
rect.pos.x + rect.size.width/2,
rect.pos.y + rect.size.width/2);
} else if (wPreferences.size_display == WDIS_TOPLEFT) {
moveGeometryDisplayCentered(scr, 1, 1);
} else if (wPreferences.size_display == WDIS_FRAME_CENTER) {
@@ -406,8 +440,10 @@ mapGeometryDisplay(WWindow *wwin, int x, int y, int w, int h)
return;
if (wPreferences.size_display == WDIS_CENTER) {
moveGeometryDisplayCentered(scr, scr->scr_width / 2,
scr->scr_height / 2);
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
moveGeometryDisplayCentered(scr,
rect.pos.x + rect.size.width/2,
rect.pos.y + rect.size.width/2);
} else if (wPreferences.size_display == WDIS_TOPLEFT) {
moveGeometryDisplayCentered(scr, 1, 1);
} else if (wPreferences.size_display == WDIS_FRAME_CENTER) {
@@ -423,9 +459,8 @@ static void
doWindowMove(WWindow *wwin, WMArray *array, int dx, int dy)
{
WWindow *tmpw;
WScreen *scr = wwin->screen_ptr;
int x, y;
int scr_width = wwin->screen_ptr->scr_width;
int scr_height = wwin->screen_ptr->scr_height;
if (!array || !WMGetArrayItemCount(array)) {
wWindowMove(wwin, wwin->frame_x + dx, wwin->frame_y + dy);
@@ -436,17 +471,23 @@ doWindowMove(WWindow *wwin, WMArray *array, int dx, int dy)
x = tmpw->frame_x + dx;
y = tmpw->frame_y + dy;
#if 1 /* XXX: with xinerama patch was #if 0, check this */
/* don't let windows become unreachable */
if (x + (int)tmpw->frame->core->width < 20)
x = 20 - (int)tmpw->frame->core->width;
else if (x + 20 > scr_width)
x = scr_width - 20;
else if (x + 20 > scr->scr_width)
x = scr->scr_width - 20;
if (y + (int)tmpw->frame->core->height < 20)
y = 20 - (int)tmpw->frame->core->height;
else if (y + 20 > scr_height)
y = scr_height - 20;
else if (y + 20 > scr->scr_height)
y = scr->scr_height - 20;
#else
wScreenBringInside(scr, &x, &y,
(int)tmpw->frame->core->width,
(int)tmpw->frame->core->height);
#endif
wWindowMove(tmpw, x, y);
}
@@ -509,7 +550,7 @@ drawFrames(WWindow *wwin, WMArray *array, int dx, int dy)
y = tmpw->frame_y + dy;
/* don't let windows become unreachable */
#if 1 /* XXX: was 0 in XINERAMA patch, check */
if (x + (int)tmpw->frame->core->width < 20)
x = 20 - (int)tmpw->frame->core->width;
else if (x + 20 > scr_width)
@@ -520,6 +561,12 @@ drawFrames(WWindow *wwin, WMArray *array, int dx, int dy)
else if (y + 20 > scr_height)
y = scr_height - 20;
#else
wScreenBringInside(wwin->screen_ptr, &x, &y,
(int)tmpw->frame->core->width,
(int)tmpw->frame->core->height);
#endif
drawTransparentFrame(tmpw, x, y, tmpw->frame->core->width,
tmpw->frame->core->height);
}
@@ -981,10 +1028,16 @@ updateWindowPosition(WWindow *wwin, MoveData *data, Bool doResistance,
if (dx || dy) {
int i;
/* window is the leftmost window: check against screen edge */
l_edge = scr->totalUsableArea.x1;
r_edge = scr->totalUsableArea.x2 + resist;
edge_l = scr->totalUsableArea.x1 - resist;
edge_r = scr->totalUsableArea.x2;
/*
* Add inter head resistance 1/2 (if needed)
*/
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
l_edge = WMAX(scr->totalUsableArea.x1, rect.pos.x);
edge_l = l_edge - resist;
edge_r = WMIN(scr->totalUsableArea.x2, rect.pos.x + rect.size.width);
r_edge = edge_r + resist;
/* 1 */
if ((data->rightIndex >= 0) && (data->rightIndex <= data->count)) {
@@ -1080,10 +1133,13 @@ updateWindowPosition(WWindow *wwin, MoveData *data, Bool doResistance,
}
/* VeRT */
t_edge = scr->totalUsableArea.y1;
b_edge = scr->totalUsableArea.y2 + resist;
edge_t = scr->totalUsableArea.y1 - resist;
edge_b = scr->totalUsableArea.y2;
/*
* Add inter head resistance 2/2 (if needed)
*/
t_edge = WMAX(scr->totalUsableArea.y1, rect.pos.y);
edge_t = t_edge - resist;
edge_b = WMIN(scr->totalUsableArea.y2, rect.pos.y + rect.size.height);
b_edge = edge_b + resist;
if ((data->bottomIndex >= 0) && (data->bottomIndex <= data->count)) {
WWindow *looprw;

View File

@@ -39,6 +39,7 @@
#include "application.h"
#include "appicon.h"
#include "dock.h"
#include "xinerama.h"
extern WPreferences wPreferences;
@@ -140,14 +141,22 @@ PlaceIcon(WScreen *scr, int *x_ret, int *y_ret)
int isize = wPreferences.icon_size;
int done = 0;
WMBagIterator iter;
/*
* Find out screen boundaries.
*/
sx1 = 0;
sy1 = 0;
sx2 = scr->scr_width;
sy2 = scr->scr_height;
/*
* Allows each head to have miniwindows
*/
WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
sx1 = rect.pos.x;
sy1 = rect.pos.y;
sw = rect.size.width;
sh = rect.size.height;
sx2 = sx1 + sw;
sy2 = sy1 + sh;
if (scr->dock) {
if (scr->dock->on_right_side)
sx2 -= isize + DOCK_EXTRA_SPACE;
@@ -155,8 +164,8 @@ PlaceIcon(WScreen *scr, int *x_ret, int *y_ret)
sx1 += isize + DOCK_EXTRA_SPACE;
}
sw = isize * (scr->scr_width/isize);
sh = isize * (scr->scr_height/isize);
sw = isize * (sw/isize);
sh = isize * (sh/isize);
fullW = (sx2-sx1)/isize;
fullH = (sy2-sy1)/isize;
@@ -284,9 +293,10 @@ calcIntersectionLength(int p1, int l1, int p2, int l2)
/*
* This function calculates the area of the intersection of two rectangles.
*/
static int
int
calcIntersectionArea(int x1, int y1, int w1, int h1,
int x2, int y2, int w2, int h2)
int x2, int y2, int w2, int h2)
{
return calcIntersectionLength(x1, w1, x2, w2)
* calcIntersectionLength(y1, h1, y2, h2);
@@ -337,7 +347,8 @@ calcSumOfCoveredAreas(WWindow *wwin, int x, int y, int w, int h)
static void
smartPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
unsigned int width, unsigned int height)
unsigned int width, unsigned int height,
WArea usableArea)
{
WScreen *scr = wwin->screen_ptr;
int test_x = 0, test_y = Y_ORIGIN(scr);
@@ -346,7 +357,6 @@ smartPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
int min_isect, min_isect_x, min_isect_y;
int sum_isect;
int extra_height;
WArea usableArea = scr->totalUsableArea;
if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width;
@@ -413,7 +423,8 @@ smartPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
static Bool
autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
unsigned int width, unsigned int height, int tryCount)
unsigned int width, unsigned int height, int tryCount,
WArea usableArea)
{
WScreen *scr = wwin->screen_ptr;
int test_x = 0, test_y = Y_ORIGIN(scr);
@@ -421,7 +432,7 @@ autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
int swidth, sx;
WWindow *test_window;
int extra_height;
WArea usableArea = scr->totalUsableArea;
if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width + 2;
@@ -435,8 +446,7 @@ autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
height += extra_height;
while (((test_y + height) < (scr->scr_height)) && (!loc_ok)) {
while (((test_y + height) < (usableArea.y2 - usableArea.y1)) && !loc_ok) {
test_x = sx;
while (((test_x + width) < swidth) && (!loc_ok)) {
@@ -527,10 +537,11 @@ autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
static void
cascadeWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret,
unsigned int width, unsigned int height, int h)
unsigned int width, unsigned int height, int h,
WArea usableArea)
{
unsigned int extra_height;
WArea usableArea = scr->totalUsableArea;
if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width;
@@ -549,26 +560,53 @@ cascadeWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret,
}
static void
randomPlaceWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret,
unsigned int width, unsigned int height,
WArea usableArea)
{
int w, h, extra_height;
if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width + 2;
else
extra_height = 24; /* random value */
w = ((usableArea.x2-X_ORIGIN(scr)) - width);
h = ((usableArea.y2-Y_ORIGIN(scr)) - height - extra_height);
if (w<1) w = 1;
if (h<1) h = 1;
*x_ret = X_ORIGIN(scr) + rand()%w;
*y_ret = Y_ORIGIN(scr) + rand()%h;
}
void
PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
unsigned width, unsigned height)
{
WScreen *scr = wwin->screen_ptr;
int h = WMFontHeight(scr->title_font) + (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
WArea usableArea = wGetUsableAreaForHead(scr,
wGetHeadForPointerLocation(scr),
NULL);
switch (wPreferences.window_placement) {
case WPM_MANUAL:
InteractivePlaceWindow(wwin, x_ret, y_ret, width, height);
break;
case WPM_SMART:
smartPlaceWindow(wwin, x_ret, y_ret, width, height);
smartPlaceWindow(wwin, x_ret, y_ret, width, height, usableArea);
break;
case WPM_AUTO:
if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 0)) {
if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 0,
usableArea)) {
break;
} else if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 1)) {
} else if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 1,
usableArea)) {
break;
}
/* there isn't a break here, because if we fail, it should fall
@@ -579,32 +617,17 @@ PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
if (wPreferences.window_placement == WPM_AUTO)
scr->cascade_index++;
cascadeWindow(scr, wwin, x_ret, y_ret, width, height, h);
cascadeWindow(scr, wwin, x_ret, y_ret, width, height, h, usableArea);
if (wPreferences.window_placement == WPM_CASCADE)
scr->cascade_index++;
break;
case WPM_RANDOM:
{
int w, h, extra_height;
WArea usableArea = scr->totalUsableArea;
if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width + 2;
else
extra_height = 24; /* random value */
w = ((usableArea.x2-X_ORIGIN(scr)) - width);
h = ((usableArea.y2-Y_ORIGIN(scr)) - height - extra_height);
if (w<1) w = 1;
if (h<1) h = 1;
*x_ret = X_ORIGIN(scr) + rand()%w;
*y_ret = Y_ORIGIN(scr) + rand()%h;
}
randomPlaceWindow(scr, wwin, x_ret, y_ret, width, height, usableArea);
break;
#ifdef DEBUG
#ifdef DEBUG
default:
puts("Invalid window placement!!!");
*x_ret = 0;
@@ -612,15 +635,20 @@ PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
#endif
}
if (*x_ret + width > scr->scr_width)
*x_ret = scr->scr_width - width;
if (*x_ret < 0)
*x_ret = 0;
/*
* clip to usableArea instead of full screen
* this will also take dock/clip etc.. into account
* aswell as being xinerama friendly
*/
if (*x_ret + width > usableArea.x2)
*x_ret = usableArea.x2 - width;
if (*x_ret < usableArea.x1)
*x_ret = usableArea.x1;
if (*y_ret + height > scr->scr_height)
*y_ret = scr->scr_height - height;
if (*y_ret < 0)
*y_ret = 0;
if (*y_ret + height > usableArea.y2)
*y_ret = usableArea.y2 - height;
if (*y_ret < usableArea.y1)
*y_ret = usableArea.y1;
}

View File

@@ -605,7 +605,6 @@ wScreenInit(int screen_number)
RContextAttributes rattr;
extern int wVisualID;
long event_mask;
WMColor *color;
XErrorHandler oldHandler;
scr = wmalloc(sizeof(WScreen));
@@ -666,10 +665,7 @@ wScreenInit(int screen_number)
return NULL;
}
#ifdef XINERAMA
wInitXinerama(scr);
#endif
XDefineCursor(dpy, scr->root_win, wCursor[WCUR_ROOT]);
@@ -832,19 +828,9 @@ wScreenInit(int screen_number)
static WArea subtractRectangle(WArea area, WArea rect)
{
WArea result = area;
}
void
wScreenUpdateUsableArea(WScreen *scr)
{
WReservedArea *area;
scr->totalUsableArea = scr->usableArea;
@@ -1119,7 +1105,46 @@ wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height)
{
int moved = 0;
int tol_w, tol_h;
/*
* With respect to the head that contains most of the window.
*/
int sx1, sy1, sx2, sy2;
WMRect rect;
int head, flags;
rect.pos.x = *x;
rect.pos.y = *y;
rect.size.width = width;
rect.size.height = height;
head = wGetRectPlacementInfo(scr, rect, &flags);
rect = wGetRectForHead(scr, head);
sx1 = rect.pos.x;
sy1 = rect.pos.y;
sx2 = sx1 + rect.size.width;
sy2 = sy1 + rect.size.height;
#if 0 /* NOTE: gives funky group movement */
if (flags & XFLAG_MULTIPLE) {
/*
* since we span multiple heads, pull window totaly inside
*/
if (*x < sx1)
*x = sx1, moved = 1;
else if (*x + width > sx2)
*x = sx2 - width, moved = 1;
if (*y < sy1)
*y = sy1, moved = 1;
else if (*y + height > sy2)
*y = sy2 - height, moved = 1;
return moved;
}
#endif
if (width > 20)
tol_w = width/2;
else
@@ -1130,15 +1155,51 @@ wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height)
else
tol_h = 20;
if (*x+width < 10)
*x = -tol_w, moved = 1;
else if (*x >= scr->scr_width - 10)
*x = scr->scr_width - tol_w - 1, moved = 1;
if (*x + width < sx1 + 10)
*x = sx1 - tol_w, moved = 1;
else if (*x >= sx2 - 10)
*x = sx2 - tol_w - 1, moved = 1;
if (*y < -height + 10)
*y = -tol_h, moved = 1;
else if (*y >= scr->scr_height - 10)
*y = scr->scr_height - tol_h - 1, moved = 1;
if (*y < sy1 - height + 10)
*y = sy1 - tol_h, moved = 1;
else if (*y >= sy2 - 10)
*y = sy2 - tol_h - 1, moved = 1;
return moved;
}
int
wScreenKeepInside(WScreen *scr, int *x, int *y, int width, int height)
{
int moved = 0;
int sx1, sy1, sx2, sy2;
WMRect rect;
int head;
rect.pos.x = *x;
rect.pos.y = *y;
rect.size.width = width;
rect.size.height = height;
head = wGetHeadForRect(scr, rect);
rect = wGetRectForHead(scr, head);
sx1 = rect.pos.x;
sy1 = rect.pos.y;
sx2 = sx1 + rect.size.width;
sy2 = sy1 + rect.size.height;
if (*x < sx1)
*x = sx1, moved = 1;
else if (*x + width > sx2)
*x = sx2 - width, moved = 1;
if (*y < sy1)
*y = sy1, moved = 1;
else if (*y + height > sy2)
*y = sy2 - height, moved = 1;
return moved;
}

View File

@@ -95,9 +95,9 @@ typedef struct _WScreen {
#ifdef XINERAMA
XineramaScreenInfo *xine_screens;
#endif
int xine_count; /* 0 means not active */
int xine_primary_head; /* main working screen */
#endif
Window no_focus_win; /* window to get focus when nobody
* else can do it */
@@ -348,6 +348,8 @@ void wScreenSaveState(WScreen *scr);
void wScreenRestoreState(WScreen *scr);
int wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height);
int wScreenKeepInside(WScreen *scr, int *x, int *y, int width, int height);
/* in startup.c */
WScreen *wScreenWithNumber(int i);

View File

@@ -53,6 +53,7 @@
#include "stacking.h"
#include "defaults.h"
#include "workspace.h"
#include "xinerama.h"
#ifdef MWM_HINTS
@@ -774,6 +775,8 @@ wManageWindow(WScreen *scr, Window window)
/* get geometry stuff */
wClientGetNormalHints(wwin, &wattribs, True, &x, &y, &width, &height);
/* printf( "wManageWindow: %d %d %d %d\n", x, y, width, height);*/
/* get colormap windows */
GetColormapWindows(wwin);
@@ -1099,27 +1102,114 @@ wManageWindow(WScreen *scr, Window window)
if (transientOwner && transientOwner->flags.mapped) {
int offs = WMAX(20, 2*transientOwner->frame->top_width);
WMRect rect;
int head;
x = transientOwner->frame_x +
abs((transientOwner->frame->core->width - width)/2) + offs;
y = transientOwner->frame_y +
abs((transientOwner->frame->core->height - height)/3) + offs;
if (x < 0)
x = 0;
else if (x + width > scr->scr_width)
x = scr->scr_width - width;
/*
* limit transient windows to be inside their parent's head
*/
rect.pos.x = transientOwner->frame_x;
rect.pos.y = transientOwner->frame_y;
rect.size.width = transientOwner->frame->core->width;
rect.size.height = transientOwner->frame->core->height;
head = wGetHeadForRect(scr, rect);
rect = wGetRectForHead(scr, head);
if (x < rect.pos.x)
x = rect.pos.x;
else if (x + width > rect.pos.x + rect.size.width)
x = rect.pos.x + rect.size.width - width;
if (y < rect.pos.y)
y = rect.pos.y;
else if (y + height > rect.pos.y + rect.size.height)
y = rect.pos.y + rect.size.height - height;
if (y < 0)
y = 0;
else if (y + height > scr->scr_height)
y = scr->scr_height - height;
} else {
PlaceWindow(wwin, &x, &y, width, height);
}
if (wPreferences.window_placement == WPM_MANUAL)
dontBring = True;
}
else if (scr->xine_count &&
wwin->normal_hints->flags & PPosition) {
int head, flags;
WMRect rect;
int reposition = 0;
/*
* Make spash screens come out in the center of a head
* trouble is that most splashies never get here
* they are managed trough atoms but god knows where.
* Dan, do you know ?
*
* Most of them are not managed, they are set
* OverrideRedirect, which means we can't do anything about
* them. -alfredo
*/
#if 0
printf( "xinerama PPosition: x: %d %d\n", x, (scr->scr_width - width)/2);
printf( "xinerama PPosition: y: %d %d\n", y, (scr->scr_height - height)/2);
if ( (unsigned)(x + (width - scr->scr_width)/2 + 10) < 20 &&
(unsigned)(y + (height - scr->scr_height)/2 + 10) < 20) {
reposition = 1;
} else
#endif
{
/*
* xinerama checks for: across head and dead space
*/
rect.pos.x = x;
rect.pos.y = y;
rect.size.width = width;
rect.size.height = height;
head = wGetRectPlacementInfo(scr, rect, &flags);
if (flags & XFLAG_DEAD)
reposition = 1;
if (flags & XFLAG_MULTIPLE)
reposition = 2;
}
switch (reposition) {
case 1:
head = wGetHeadForPointerLocation(scr);
rect = wGetRectForHead(scr, head);
x = rect.pos.x + (x * rect.size.width)/scr->scr_width;
y = rect.pos.y + (y * rect.size.height)/scr->scr_height;
break;
case 2:
rect = wGetRectForHead(scr, head);
if (x < rect.pos.x)
x = rect.pos.x;
else if (x + width > rect.pos.x + rect.size.width)
x = rect.pos.x + rect.size.width - width;
if (y < rect.pos.y)
y = rect.pos.y;
else if (y + height > rect.pos.y + rect.size.height)
y = rect.pos.y + rect.size.height - height;
break;
default:
break;
}
}
if (WFLAGP(wwin, dont_move_off) && dontBring)
wScreenBringInside(scr, &x, &y, width, height);

View File

@@ -23,92 +23,91 @@
#include "wconfig.h"
#ifdef XINERAMA
#include "xinerama.h"
#include "screen.h"
#include "window.h"
#include "framewin.h"
#include "wcore.h"
#include "funcs.h"
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
void wInitXinerama(WScreen *scr)
{
scr->xine_screens = 0;
scr->xine_count = 0;
#ifdef XINERAMA
scr->xine_screens = XineramaQueryScreens(dpy, &scr->xine_count);
#endif
scr->xine_primary_head = 0;
}
/*
* intersect_rectangles-
* Calculate the rectangle that results from the intersection of
* 2 rectangles.
*
* Returns:
* 0 if the rectangles do not intersect, 1 otherwise.
*/
typedef struct {
int x1, y1, x2, y2;
} _Rectangle;
int intersect_rectangles(_Rectangle *rect1,
_Rectangle *rect2,
_Rectangle *result)
int wGetRectPlacementInfo(WScreen *scr, WMRect rect, int *flags)
{
if (rect1->x1 < rect2->x1)
result->x1 = rect2->x1;
else
result->x1 = rect1->x1;
if (rect1->x2 > rect2->x2)
result->x2 = rect2->x2;
else
result->x2 = rect1->x2;
if (rect1->y1 < rect2->y1)
result->y1 = rect2->y1;
else
result->y1 = rect1->y1;
if (rect1->y2 > rect2->y2)
result->y2 = rect2->y2;
else
result->y2 = rect1->y2;
if (result->x2 < result->x1)
return 0;
if (result->y2 < result->y1)
return 0;
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;
return 1;
}
wassertrv(flags!=NULL, 0);
best = -1;
area = 0;
totalArea = 0;
static int intersectArea(int x1, int y1, int w1, int h1,
int x2, int y2, int w2, int h2)
{
_Rectangle rect1, rect2, result;
rect1.x1 = x1;
rect1.y1 = y1;
rect1.x2 = x1+w1;
rect1.y2 = y1+h1;
rect2.x1 = x2;
rect2.y1 = y2;
rect2.x2 = x2+w2;
rect2.y2 = y2+h2;
if (intersect_rectangles(&rect1, &rect2, &result))
return (result.x2-result.x1)*(result.y2-result.y1);
else
return 0;
*flags = XFLAG_NONE;
if (scr->xine_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_primary_head;
}
#ifdef XINERAMA
for (i = 0; i < scr->xine_count; i++) {
unsigned long a;
a = calcIntersectionArea(rx, ry, rw, rh,
scr->xine_screens[i].x_org,
scr->xine_screens[i].y_org,
scr->xine_screens[i].width,
scr->xine_screens[i].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;
#endif
}
/* get the head that covers most of the rectangle */
@@ -122,17 +121,21 @@ int wGetHeadForRect(WScreen *scr, WMRect rect)
int rw = rect.size.width;
int rh = rect.size.height;
if (!scr->xine_count)
return scr->xine_primary_head;
best = -1;
area = 0;
#ifdef XINERAMA
for (i = 0; i < scr->xine_count; i++) {
unsigned long a;
a = intersectArea(rx, ry, rw, rh,
scr->xine_screens[i].x_org,
scr->xine_screens[i].y_org,
scr->xine_screens[i].width,
scr->xine_screens[i].height);
a = calcIntersectionArea(rx, ry, rw, rh,
scr->xine_screens[i].x_org,
scr->xine_screens[i].y_org,
scr->xine_screens[i].width,
scr->xine_screens[i].height);
if (a > area) {
area = a;
@@ -140,7 +143,16 @@ int wGetHeadForRect(WScreen *scr, WMRect rect)
}
}
/*
* in case rect is in dead space, return valid head
*/
if (best == -1)
best = wGetHeadForPointerLocation(scr);
return best;
#else /* !XINERAMA */
return scr->xine_primary_head;
#endif /* !XINERAMA */
}
@@ -157,11 +169,20 @@ int wGetHeadForWindow(WWindow *wwin)
}
int wGetHeadForPoint(WScreen *scr, WMPoint point)
/*
int wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags)
{
int i;
// paranoia
if ( flags == NULL) {
static int tmp;
flags = &tmp;
}
*flags = XFLAG_NONE;
for (i = 0; i < scr->xine_count; i++) {
#if 0
int yy, xx;
xx = scr->xine_screens[i].x_org + scr->xine_screens[i].width;
@@ -171,10 +192,38 @@ int wGetHeadForPoint(WScreen *scr, WMPoint point)
point.x < xx && point.y < yy) {
return i;
}
#else
XineramaScreenInfo *xsi = &scr->xine_screens[i];
if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
(unsigned)(point.y - xsi->y_org) < xsi->height)
return i;
#endif
}
*flags |= XFLAG_DEAD;
return scr->xine_primary_head;
}
*/
int wGetHeadForPoint(WScreen *scr, WMPoint point)
{
#ifdef XINERAMA
int i;
for (i = 0; i < scr->xine_count; i++) {
XineramaScreenInfo *xsi = &scr->xine_screens[i];
if ((unsigned)(point.x - xsi->x_org) < xsi->width &&
(unsigned)(point.y - xsi->y_org) < xsi->height)
return i;
}
#endif /* XINERAMA */
return scr->xine_primary_head;
}
int wGetHeadForPointerLocation(WScreen *scr)
@@ -184,6 +233,8 @@ int wGetHeadForPointerLocation(WScreen *scr)
int ble;
unsigned int blo;
if (!scr->xine_count)
return scr->xine_primary_head;
if (!XQueryPointer(dpy, scr->root_win, &bla, &bla,
&point.x, &point.y,
@@ -200,12 +251,15 @@ wGetRectForHead(WScreen *scr, int head)
{
WMRect rect;
#ifdef XINERAMA
if (head < scr->xine_count) {
rect.pos.x = scr->xine_screens[head].x_org;
rect.pos.y = scr->xine_screens[head].y_org;
rect.size.width = scr->xine_screens[head].width;
rect.size.height = scr->xine_screens[head].height;
} else {
} else
#endif /* XINERAMA */
{
rect.pos.x = 0;
rect.pos.y = 0;
rect.size.width = scr->scr_width;
@@ -216,24 +270,36 @@ wGetRectForHead(WScreen *scr, int head)
}
WMRect
wGetUsableRectForHead(WScreen *scr, int head)
WArea wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr)
{
WMRect rect;
WArea totalArea, usableArea = scr->totalUsableArea;
WMRect rect = wGetRectForHead(scr, head);
if (head < scr->xine_count) {
rect.pos.x = scr->xine_screens[head].x_org;
rect.pos.y = scr->xine_screens[head].y_org;
rect.size.width = scr->xine_screens[head].width;
rect.size.height = scr->xine_screens[head].height;
} else {
rect.pos.x = 0;
rect.pos.y = 0;
rect.size.width = scr->scr_width;
rect.size.height = scr->scr_height;
}
totalArea.x1 = rect.pos.x;
totalArea.y1 = rect.pos.y;
totalArea.x2 = totalArea.x1 + rect.size.width;
totalArea.y2 = totalArea.y1 + rect.size.height;
return rect;
if (totalAreaPtr != NULL) *totalAreaPtr = totalArea;
usableArea.x1 = WMAX(totalArea.x1, usableArea.x1);
usableArea.y1 = WMAX(totalArea.y1, usableArea.y1);
usableArea.x2 = WMIN(totalArea.x2, usableArea.x2);
usableArea.y2 = WMIN(totalArea.y2, usableArea.y2);
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;
}
#endif

View File

@@ -29,6 +29,14 @@
void wInitXinerama(WScreen *scr);
#define XFLAG_NONE 0x00
#define XFLAG_DEAD 0x01
#define XFLAG_MULTIPLE 0x02
#define XFLAG_PARTIAL 0x04
int wGetRectPlacementInfo(WScreen *scr, WMRect rect, int *flags);
int wGetHeadForRect(WScreen *scr, WMRect rect);
int wGetHeadForWindow(WWindow *wwin);
@@ -39,7 +47,9 @@ int wGetHeadForPointerLocation(WScreen *scr);
WMRect wGetRectForHead(WScreen *scr, int head);
WMRect wGetUsableRectForHead(WScreen *scr, int head);
WArea wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr);
WMPoint wGetPointToCenterRectInHead(WScreen *scr, int head, int width, int height);
#endif