[calmwm.h, conf.c, mousefunc.c, parse.y]
When a window is being moved with the mouse, if the window comes within
SNAPDIST pixels of the screen's edge -- snap the window to the screen's
edge.
[kbfunc.c]
Suppose moveamount=1, then bigmoveamount=10. The window is 3 pixels
away from the screen's edge. If the window is moved by bigmoveamount
toward the screen edge, then it will align itself perfectly along the
screen's edge, i.e. travel only 3 pixels, instead of 10. Subsequent
moves don't have any special behaviour. Works both ways: when moving a
window from beyond the screen to within and vice versa.
[menu.c]
Bugfix: the menu code ignores the fact that it might be on a multi-head
configuration, where screens are configured to be atop of each other,
e.g. xrandr --output LVDS --primary --auto xrandr --output TMDS-1
--above LVDS --auto In this case when a menu containing a lot of
entries is opened, it will span both screens, which is quite annoying
and contradicts cwm's behaviour regarding placing new windows and
window maximization.
[menu.c]
Don't move the pointer when resizing the menu. Reasoning: I already
have my pointer right where I want it to be, thank you very much. For
example, hovering above a certain control of a program that I'm about
to launch.
[screen.c]
Fix screen_find_xinerama(). For example, pixel (0,0) belongs to the
top-left-most screen.
Index: calmwm.h
===================================================================
RCS file: /OpenBSD/xenocara/app/cwm/calmwm.h,v
retrieving revision 1.118
diff -u -r1.118 calmwm.h
--- calmwm.h 22 May 2010 22:10:31 -0000 1.118
+++ calmwm.h 16 Mar 2011 20:16:33 -0000
@@ -287,10 +287,12 @@
#define CONF_STICKY_GROUPS 0x0001
int flags;
-#define CONF_BWIDTH 1
+#define CONF_BWIDTH 1
int bwidth;
#define CONF_MAMOUNT 1
int mamount;
+#define CONF_SNAPDIST 12
+ int snapdist;
struct gap gap;
#define CONF_COLOR_ACTIVEBORDER "#CCCCCC"
Index: conf.c
===================================================================
RCS file: /OpenBSD/xenocara/app/cwm/conf.c,v
retrieving revision 1.76
diff -u -r1.76 conf.c
--- conf.c 27 Jan 2010 03:04:50 -0000 1.76
+++ conf.c 16 Mar 2011 20:16:33 -0000
@@ -184,6 +184,7 @@
c->flags = 0;
c->bwidth = CONF_BWIDTH;
c->mamount = CONF_MAMOUNT;
+ c->snapdist = CONF_SNAPDIST;
TAILQ_INIT(&c->ignoreq);
TAILQ_INIT(&c->cmdq);
Index: kbfunc.c
===================================================================
RCS file: /OpenBSD/xenocara/app/cwm/kbfunc.c,v
retrieving revision 1.51
diff -u -r1.51 kbfunc.c
--- kbfunc.c 10 Feb 2010 01:23:05 -0000 1.51
+++ kbfunc.c 16 Mar 2011 20:16:33 -0000
@@ -55,8 +55,11 @@
kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
{
struct screen_ctx *sc;
- int x, y, flags, amt;
+ int x, y, right, bottom, bwidth2, flags, amt;
+ int old_x, old_y, old_right, old_bottom;
+ int xmin, ymin, xmax, ymax;
u_int mx, my;
+ XineramaScreenInfo *xine;
sc = cc->sc;
mx = my = 0;
@@ -69,6 +72,20 @@
amt = amt * 10;
}
+ xine = screen_find_xinerama(sc,
+ cc->geom.x + cc->geom.width/2, cc->geom.y + cc->geom.height/2);
+ if (xine) {
+ xmin = xine->x_org;
+ ymin = xine->y_org;
+ xmax = xine->x_org + xine->width;
+ ymax = xine->y_org + xine->height;
+ } else {
+ xmin = 0;
+ ymin = 0;
+ xmax = sc->xmax;
+ ymax = sc->ymax;
+ }
+
switch (flags & movemask) {
case CWM_UP:
my -= amt;
@@ -85,22 +102,47 @@
}
switch (flags & typemask) {
case CWM_MOVE:
- cc->geom.y += my;
+ bwidth2 = cc->bwidth * 2;
+
+ old_y = cc->geom.y;
+ old_bottom = old_y + cc->geom.height + bwidth2;
+ old_x = cc->geom.x;
+ old_right = old_x + cc->geom.width + bwidth2;
+
+ y = cc->geom.y + my;
+ bottom = y + cc->geom.height + bwidth2;
+ x = cc->geom.x + mx;
+ right = x + cc->geom.width + bwidth2;
+
+ if (abs(ymin - old_y) < abs(my) && abs(ymin - y) < abs(my))
+ y = ymin;
+ else if (abs(ymax - old_bottom) < abs(my)
+ && abs(ymax - bottom) < abs(my))
+ y = ymax - cc->geom.height - bwidth2;
+
+ if (abs(xmin - old_x) < abs(mx) && abs(xmin - x) < abs(mx))
+ x = xmin;
+ else if (abs(xmax - old_right) < abs(mx)
+ && abs(xmax - right) < abs(mx))
+ x = xmax - cc->geom.width - bwidth2;
+
+ cc->geom.y = y;
+ cc->geom.x = x;
+
if (cc->geom.y + cc->geom.height < 0)
cc->geom.y = -cc->geom.height;
if (cc->geom.y > cc->sc->ymax - 1)
cc->geom.y = cc->sc->ymax - 1;
- cc->geom.x += mx;
if (cc->geom.x + cc->geom.width < 0)
cc->geom.x = -cc->geom.width;
if (cc->geom.x > cc->sc->xmax - 1)
cc->geom.x = cc->sc->xmax - 1;
client_move(cc);
- xu_ptr_getpos(cc->win, &x, &y);
- cc->ptr.y = y + my;
- cc->ptr.x = x + mx;
+ xu_ptr_getpos(cc->win, &cc->ptr.x, &cc->ptr.y);
+ cc->ptr.x += x - old_x;
+ cc->ptr.y += y - old_y;
client_ptrwarp(cc);
break;
case CWM_RESIZE:
Index: menu.c
===================================================================
RCS file: /OpenBSD/xenocara/app/cwm/menu.c,v
retrieving revision 1.20
diff -u -r1.20 menu.c
--- menu.c 10 Feb 2010 01:23:05 -0000 1.20
+++ menu.c 16 Mar 2011 20:16:33 -0000
@@ -43,8 +43,8 @@
int entry;
int width;
int num;
- int x;
- int y;
+ int want_x;
+ int want_y;
void (*match)(struct menu_q *, struct menu_q *, char *);
void (*print)(struct menu *, int);
};
@@ -94,7 +94,7 @@
bzero(&mc, sizeof(mc));
- xu_ptr_getpos(sc->rootwin, &mc.x, &mc.y);
+ xu_ptr_getpos(sc->rootwin, &mc.want_x, &mc.want_y);
if (prompt == NULL) {
evmask = MenuMask;
@@ -119,7 +119,7 @@
mc.print = print;
mc.entry = mc.prev = -1;
- XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, mc.width,
+ XMoveResizeWindow(X_Dpy, sc->menuwin, mc.want_x, mc.want_y, mc.width,
font_height(sc));
XSelectInput(X_Dpy, sc->menuwin, evmask);
XMapRaised(X_Dpy, sc->menuwin);
@@ -271,8 +271,11 @@
menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
struct menu_q *resultq)
{
- struct menu *mi;
- int n, dy, xsave, ysave;
+ struct menu *mi;
+ int n, dy;
+ int x, y;
+ int xmin, ymin, xmax, ymax;
+ XineramaScreenInfo *xine;
if (mc->list) {
if (TAILQ_EMPTY(resultq) && mc->list) {
@@ -314,24 +317,35 @@
mc->num++;
}
- xsave = mc->x;
- ysave = mc->y;
- if (mc->x < 0)
- mc->x = 0;
- else if (mc->x + mc->width >= sc->xmax)
- mc->x = sc->xmax - mc->width;
-
- if (mc->y + dy >= sc->ymax)
- mc->y = sc->ymax - dy;
- /* never hide the top of the menu */
- if (mc->y < 0)
- mc->y = 0;
+ xine = screen_find_xinerama(sc, mc->want_x, mc->want_y);
+ if (xine) {
+ xmin = xine->x_org;
+ ymin = xine->y_org;
+ xmax = xine->x_org + xine->width;
+ ymax = xine->y_org + xine->height;
+ } else {
+ xmin = 0;
+ ymin = 0;
+ xmax = sc->xmax;
+ ymax = sc->ymax;
+ }
+
+ x = mc->want_x;
+ y = mc->want_y;
- if (mc->x != xsave || mc->y != ysave)
- xu_ptr_setpos(sc->rootwin, mc->x, mc->y);
+ if (x + mc->width >= xmax)
+ x = xmax - mc->width;
+ if (x < xmin)
+ x = xmin;
+ if (dy > (ymax - ymin))
+ dy = ymax - ymin;
+ if (y + dy >= ymax)
+ y = ymax - dy;
+ if (y < ymin)
+ y = ymin;
XClearWindow(X_Dpy, sc->menuwin);
- XMoveResizeWindow(X_Dpy, sc->menuwin, mc->x, mc->y, mc->width, dy);
+ XMoveResizeWindow(X_Dpy, sc->menuwin, x, y, mc->width, dy);
if (mc->hasprompt) {
font_draw(sc, mc->dispstr, strlen(mc->dispstr), sc->menuwin,
Index: mousefunc.c
===================================================================
RCS file: /OpenBSD/xenocara/app/cwm/mousefunc.c,v
retrieving revision 1.20
diff -u -r1.20 mousefunc.c
--- mousefunc.c 14 Dec 2010 11:08:47 -0000 1.20
+++ mousefunc.c 16 Mar 2011 20:16:33 -0000
@@ -138,9 +138,13 @@
void
mousefunc_window_move(struct client_ctx *cc, void *arg)
{
+ struct screen_ctx *sc = cc->sc;
XEvent ev;
Time time = 0;
- int px, py;
+ int x, y, right, bottom, px, py, bwidth2;
+ int xmin, ymin, xmax, ymax;
+ int snapdist;
+ XineramaScreenInfo *xine;
client_raise(cc);
@@ -149,6 +153,9 @@
xu_ptr_getpos(cc->win, &px, &py);
+ snapdist = Conf.snapdist;
+ bwidth2 = cc->bwidth * 2;
+
for (;;) {
XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
@@ -157,8 +164,38 @@
client_draw_border(cc);
break;
case MotionNotify:
- cc->geom.x = ev.xmotion.x_root - px - cc->bwidth;
- cc->geom.y = ev.xmotion.y_root - py - cc->bwidth;
+ xine = screen_find_xinerama(cc->sc,
+ cc->geom.x + cc->geom.width/2,
+ cc->geom.y + cc->geom.height/2);
+ if (xine) {
+ xmin = xine->x_org;
+ ymin = xine->y_org;
+ xmax = xine->x_org + xine->width;
+ ymax = xine->y_org + xine->height;
+ } else {
+ xmin = 0;
+ ymin = 0;
+ xmax = sc->xmax;
+ ymax = sc->ymax;
+ }
+
+ x = ev.xmotion.x_root - px - cc->bwidth;
+ y = ev.xmotion.y_root - py - cc->bwidth;
+ right = x + cc->geom.width + bwidth2;
+ bottom = y + cc->geom.height + bwidth2;
+
+ if (abs(xmin - x) < snapdist)
+ x = xmin;
+ else if (abs(xmax - right) < snapdist)
+ x = xmax - cc->geom.width - bwidth2;
+
+ if (abs(ymin - y) < snapdist)
+ y = ymin;
+ else if (abs(ymax - bottom) < snapdist)
+ y = ymax - cc->geom.height - bwidth2;
+
+ cc->geom.x = x;
+ cc->geom.y = y;
/* don't sync more than 60 times / second */
if ((ev.xmotion.time - time) > (1000 / 60)) {
Index: parse.y
===================================================================
RCS file: /OpenBSD/xenocara/app/cwm/parse.y,v
retrieving revision 1.26
diff -u -r1.26 parse.y
--- parse.y 25 Sep 2010 20:02:58 -0000 1.26
+++ parse.y 16 Mar 2011 20:16:33 -0000
@@ -69,7 +69,7 @@
%token FONTNAME STICKY GAP MOUSEBIND
%token AUTOGROUP BIND COMMAND IGNORE
-%token YES NO BORDERWIDTH MOVEAMOUNT
+%token YES NO BORDERWIDTH MOVEAMOUNT SNAPDIST
%token COLOR
%token ACTIVEBORDER INACTIVEBORDER
%token GROUPBORDER UNGROUPBORDER
@@ -120,6 +120,9 @@
| MOVEAMOUNT NUMBER {
conf->mamount = $2;
}
+ | SNAPDIST NUMBER {
+ conf->snapdist = $2;
+ }
| COMMAND STRING string {
conf_cmd_add(conf, $3, $2, 0);
free($2);
@@ -228,6 +231,7 @@
{ "mousebind", MOUSEBIND},
{ "moveamount", MOVEAMOUNT},
{ "no", NO},
+ { "snapdist", SNAPDIST},
{ "sticky", STICKY},
{ "ungroupborder", UNGROUPBORDER},
{ "yes", YES}
@@ -523,6 +527,7 @@
xconf->flags = conf->flags;
xconf->bwidth = conf->bwidth;
xconf->mamount = conf->mamount;
+ xconf->snapdist = conf->snapdist;
xconf->gap = conf->gap;
while ((cmd = TAILQ_FIRST(&conf->cmdq)) != NULL) {
Index: screen.c
===================================================================
RCS file: /OpenBSD/xenocara/app/cwm/screen.c,v
retrieving revision 1.26
diff -u -r1.26 screen.c
--- screen.c 27 Jan 2010 03:04:50 -0000 1.26
+++ screen.c 16 Mar 2011 20:16:33 -0000
@@ -101,8 +101,8 @@
for (i = 0; i < sc->xinerama_no; i++) {
info = &sc->xinerama[i];
- if (x > info->x_org && x < info->x_org + info->width &&
- y > info->y_org && y < info->y_org + info->height)
+ if (x >= info->x_org && x < info->x_org + info->width &&
+ y >= info->y_org && y < info->y_org + info->height)
return (info);
}
return (NULL);