1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 12:28:22 +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

@@ -31,6 +31,9 @@ Changes since version 0.80.1:
- Fixed wrlib to not accept too large images (fixes buffer overflow) - Fixed wrlib to not accept too large images (fixes buffer overflow)
- Patched FAQ (David Coe <davidc@debian.org>) - Patched FAQ (David Coe <davidc@debian.org>)
- Fixed bug with resizebars appearing out of nothing when reloading configs - Fixed bug with resizebars appearing out of nothing when reloading configs
- 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>)
Changes since version 0.80.0: Changes since version 0.80.0:
............................. .............................

27
FAQ
View File

@@ -1074,16 +1074,29 @@ to force the modification time into the future.
4.16 How can I set dock/clip to use single click to launch 4.16 How can I set dock/clip to use single click to launch
applications, instead of double click? applications, instead of double click?
---------------------------------- ----------------------------------
You cannot do this. This is because single click is used to select app-icons, This question was officially answered as follows:
or to raise/lower the app-icon or the dock/clip.
If this is impelmented then you will be unable to select or raise/lower
dock/clip or app-icons, without also launching the application it represents.
So don't ask for this to be implemented, because it will not be. Double You cannot do this. This is because single click is used to select
click is used for a reason, is not just some weird idea we got in a morning app-icons, or to raise/lower the app-icon or the dock/clip. If
when we wake up too early. this is impelmented then you will be unable to select or
raise/lower dock/clip or app-icons, without also launching the
application it represents.
So don't ask for this to be implemented, because it will not
be. Double click is used for a reason, is not just some weird idea
we got in a morning when we wake up too early.
Regardless of that, there is now an option in WPrefs, under "Expert
User Preferences," which allows you to set "Launch applications and
restore windows with a single click." (See the files contrib/README
and contrib/single_click.diff in the source package for details.)
If you set that option, a left button single click will launch or
restore, rather than select, the app-icon. You can use other methods
(or temporarily turn the option off again) to select app-icons or
raise/lower the dock/clip. You can toggle the selected state of any
app-icon via its right button menu, and there are auto-raise and
keep-on-top options for the dock and clip.
4.18 How do I restore the configuration app to the dock? 4.18 How do I restore the configuration app to the dock?

View File

@@ -1303,14 +1303,15 @@ main(int argc, char **argv)
*/ */
testTextField(scr);
testDragAndDrop(scr);
testText(scr);
testFontPanel(scr); testFontPanel(scr);
#if 0 #if 0
testText(scr);
testDragAndDrop(scr);
testColorPanel(scr); testColorPanel(scr);
testScrollView(scr); testScrollView(scr);
testTabView(scr); testTabView(scr);
@@ -1322,7 +1323,6 @@ main(int argc, char **argv)
testColorWell(scr); testColorWell(scr);
testTextField(scr);
testDragAndDrop(scr); testDragAndDrop(scr);
testFontPanel(scr); testFontPanel(scr);

View File

@@ -15,7 +15,7 @@ AC_INIT(src/WindowMaker.h)
AM_INIT_AUTOMAKE(WindowMaker, 0.81.0) AM_INIT_AUTOMAKE(WindowMaker, 0.81.2)
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
@@ -526,10 +526,10 @@ fi
dnl XINERAMA support dnl XINERAMA support
dnl ================ dnl ================
xinerama=no xinerama=yes
#AC_ARG_ENABLE(xinerama, AC_ARG_ENABLE(xinerama,
#[ --disable-xinerama disable XInerama extension support], [ --disable-xinerama disable XInerama extension support],
# xinerama=$enableval, xinerama=yes) xinerama=$enableval, xinerama=yes)
if test "$xinerama" = yes; then if test "$xinerama" = yes; then
AC_CHECK_LIB(Xinerama, XineramaQueryScreens, [XLIBS="-lXinerama $XLIBS" AC_CHECK_LIB(Xinerama, XineramaQueryScreens, [XLIBS="-lXinerama $XLIBS"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -39,6 +39,7 @@
#include "application.h" #include "application.h"
#include "appicon.h" #include "appicon.h"
#include "dock.h" #include "dock.h"
#include "xinerama.h"
extern WPreferences wPreferences; extern WPreferences wPreferences;
@@ -140,14 +141,22 @@ PlaceIcon(WScreen *scr, int *x_ret, int *y_ret)
int isize = wPreferences.icon_size; int isize = wPreferences.icon_size;
int done = 0; int done = 0;
WMBagIterator iter; WMBagIterator iter;
/* /*
* Find out screen boundaries. * Find out screen boundaries.
*/ */
sx1 = 0;
sy1 = 0; /*
sx2 = scr->scr_width; * Allows each head to have miniwindows
sy2 = scr->scr_height; */
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) {
if (scr->dock->on_right_side) if (scr->dock->on_right_side)
sx2 -= isize + DOCK_EXTRA_SPACE; sx2 -= isize + DOCK_EXTRA_SPACE;
@@ -155,8 +164,8 @@ PlaceIcon(WScreen *scr, int *x_ret, int *y_ret)
sx1 += isize + DOCK_EXTRA_SPACE; sx1 += isize + DOCK_EXTRA_SPACE;
} }
sw = isize * (scr->scr_width/isize); sw = isize * (sw/isize);
sh = isize * (scr->scr_height/isize); sh = isize * (sh/isize);
fullW = (sx2-sx1)/isize; fullW = (sx2-sx1)/isize;
fullH = (sy2-sy1)/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. * This function calculates the area of the intersection of two rectangles.
*/ */
static int
int
calcIntersectionArea(int x1, int y1, int w1, int h1, 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) return calcIntersectionLength(x1, w1, x2, w2)
* calcIntersectionLength(y1, h1, y2, h2); * calcIntersectionLength(y1, h1, y2, h2);
@@ -337,7 +347,8 @@ calcSumOfCoveredAreas(WWindow *wwin, int x, int y, int w, int h)
static void static void
smartPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, 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; WScreen *scr = wwin->screen_ptr;
int test_x = 0, test_y = Y_ORIGIN(scr); 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 min_isect, min_isect_x, min_isect_y;
int sum_isect; int sum_isect;
int extra_height; int extra_height;
WArea usableArea = scr->totalUsableArea;
if (wwin->frame) if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width; 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 static Bool
autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, 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; WScreen *scr = wwin->screen_ptr;
int test_x = 0, test_y = Y_ORIGIN(scr); 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; int swidth, sx;
WWindow *test_window; WWindow *test_window;
int extra_height; int extra_height;
WArea usableArea = scr->totalUsableArea;
if (wwin->frame) if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width + 2; 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; 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; test_x = sx;
while (((test_x + width) < swidth) && (!loc_ok)) { while (((test_x + width) < swidth) && (!loc_ok)) {
@@ -527,10 +537,11 @@ autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
static void static void
cascadeWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret, 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; unsigned int extra_height;
WArea usableArea = scr->totalUsableArea;
if (wwin->frame) if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width; 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 void
PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
unsigned width, unsigned height) unsigned width, unsigned height)
{ {
WScreen *scr = wwin->screen_ptr; WScreen *scr = wwin->screen_ptr;
int h = WMFontHeight(scr->title_font) + (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE) * 2; 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) { switch (wPreferences.window_placement) {
case WPM_MANUAL: case WPM_MANUAL:
InteractivePlaceWindow(wwin, x_ret, y_ret, width, height); InteractivePlaceWindow(wwin, x_ret, y_ret, width, height);
break; break;
case WPM_SMART: case WPM_SMART:
smartPlaceWindow(wwin, x_ret, y_ret, width, height); smartPlaceWindow(wwin, x_ret, y_ret, width, height, usableArea);
break; break;
case WPM_AUTO: 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; 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; break;
} }
/* there isn't a break here, because if we fail, it should fall /* 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) if (wPreferences.window_placement == WPM_AUTO)
scr->cascade_index++; 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) if (wPreferences.window_placement == WPM_CASCADE)
scr->cascade_index++; scr->cascade_index++;
break; break;
case WPM_RANDOM: case WPM_RANDOM:
{ randomPlaceWindow(scr, wwin, x_ret, y_ret, width, height, usableArea);
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;
}
break; break;
#ifdef DEBUG #ifdef DEBUG
default: default:
puts("Invalid window placement!!!"); puts("Invalid window placement!!!");
*x_ret = 0; *x_ret = 0;
@@ -612,15 +635,20 @@ PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
#endif #endif
} }
if (*x_ret + width > scr->scr_width) /*
*x_ret = scr->scr_width - width; * clip to usableArea instead of full screen
if (*x_ret < 0) * this will also take dock/clip etc.. into account
*x_ret = 0; * 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) if (*y_ret + height > usableArea.y2)
*y_ret = scr->scr_height - height; *y_ret = usableArea.y2 - height;
if (*y_ret < 0) if (*y_ret < usableArea.y1)
*y_ret = 0; *y_ret = usableArea.y1;
} }

View File

@@ -605,7 +605,6 @@ wScreenInit(int screen_number)
RContextAttributes rattr; RContextAttributes rattr;
extern int wVisualID; extern int wVisualID;
long event_mask; long event_mask;
WMColor *color;
XErrorHandler oldHandler; XErrorHandler oldHandler;
scr = wmalloc(sizeof(WScreen)); scr = wmalloc(sizeof(WScreen));
@@ -666,10 +665,7 @@ wScreenInit(int screen_number)
return NULL; return NULL;
} }
#ifdef XINERAMA
wInitXinerama(scr); wInitXinerama(scr);
#endif
XDefineCursor(dpy, scr->root_win, wCursor[WCUR_ROOT]); 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 void
wScreenUpdateUsableArea(WScreen *scr) wScreenUpdateUsableArea(WScreen *scr)
{ {
WReservedArea *area;
scr->totalUsableArea = scr->usableArea; scr->totalUsableArea = scr->usableArea;
@@ -1119,7 +1105,46 @@ wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height)
{ {
int moved = 0; int moved = 0;
int tol_w, tol_h; 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) if (width > 20)
tol_w = width/2; tol_w = width/2;
else else
@@ -1130,15 +1155,51 @@ wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height)
else else
tol_h = 20; tol_h = 20;
if (*x+width < 10) if (*x + width < sx1 + 10)
*x = -tol_w, moved = 1; *x = sx1 - tol_w, moved = 1;
else if (*x >= scr->scr_width - 10) else if (*x >= sx2 - 10)
*x = scr->scr_width - tol_w - 1, moved = 1; *x = sx2 - tol_w - 1, moved = 1;
if (*y < -height + 10) if (*y < sy1 - height + 10)
*y = -tol_h, moved = 1; *y = sy1 - tol_h, moved = 1;
else if (*y >= scr->scr_height - 10) else if (*y >= sy2 - 10)
*y = scr->scr_height - tol_h - 1, moved = 1; *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; return moved;
} }

View File

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

View File

@@ -53,6 +53,7 @@
#include "stacking.h" #include "stacking.h"
#include "defaults.h" #include "defaults.h"
#include "workspace.h" #include "workspace.h"
#include "xinerama.h"
#ifdef MWM_HINTS #ifdef MWM_HINTS
@@ -774,6 +775,8 @@ wManageWindow(WScreen *scr, Window window)
/* get geometry stuff */ /* get geometry stuff */
wClientGetNormalHints(wwin, &wattribs, True, &x, &y, &width, &height); wClientGetNormalHints(wwin, &wattribs, True, &x, &y, &width, &height);
/* printf( "wManageWindow: %d %d %d %d\n", x, y, width, height);*/
/* get colormap windows */ /* get colormap windows */
GetColormapWindows(wwin); GetColormapWindows(wwin);
@@ -1099,27 +1102,114 @@ wManageWindow(WScreen *scr, Window window)
if (transientOwner && transientOwner->flags.mapped) { if (transientOwner && transientOwner->flags.mapped) {
int offs = WMAX(20, 2*transientOwner->frame->top_width); int offs = WMAX(20, 2*transientOwner->frame->top_width);
WMRect rect;
int head;
x = transientOwner->frame_x + x = transientOwner->frame_x +
abs((transientOwner->frame->core->width - width)/2) + offs; abs((transientOwner->frame->core->width - width)/2) + offs;
y = transientOwner->frame_y + y = transientOwner->frame_y +
abs((transientOwner->frame->core->height - height)/3) + offs; abs((transientOwner->frame->core->height - height)/3) + offs;
if (x < 0) /*
x = 0; * limit transient windows to be inside their parent's head
else if (x + width > scr->scr_width) */
x = scr->scr_width - width; 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 { } else {
PlaceWindow(wwin, &x, &y, width, height); PlaceWindow(wwin, &x, &y, width, height);
} }
if (wPreferences.window_placement == WPM_MANUAL) if (wPreferences.window_placement == WPM_MANUAL)
dontBring = True; 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) if (WFLAGP(wwin, dont_move_off) && dontBring)
wScreenBringInside(scr, &x, &y, width, height); wScreenBringInside(scr, &x, &y, width, height);

View File

@@ -23,92 +23,91 @@
#include "wconfig.h" #include "wconfig.h"
#ifdef XINERAMA
#include "xinerama.h" #include "xinerama.h"
#include "screen.h" #include "screen.h"
#include "window.h" #include "window.h"
#include "framewin.h" #include "framewin.h"
#include "wcore.h" #include "wcore.h"
#include "funcs.h"
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
#endif
void wInitXinerama(WScreen *scr) void wInitXinerama(WScreen *scr)
{ {
scr->xine_screens = 0;
scr->xine_count = 0;
#ifdef XINERAMA
scr->xine_screens = XineramaQueryScreens(dpy, &scr->xine_count); scr->xine_screens = XineramaQueryScreens(dpy, &scr->xine_count);
#endif
scr->xine_primary_head = 0; scr->xine_primary_head = 0;
} }
/* int wGetRectPlacementInfo(WScreen *scr, WMRect rect, int *flags)
* 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)
{ {
if (rect1->x1 < rect2->x1) int best;
result->x1 = rect2->x1; unsigned long area, totalArea;
else int i;
result->x1 = rect1->x1; int rx = rect.pos.x;
int ry = rect.pos.y;
if (rect1->x2 > rect2->x2) int rw = rect.size.width;
result->x2 = rect2->x2; int rh = rect.size.height;
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;
return 1; wassertrv(flags!=NULL, 0);
}
best = -1;
area = 0;
totalArea = 0;
static int intersectArea(int x1, int y1, int w1, int h1, *flags = XFLAG_NONE;
int x2, int y2, int w2, int h2)
{ if (scr->xine_count <= 1) {
_Rectangle rect1, rect2, result; unsigned long a;
rect1.x1 = x1; a = calcIntersectionArea(rx, ry, rw, rh,
rect1.y1 = y1; 0, 0, scr->scr_width, scr->scr_height);
rect1.x2 = x1+w1;
rect1.y2 = y1+h1; if (a == 0) {
*flags |= XFLAG_DEAD;
rect2.x1 = x2; } else if (a != rw*rh) {
rect2.y1 = y2; *flags |= XFLAG_PARTIAL;
rect2.x2 = x2+w2; }
rect2.y2 = y2+h2;
return scr->xine_primary_head;
if (intersect_rectangles(&rect1, &rect2, &result)) }
return (result.x2-result.x1)*(result.y2-result.y1);
else #ifdef XINERAMA
return 0; 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 */ /* 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 rw = rect.size.width;
int rh = rect.size.height; int rh = rect.size.height;
if (!scr->xine_count)
return scr->xine_primary_head;
best = -1; best = -1;
area = 0; area = 0;
#ifdef XINERAMA
for (i = 0; i < scr->xine_count; i++) { for (i = 0; i < scr->xine_count; i++) {
unsigned long a; unsigned long a;
a = intersectArea(rx, ry, rw, rh, a = calcIntersectionArea(rx, ry, rw, rh,
scr->xine_screens[i].x_org, scr->xine_screens[i].x_org,
scr->xine_screens[i].y_org, scr->xine_screens[i].y_org,
scr->xine_screens[i].width, scr->xine_screens[i].width,
scr->xine_screens[i].height); scr->xine_screens[i].height);
if (a > area) { if (a > area) {
area = a; 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; 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; int i;
// paranoia
if ( flags == NULL) {
static int tmp;
flags = &tmp;
}
*flags = XFLAG_NONE;
for (i = 0; i < scr->xine_count; i++) { for (i = 0; i < scr->xine_count; i++) {
#if 0
int yy, xx; int yy, xx;
xx = scr->xine_screens[i].x_org + scr->xine_screens[i].width; 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) { point.x < xx && point.y < yy) {
return i; 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; 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) int wGetHeadForPointerLocation(WScreen *scr)
@@ -184,6 +233,8 @@ int wGetHeadForPointerLocation(WScreen *scr)
int ble; int ble;
unsigned int blo; unsigned int blo;
if (!scr->xine_count)
return scr->xine_primary_head;
if (!XQueryPointer(dpy, scr->root_win, &bla, &bla, if (!XQueryPointer(dpy, scr->root_win, &bla, &bla,
&point.x, &point.y, &point.x, &point.y,
@@ -200,12 +251,15 @@ wGetRectForHead(WScreen *scr, int head)
{ {
WMRect rect; WMRect rect;
#ifdef XINERAMA
if (head < scr->xine_count) { if (head < scr->xine_count) {
rect.pos.x = scr->xine_screens[head].x_org; rect.pos.x = scr->xine_screens[head].x_org;
rect.pos.y = scr->xine_screens[head].y_org; rect.pos.y = scr->xine_screens[head].y_org;
rect.size.width = scr->xine_screens[head].width; rect.size.width = scr->xine_screens[head].width;
rect.size.height = scr->xine_screens[head].height; rect.size.height = scr->xine_screens[head].height;
} else { } else
#endif /* XINERAMA */
{
rect.pos.x = 0; rect.pos.x = 0;
rect.pos.y = 0; rect.pos.y = 0;
rect.size.width = scr->scr_width; 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) { totalArea.x1 = rect.pos.x;
rect.pos.x = scr->xine_screens[head].x_org; totalArea.y1 = rect.pos.y;
rect.pos.y = scr->xine_screens[head].y_org; totalArea.x2 = totalArea.x1 + rect.size.width;
rect.size.width = scr->xine_screens[head].width; totalArea.y2 = totalArea.y1 + rect.size.height;
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;
}
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); 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 wGetHeadForRect(WScreen *scr, WMRect rect);
int wGetHeadForWindow(WWindow *wwin); int wGetHeadForWindow(WWindow *wwin);
@@ -39,7 +47,9 @@ int wGetHeadForPointerLocation(WScreen *scr);
WMRect wGetRectForHead(WScreen *scr, int head); 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 #endif

View File

@@ -40,6 +40,10 @@
#include "../src/config.h" #include "../src/config.h"
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#ifdef HAVE_DLFCN_H #ifdef HAVE_DLFCN_H
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
@@ -62,7 +66,12 @@ Window root;
int scr; int scr;
int scrWidth; int scrWidth;
int scrHeight; int scrHeight;
int scrX, scrY;
#ifdef XINERAMA
XineramaScreenInfo *xine_screens;
int xine_count;
#endif
Bool smooth = False; Bool smooth = False;
@@ -116,6 +125,86 @@ loadImage(RContext *rc, char *file)
} }
void applyImage( RContext * rc, BackgroundTexture *texture, RImage *image, char type, int x, int y, int width, int height) {
int w, h;
Bool fimage = False;
switch( toupper(type)) {
case 'S':
case 'M':
if ( type == 'S') {
w = width;
h = height;
} else {
if ( image->width*height > image->height*width) {
w = width;
h = (width*image->height) / image->width;
} else {
w = (height*image->width) / image->height;
h = height;
}
}
if ( w != image->width || h != image->height) {
RImage * simage;
if ( smooth) {
simage = RSmoothScaleImage( image, w, h);
} else {
simage = RScaleImage( image, w, h);
}
if ( !simage) {
wwarning( "could not scale image:%s", RMessageForError(RErrorCode));
return;
}
fimage = True;
image = simage;
}
/* fall through */
case 'C':
{
Pixmap pixmap;
if ( !RConvertImage(rc, image, &pixmap)) {
wwarning( "could not convert texture:%s", RMessageForError(RErrorCode));
return;
}
if ( image->width != width || image->height != height) {
int sx, sy, w, h;
if ( image->height < height) {
h = image->height;
y += (height - h) / 2;
sy = 0;
} else {
sy = (image->height - height) / 2;
h = height;
}
if ( image->width < width) {
w = image->width;
x += (width - w) / 2;
sx = 0;
} else {
sx = (image->width - width) / 2;
w = width;
}
XCopyArea(dpy, pixmap, texture->pixmap, DefaultGC(dpy, scr), sx, sy, w, h, x, y);
} else
XCopyArea(dpy, pixmap, texture->pixmap, DefaultGC(dpy, scr), 0, 0, width, height, x, y);
XFreePixmap(dpy, pixmap);
if ( fimage) RReleaseImage( image);
}
break;
}
}
BackgroundTexture* BackgroundTexture*
parseTexture(RContext *rc, char *text) parseTexture(RContext *rc, char *text)
{ {
@@ -404,6 +493,7 @@ parseTexture(RContext *rc, char *text)
break; break;
case 'S': case 'S':
case 'M': case 'M':
#if 0
if (toupper(type[0])=='S') { if (toupper(type[0])=='S') {
w = scrWidth; w = scrWidth;
h = scrHeight; h = scrHeight;
@@ -488,10 +578,37 @@ parseTexture(RContext *rc, char *text)
texture->height = scrHeight; texture->height = scrHeight;
} }
break; break;
#else
case 'C':
{
Pixmap tpixmap = XCreatePixmap( dpy, root, scrWidth, scrHeight, DefaultDepth(dpy, scr));
XFillRectangle(dpy, tpixmap, DefaultGC(dpy, scr), 0, 0, scrWidth, scrHeight);
texture->pixmap = tpixmap;
texture->color = color;
texture->width = scrWidth;
texture->height = scrHeight;
if ( xine_count) {
int i;
for ( i=0; i<xine_count; ++i) {
applyImage( rc, texture, image, type[0],
xine_screens[i].x_org, xine_screens[i].y_org,
xine_screens[i].width, xine_screens[i].height);
}
} else {
applyImage( rc, texture, image, type[0], 0, 0, scrWidth, scrHeight);
}
RReleaseImage( image);
}
break;
#endif
} }
#if 0
texture->pixmap = pixmap; texture->pixmap = pixmap;
texture->color = color; texture->color = color;
#endif
} else if (strcasecmp(type, "thgradient")==0 } else if (strcasecmp(type, "thgradient")==0
|| strcasecmp(type, "tvgradient")==0 || strcasecmp(type, "tvgradient")==0
|| strcasecmp(type, "tdgradient")==0) { || strcasecmp(type, "tdgradient")==0) {
@@ -1414,6 +1531,12 @@ main(int argc, char **argv)
scrWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); scrWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
scrHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); scrHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
scrX = scrY = 0;
#ifdef XINERAMA
xine_screens = XineramaQueryScreens(dpy, &xine_count);
#endif
if (!obey_user && DefaultDepth(dpy, scr) <= 8) if (!obey_user && DefaultDepth(dpy, scr) <= 8)
render_mode = RDitheredRendering; render_mode = RDitheredRendering;