[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);

Reply via email to