merge 7773 from trunk
authorDana Jansens <danakj@orodu.net>
Wed, 11 Jul 2007 23:53:26 +0000 (23:53 +0000)
committerDana Jansens <danakj@orodu.net>
Wed, 11 Jul 2007 23:53:26 +0000 (23:53 +0000)
openbox/client.c
openbox/moveresize.c

index 1b5aff92e79ca732f09a5b9c7fa3b98bd4499554..071ecc4d7b262392bf25890e4965b3a6f3ede687 100644 (file)
@@ -88,7 +88,8 @@ static void client_update_transient_tree(ObClient *self,
                                          gboolean oldgtran, gboolean newgtran,
                                          ObClient* oldparent,
                                          ObClient *newparent);
-static void client_present(ObClient *self, gboolean here, gboolean raise);
+static void client_present(ObClient *self, gboolean here, gboolean raise,
+                           gboolean unshade);
 static GSList *client_search_all_top_parents_internal(ObClient *self,
                                                       gboolean bylayer,
                                                       ObStackingLayer layer);
@@ -547,7 +548,7 @@ void client_manage(Window window)
 
     if (activate) {
         gboolean stacked = client_restore_session_stacking(self);
-        client_present(self, FALSE, !stacked);
+        client_present(self, FALSE, !stacked, TRUE);
     }
 
     /* add to client list/map */
@@ -935,7 +936,7 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     frame_rect_to_frame(self->frame, &desired);
 
     /* get where the frame would be */
-    frame_client_gravity(self->frame, x, y, w, h);
+    frame_client_gravity(self->frame, x, y);
 
     /* get the requested size of the window with decorations */
     fw = self->frame->size.left + w + self->frame->size.right;
@@ -1023,7 +1024,7 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     }
 
     /* get where the client should be */
-    frame_frame_gravity(self->frame, x, y, w, h);
+    frame_frame_gravity(self->frame, x, y);
 
     return ox != *x || oy != *y;
 }
@@ -2683,7 +2684,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
     frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
 
     /* gets the frame's position */
-    frame_client_gravity(self->frame, x, y, *w, *h);
+    frame_client_gravity(self->frame, x, y);
 
     /* these positions are frame positions, not client positions */
 
@@ -2730,7 +2731,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
     }
 
     /* gets the client's position */
-    frame_frame_gravity(self->frame, x, y, *w, *h);
+    frame_frame_gravity(self->frame, x, y);
 
     /* work within the prefered sizes given by the window */
     if (!(*w == self->area.width && *h == self->area.height)) {
@@ -2865,9 +2866,6 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
     oldw = self->area.width;
     oldh = self->area.height;
     RECT_SET(self->area, x, y, w, h);
-    ob_debug("Client area %s set to %d %d %d %d\n",
-             self->title, self->area.x, self->area.y,
-             self->area.width, self->area.height);
 
     /* for app-requested resizes, always resize if 'resized' is true.
        for user-requested ones, only resize if final is true, or when
@@ -3549,6 +3547,10 @@ gboolean client_focus(ObClient *self)
                   "Focusing client \"%s\" (0x%x) at time %u\n",
                   self->title, self->window, event_curtime);
 
+    /* if using focus_delay, stop the timer now so that focus doesn't
+       go moving on us */
+    event_halt_focus_delay();
+
     /* if there is a grab going on, then we need to cancel it. if we move
        focus during the grab, applications will get NotifyWhileGrabbed events
        and ignore them !
@@ -3589,17 +3591,9 @@ gboolean client_focus(ObClient *self)
     return !xerror_occured;
 }
 
-/*! Present the client to the user.
-  @param raise If the client should be raised or not. You should only set
-               raise to false if you don't care if the window is completely
-               hidden.
-*/
-static void client_present(ObClient *self, gboolean here, gboolean raise)
+static void client_present(ObClient *self, gboolean here, gboolean raise,
+                           gboolean unshade)
 {
-    /* if using focus_delay, stop the timer now so that focus doesn't
-       go moving on us */
-    event_halt_focus_delay();
-
     if (client_normal(self) && screen_showing_desktop)
         screen_show_desktop(FALSE, self);
     if (self->iconic)
@@ -3615,7 +3609,7 @@ static void client_present(ObClient *self, gboolean here, gboolean raise)
         /* if its not visible for other reasons, then don't mess
            with it */
         return;
-    if (self->shaded)
+    if (self->shaded && unshade)
         client_shade(self, FALSE);
     if (raise)
         stacking_raise(CLIENT_AS_WINDOW(self));
@@ -3623,7 +3617,8 @@ static void client_present(ObClient *self, gboolean here, gboolean raise)
     client_focus(self);
 }
 
-void client_activate(ObClient *self, gboolean here, gboolean user)
+void client_activate(ObClient *self, gboolean here, gboolean raise,
+                     gboolean unshade, gboolean user)
 {
     guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
     gboolean allow = FALSE;
@@ -3649,7 +3644,7 @@ void client_activate(ObClient *self, gboolean here, gboolean user)
                   (user ? "user" : "application"), allow);
 
     if (allow)
-        client_present(self, here, TRUE);
+        client_present(self, here, raise, unshade);
     else
         /* don't focus it but tell the user it wants attention */
         client_hilite(self, TRUE);
@@ -3854,188 +3849,297 @@ ObClient *client_search_transient(ObClient *self, ObClient *search)
     return NULL;
 }
 
-#define WANT_EDGE(cur, c) \
-            if (cur == c)                                                     \
-                continue;                                                     \
-            if (c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL &&  \
-                cur->desktop != screen_desktop)                               \
-                continue;                                                     \
-            if (cur->iconic)                                                  \
-                continue;
-
-#define HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) \
-            if ((his_edge_start >= my_edge_start && \
-                 his_edge_start <= my_edge_end) ||  \
-                (my_edge_start >= his_edge_start && \
-                 my_edge_start <= his_edge_end))    \
-                dest = his_offset;
-
-/* finds the nearest edge in the given direction from the current client
- * note to self: the edge is the -frame- edge (the actual one), not the
- * client edge.
- */
-gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
-{
-    gint dest, monitor_dest;
-    gint my_edge_start, my_edge_end, my_offset;
+void client_find_edge_directional(ObClient *self, ObDirection dir,
+                                  gint my_head, gint my_size,
+                                  gint my_edge_start, gint my_edge_size,
+                                  gint *dest, gboolean *near_edge)
+{
     GList *it;
     Rect *a, *mon;
-    
-    if(!client_list)
-        return -1;
+    gint edge;
 
-    a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area);
-    mon = screen_area(c->desktop, SCREEN_AREA_ONE_MONITOR, &c->frame->area);
+    a = screen_area(self->desktop, SCREEN_AREA_ALL_MONITORS,
+                    &self->frame->area);
+    mon = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR,
+                      &self->frame->area);
 
     switch(dir) {
     case OB_DIRECTION_NORTH:
-        my_edge_start = c->frame->area.x;
-        my_edge_end = c->frame->area.x + c->frame->area.width;
-        my_offset = c->frame->area.y + (hang ? c->frame->area.height : 0);
-        
-        /* default: top of screen */
-        dest = a->y + (hang ? c->frame->area.height : 0);
-        monitor_dest = mon->y + (hang ? c->frame->area.height : 0);
-        /* if the monitor edge comes before the screen edge, */
-        /* use that as the destination instead. (For xinerama) */
-        if (monitor_dest != dest && my_offset > monitor_dest)
-            dest = monitor_dest; 
-
-        for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
-            gint his_edge_start, his_edge_end, his_offset;
-            ObClient *cur = it->data;
-
-            WANT_EDGE(cur, c)
-
-            his_edge_start = cur->frame->area.x;
-            his_edge_end = cur->frame->area.x + cur->frame->area.width;
-            his_offset = cur->frame->area.y + 
-                         (hang ? 0 : cur->frame->area.height);
-
-            if(his_offset + 1 > my_offset)
-                continue;
-
-            if(his_offset < dest)
-                continue;
-
-            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
-        }
+        if (my_head >= RECT_TOP(*mon))
+            edge = RECT_TOP(*mon) - 1;
+        else
+            edge = RECT_TOP(*a) - 1;
         break;
     case OB_DIRECTION_SOUTH:
-        my_edge_start = c->frame->area.x;
-        my_edge_end = c->frame->area.x + c->frame->area.width;
-        my_offset = c->frame->area.y + (hang ? 0 : c->frame->area.height);
-
-        /* default: bottom of screen */
-        dest = a->y + a->height - (hang ? c->frame->area.height : 0);
-        monitor_dest = mon->y + mon->height -
-                       (hang ? c->frame->area.height : 0);
-        /* if the monitor edge comes before the screen edge, */
-        /* use that as the destination instead. (For xinerama) */
-        if (monitor_dest != dest && my_offset < monitor_dest)
-            dest = monitor_dest; 
+        if (my_head <= RECT_BOTTOM(*mon))
+            edge = RECT_BOTTOM(*mon) + 1;
+        else
+            edge = RECT_BOTTOM(*a) + 1;
+        break;
+    case OB_DIRECTION_EAST:
+        if (my_head <= RECT_RIGHT(*mon))
+            edge = RECT_RIGHT(*mon) + 1;
+        else
+            edge = RECT_RIGHT(*a) + 1;
+        break;
+    case OB_DIRECTION_WEST:
+        if (my_head >= RECT_LEFT(*mon))
+            edge = RECT_LEFT(*mon) - 1;
+        else
+            edge = RECT_LEFT(*a) - 1;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    /* default to the far edge, then narrow it down */
+    *dest = edge;
+    *near_edge = TRUE;
 
-        for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
-            gint his_edge_start, his_edge_end, his_offset;
-            ObClient *cur = it->data;
+    for(it = client_list; it; it = g_list_next(it)) {
+        ObClient *cur = it->data;
+        gint edge_start, edge_size, head, tail;
+        gboolean skip_head = FALSE, skip_tail = FALSE;
 
-            WANT_EDGE(cur, c)
+        /* skip windows to not bump into */
+        if (cur == self)
+            continue;
+        if (cur->iconic)
+            continue;
+        if (self->desktop != cur->desktop && cur->desktop != DESKTOP_ALL &&
+            cur->desktop != screen_desktop)
+            continue;
 
-            his_edge_start = cur->frame->area.x;
-            his_edge_end = cur->frame->area.x + cur->frame->area.width;
-            his_offset = cur->frame->area.y +
-                         (hang ? cur->frame->area.height : 0);
+        ob_debug("trying window %s\n", cur->title);
 
+        switch(dir) {
+        case OB_DIRECTION_NORTH:
+        case OB_DIRECTION_SOUTH:
+            edge_start = cur->frame->area.x;
+            edge_size = cur->frame->area.width;
+            break;
+        case OB_DIRECTION_EAST:
+        case OB_DIRECTION_WEST:
+            edge_start = cur->frame->area.y;
+            edge_size = cur->frame->area.height;
+            break;
+        default:
+            g_assert_not_reached();
+        }
 
-            if(his_offset - 1 < my_offset)
-                continue;
-            
-            if(his_offset > dest)
-                continue;
+        /* do we collide with this window? */
+        if (!RANGES_INTERSECT(my_edge_start, my_edge_size,
+                              edge_start, edge_size))
+            continue;
 
-            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
+        switch(dir) {
+        case OB_DIRECTION_NORTH:
+            head = RECT_BOTTOM(cur->frame->area);
+            tail = RECT_TOP(cur->frame->area);
+            break;
+        case OB_DIRECTION_SOUTH:
+            head = RECT_TOP(cur->frame->area);
+            tail = RECT_BOTTOM(cur->frame->area);
+            break;
+        case OB_DIRECTION_EAST:
+            head = RECT_LEFT(cur->frame->area);
+            tail = RECT_RIGHT(cur->frame->area);
+            break;
+        case OB_DIRECTION_WEST:
+            head = RECT_RIGHT(cur->frame->area);
+            tail = RECT_LEFT(cur->frame->area);
+            break;
+        default:
+            g_assert_not_reached();
         }
-        break;
-    case OB_DIRECTION_WEST:
-        my_edge_start = c->frame->area.y;
-        my_edge_end = c->frame->area.y + c->frame->area.height;
-        my_offset = c->frame->area.x + (hang ? c->frame->area.width : 0);
 
-        /* default: leftmost egde of screen */
-        dest = a->x + (hang ? c->frame->area.width : 0);
-        monitor_dest = mon->x + (hang ? c->frame->area.width : 0);
-        /* if the monitor edge comes before the screen edge, */
-        /* use that as the destination instead. (For xinerama) */
-        if (monitor_dest != dest && my_offset > monitor_dest)
-            dest = monitor_dest;            
+        switch(dir) {
+        case OB_DIRECTION_NORTH:
+        case OB_DIRECTION_WEST:
+            if (my_head <= head + 1)
+                skip_head = TRUE;
+            if (my_head + my_size - 1 <= tail)
+                skip_tail = TRUE;
+            if (head < *dest)
+                skip_head = TRUE;
+            if (tail - my_size < *dest)
+                skip_tail = TRUE;
+            break;
+        case OB_DIRECTION_SOUTH:
+        case OB_DIRECTION_EAST:
+            if (my_head >= head - 1)
+                skip_head = TRUE;
+            if (my_head - my_size + 1 >= tail)
+                skip_tail = TRUE;
+            if (head > *dest)
+                skip_head = TRUE;
+            if (tail + my_size > *dest)
+                skip_tail = TRUE;
+            break;
+        default:
+            g_assert_not_reached();
+        }
 
-        for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
-            gint his_edge_start, his_edge_end, his_offset;
-            ObClient *cur = it->data;
+        ob_debug("my head %d size %d\n", my_head, my_size);
+        ob_debug("head %d tail %d deest %d\n", head, tail, *dest);
+        if (!skip_head) {
+            ob_debug("using near edge %d\n", head);
+            *dest = head;
+            *near_edge = TRUE;
+        }
+        else if (!skip_tail) {
+            ob_debug("using far edge %d\n", tail);
+            *dest = tail;
+            *near_edge = FALSE;
+        }
+    }
+}
 
-            WANT_EDGE(cur, c)
+void client_find_move_directional(ObClient *self, ObDirection dir,
+                                  gint *x, gint *y)
+{
+    gint head, size;
+    gint e, e_start, e_size;
+    gboolean near;
 
-            his_edge_start = cur->frame->area.y;
-            his_edge_end = cur->frame->area.y + cur->frame->area.height;
-            his_offset = cur->frame->area.x +
-                         (hang ? 0 : cur->frame->area.width);
+    switch (dir) {
+    case OB_DIRECTION_EAST:
+        head = RECT_RIGHT(self->frame->area);
+        size = self->frame->area.width;
+        e_start = RECT_TOP(self->frame->area);
+        e_size = self->frame->area.height;
+        break;
+    case OB_DIRECTION_WEST:
+        head = RECT_LEFT(self->frame->area);
+        size = self->frame->area.width;
+        e_start = RECT_TOP(self->frame->area);
+        e_size = self->frame->area.height;
+        break;
+    case OB_DIRECTION_NORTH:
+        head = RECT_TOP(self->frame->area);
+        size = self->frame->area.height;
+        e_start = RECT_LEFT(self->frame->area);
+        e_size = self->frame->area.width;
+        break;
+    case OB_DIRECTION_SOUTH:
+        head = RECT_BOTTOM(self->frame->area);
+        size = self->frame->area.height;
+        e_start = RECT_LEFT(self->frame->area);
+        e_size = self->frame->area.width;
+        break;
+    default:
+        g_assert_not_reached();
+    }
 
-            if(his_offset + 1 > my_offset)
-                continue;
+    client_find_edge_directional(self, dir, head, size,
+                                 e_start, e_size, &e, &near);
+    *x = self->frame->area.x;
+    *y = self->frame->area.y;
+    switch (dir) {
+    case OB_DIRECTION_EAST:
+        if (near) e -= self->frame->area.width;
+        else      e++;
+        *x = e;
+        break;
+    case OB_DIRECTION_WEST:
+        if (near) e++;
+        else      e -= self->frame->area.width;
+        *x = e;
+        break;
+    case OB_DIRECTION_NORTH:
+        if (near) e++;
+        else      e -= self->frame->area.height;
+        *y = e;
+        break;
+    case OB_DIRECTION_SOUTH:
+        if (near) e -= self->frame->area.height;
+        else      e++;
+        *y = e;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    frame_frame_gravity(self->frame, x, y);
+}
 
-            if(his_offset < dest)
-                continue;
+void client_find_resize_directional(ObClient *self, ObDirection side,
+                                    gboolean grow,
+                                    gint *x, gint *y, gint *w, gint *h)
+{
+    gint head;
+    gint e, e_start, e_size, delta;
+    gboolean near;
+    ObDirection dir;
 
-            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
-        }
-       break;
+    switch (side) {
     case OB_DIRECTION_EAST:
-        my_edge_start = c->frame->area.y;
-        my_edge_end = c->frame->area.y + c->frame->area.height;
-        my_offset = c->frame->area.x + (hang ? 0 : c->frame->area.width);
-        
-        /* default: rightmost edge of screen */
-        dest = a->x + a->width - (hang ? c->frame->area.width : 0);
-        monitor_dest = mon->x + mon->width -
-                       (hang ? c->frame->area.width : 0);
-        /* if the monitor edge comes before the screen edge, */
-        /* use that as the destination instead. (For xinerama) */
-        if (monitor_dest != dest && my_offset < monitor_dest)
-            dest = monitor_dest;            
-
-        for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
-            gint his_edge_start, his_edge_end, his_offset;
-            ObClient *cur = it->data;
-
-            WANT_EDGE(cur, c)
-
-            his_edge_start = cur->frame->area.y;
-            his_edge_end = cur->frame->area.y + cur->frame->area.height;
-            his_offset = cur->frame->area.x +
-                         (hang ? cur->frame->area.width : 0);
-
-            if(his_offset - 1 < my_offset)
-                continue;
-            
-            if(his_offset > dest)
-                continue;
-
-            HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
-        }
+        head = RECT_RIGHT(self->frame->area) +
+            (self->size_inc.width - 1) * (grow ? 1 : -1);
+        e_start = RECT_TOP(self->frame->area);
+        e_size = self->frame->area.height;
+        dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST;
+        break;
+    case OB_DIRECTION_WEST:
+        head = RECT_LEFT(self->frame->area) -
+            (self->size_inc.width - 1) * (grow ? 1 : -1);
+        e_start = RECT_TOP(self->frame->area);
+        e_size = self->frame->area.height;
+        dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST;
+        break;
+    case OB_DIRECTION_NORTH:
+        head = RECT_TOP(self->frame->area) -
+            (self->size_inc.height - 1) * (grow ? 1 : -1);
+        e_start = RECT_LEFT(self->frame->area);
+        e_size = self->frame->area.width;
+        dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH;
+        break;
+    case OB_DIRECTION_SOUTH:
+        head = RECT_BOTTOM(self->frame->area) +
+            (self->size_inc.height - 1) * (grow ? 1 : -1);
+        e_start = RECT_LEFT(self->frame->area);
+        e_size = self->frame->area.width;
+        dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH;
         break;
-    case OB_DIRECTION_NORTHEAST:
-    case OB_DIRECTION_SOUTHEAST:
-    case OB_DIRECTION_NORTHWEST:
-    case OB_DIRECTION_SOUTHWEST:
-        /* not implemented */
     default:
         g_assert_not_reached();
-        dest = 0; /* suppress warning */
     }
 
-    g_free(a);
-    g_free(mon);
-    return dest;
+    ob_debug("head %d dir %d\n", head, dir);
+    client_find_edge_directional(self, dir, head, 1,
+                                 e_start, e_size, &e, &near);
+    ob_debug("edge %d\n", e);
+    *x = self->frame->area.x;
+    *y = self->frame->area.y;
+    *w = self->frame->area.width;
+    *h = self->frame->area.height;
+    switch (side) {
+    case OB_DIRECTION_EAST:
+        if (grow == near) --e;
+        delta = e - RECT_RIGHT(self->frame->area);
+        *w += delta;
+        break;
+    case OB_DIRECTION_WEST:
+        if (grow == near) ++e;
+        delta = RECT_LEFT(self->frame->area) - e;
+        *x -= delta;
+        *w += delta;
+        break;
+    case OB_DIRECTION_NORTH:
+        if (grow == near) ++e;
+        delta = RECT_TOP(self->frame->area) - e;
+        *y -= delta;
+        *h += delta;
+        break;
+    case OB_DIRECTION_SOUTH:
+        if (grow == near) --e;
+        delta = e - RECT_BOTTOM(self->frame->area);
+        *h += delta;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    frame_frame_gravity(self->frame, x, y);
+    *w -= self->frame->size.left + self->frame->size.right;
+    *h -= self->frame->size.top + self->frame->size.bottom;
 }
 
 ObClient* client_under_pointer()
index 3d411a8dee8e422752c3b9fef1a45b6ed90669d4..9f1a9b04bbc787ff7e4de927d28a97f033a8946a 100644 (file)
@@ -26,6 +26,7 @@
 #include "openbox.h"
 #include "resist.h"
 #include "mainloop.h"
+#include "modkeys.h"
 #include "popup.h"
 #include "moveresize.h"
 #include "config.h"
@@ -39,7 +40,7 @@
 #include <glib.h>
 
 /* how far windows move and resize with the keyboard arrows */
-#define KEY_DIST 4
+#define KEY_DIST 8
 
 gboolean moveresize_in_progress = FALSE;
 ObClient *moveresize_client = NULL;
@@ -50,11 +51,12 @@ XSyncAlarm moveresize_alarm = None;
 static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
 
 static gint start_x, start_y, start_cx, start_cy, start_cw, start_ch;
-static gint cur_x, cur_y;
+static gint cur_x, cur_y, cur_w, cur_h;
 static guint button;
 static guint32 corner;
 static ObCorner lockcorner;
 static ObDirection edge_warp_dir = -1;
+static ObDirection key_resize_edge = -1;
 #ifdef SYNC
 static gboolean waiting_for_sync;
 #endif
@@ -63,6 +65,9 @@ static ObPopup *popup = NULL;
 
 static void do_edge_warp(gint x, gint y);
 static void cancel_edge_warp();
+#ifdef SYNC
+static gboolean sync_timeout_func(gpointer data);
+#endif
 
 static void client_dest(ObClient *client, gpointer data)
 {
@@ -91,50 +96,6 @@ void moveresize_shutdown(gboolean reconfig)
     popup = NULL;
 }
 
-static void get_resize_position(gint *x, gint *y, gboolean cancel)
-{
-    gint dw, dh;
-    gint w, h, lw, lh;
-
-    *x = moveresize_client->frame->area.x;
-    *y = moveresize_client->frame->area.y;
-
-    if (cancel) {
-        w = start_cw;
-        h = start_ch;
-    } else {
-        w = cur_x;
-        h = cur_y;
-    }
-
-    /* see how much it is actually going to resize */
-    {
-        gint cx = *x, cy = *y;
-        frame_frame_gravity(moveresize_client->frame, &cx, &cy, w, h);
-        client_try_configure(moveresize_client, &cx, &cy, &w, &h,
-                             &lw, &lh, TRUE);
-    }
-    dw = w - moveresize_client->area.width;
-    dh = h - moveresize_client->area.height;
-
-    switch (lockcorner) {
-    case OB_CORNER_TOPLEFT:
-        break;
-    case OB_CORNER_TOPRIGHT:
-        *x -= dw;
-        break;
-    case OB_CORNER_BOTTOMLEFT:
-        *y -= dh;
-        break;
-    case OB_CORNER_BOTTOMRIGHT:
-        *x -= dw;
-        *y -= dh;
-        break;
-    }
-
-    frame_frame_gravity(moveresize_client->frame, x, y, w, h);
-}
-
 static void popup_coords(ObClient *c, const gchar *format, gint a, gint b)
 {
     gchar *text;
@@ -206,17 +167,17 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
     moveresize_client = c;
     start_cx = c->area.x;
     start_cy = c->area.y;
+    start_cw = c->area.width;
+    start_ch = c->area.height;
     /* these adjustments for the size_inc make resizing a terminal more
        friendly. you essentially start the resize in the middle of the
        increment instead of at 0, so you have to move half an increment
-       either way instead of a full increment one and 1 px the other. and this
-       is one large mother fucking comment. */
-    start_cw = c->area.width + c->size_inc.width / 2;
-    start_ch = c->area.height + c->size_inc.height / 2;
-    start_x = x;
-    start_y = y;
+       either way instead of a full increment one and 1 px the other. */
+    start_x = x - c->size_inc.width / 2;
+    start_y = y - c->size_inc.height / 2;
     corner = cnr;
     button = b;
+    key_resize_edge = -1;
 
     /*
       have to change start_cx and start_cy if going to do this..
@@ -226,18 +187,15 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
                      c->area.width / 2, c->area.height / 2);
     */
 
-    if (moving) {
-        cur_x = start_cx;
-        cur_y = start_cy;
-    } else {
-        cur_x = start_cw;
-        cur_y = start_ch;
-    }
+    cur_x = start_cx;
+    cur_y = start_cy;
+    cur_w = start_cw;
+    cur_h = start_ch;
 
     moveresize_in_progress = TRUE;
 
 #ifdef SYNC
-    if (config_resize_redraw && !moving && extensions_shape &&
+    if (config_resize_redraw && !moving && extensions_sync &&
         moveresize_client->sync_request && moveresize_client->sync_counter)
     {
         /* Initialize values for the resize syncing, and create an alarm for
@@ -280,8 +238,6 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
 
 void moveresize_end(gboolean cancel)
 {
-    gint x, y;
-
     ungrab_keyboard();
     ungrab_pointer();
 
@@ -298,12 +254,15 @@ void moveresize_end(gboolean cancel)
             XSyncDestroyAlarm(ob_display, moveresize_alarm);
             moveresize_alarm = None;
         }
+
+        ob_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
 #endif
 
-        get_resize_position(&x, &y, cancel);
-        client_configure(moveresize_client, x, y,
-                         (cancel ? start_cw : cur_x),
-                         (cancel ? start_ch : cur_y),
+        client_configure(moveresize_client,
+                         (cancel ? start_cx : cur_x),
+                         (cancel ? start_cy : cur_y),
+                         (cancel ? start_cw : cur_w),
+                         (cancel ? start_ch : cur_h),
                          TRUE, TRUE, FALSE);
     }
 
@@ -314,19 +273,17 @@ void moveresize_end(gboolean cancel)
     moveresize_client = NULL;
 }
 
-static void do_move(gboolean keyboard)
+static void do_move(gboolean keyboard, gint keydist)
 {
     gint resist;
 
-    if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */
+    if (keyboard) resist = keydist - 1; /* resist for one key press */
     else resist = config_resist_win;
     resist_move_windows(moveresize_client, resist, &cur_x, &cur_y);
     if (!keyboard) resist = config_resist_edge;
     resist_move_monitors(moveresize_client, resist, &cur_x, &cur_y);
 
-    client_configure(moveresize_client, cur_x, cur_y,
-                     moveresize_client->area.width,
-                     moveresize_client->area.height,
+    client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
                      TRUE, FALSE, FALSE);
     if (config_resize_popup_show == 2) /* == "Always" */
         popup_coords(moveresize_client, "%d x %d",
@@ -334,6 +291,7 @@ static void do_move(gboolean keyboard)
                      moveresize_client->frame->area.y);
 }
 
+
 static void do_resize()
 {
     gint x, y, w, h, lw, lh;
@@ -341,8 +299,8 @@ static void do_resize()
     /* see if it is actually going to resize */
     x = 0;
     y = 0;
-    w = cur_x;
-    h = cur_y;
+    w = cur_w;
+    h = cur_h;
     client_try_configure(moveresize_client, &x, &y, &w, &h,
                          &lw, &lh, TRUE);
     if (w == moveresize_client->area.width &&
@@ -381,11 +339,16 @@ static void do_resize()
                    NoEventMask, &ce);
 
         waiting_for_sync = TRUE;
+
+        ob_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
+        ob_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2,
+                                 sync_timeout_func,
+                                 NULL, NULL, NULL);
     }
 #endif
 
-    get_resize_position(&x, &y, FALSE);
-    client_configure(moveresize_client, x, y, cur_x, cur_y, TRUE, FALSE, FALSE);
+    client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
+                     TRUE, FALSE, FALSE);
 
     /* this would be better with a fixed width font ... XXX can do it better
        if there are 2 text boxes */
@@ -398,26 +361,50 @@ static void do_resize()
                      moveresize_client->logical_size.height);
 }
 
-static void calc_resize(gboolean keyboard)
+#ifdef SYNC
+static gboolean sync_timeout_func(gpointer data)
+{
+    waiting_for_sync = FALSE; /* we timed out waiting for our sync... */
+    do_resize(); /* ...so let any pending resizes through */
+
+    return FALSE; /* don't repeat */
+}
+#endif
+
+static void calc_resize(gboolean keyboard, gint keydist, gint *dw, gint *dh,
+                        ObCorner cor)
 {
-    gint resist;
+    gint resist, x, y, lw, lh, ow, oh, nw, nh;
 
+    ow = cur_w;
+    oh = cur_h;
     /* resist_size_* needs the frame size */
-    cur_x += moveresize_client->frame->size.left +
+    nw = ow + *dw +
+        moveresize_client->frame->size.left +
         moveresize_client->frame->size.right;
-    cur_y += moveresize_client->frame->size.top +
+    nh = oh + *dh +
+        moveresize_client->frame->size.top +
         moveresize_client->frame->size.bottom;
 
-    if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */
+    if (keyboard) resist = keydist - 1; /* resist for one key press */
     else resist = config_resist_win;
-    resist_size_windows(moveresize_client, resist, &cur_x, &cur_y, lockcorner);
+    resist_size_windows(moveresize_client, resist, &nw, &nh, cor);
     if (!keyboard) resist = config_resist_edge;
-    resist_size_monitors(moveresize_client, resist, &cur_x, &cur_y,lockcorner);
+    resist_size_monitors(moveresize_client, resist, &nw, &nh, cor);
 
-    cur_x -= moveresize_client->frame->size.left +
+    nw -= moveresize_client->frame->size.left +
         moveresize_client->frame->size.right;
-    cur_y -= moveresize_client->frame->size.top +
+    nh -= moveresize_client->frame->size.top +
         moveresize_client->frame->size.bottom;
+
+    /* see its actual size */
+    x = 0;
+    y = 0;
+    client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh, TRUE);
+
+
+    *dw = nw - ow;
+    *dh = nh - oh;
 }
 
 static gboolean edge_warp_delay_func(gpointer data)
@@ -434,7 +421,7 @@ static gboolean edge_warp_delay_func(gpointer data)
 
 static void do_edge_warp(gint x, gint y)
 {
-    guint i, d;
+    guint i;
     ObDirection dir;
 
     if (!config_mouse_screenedgetime) return;
@@ -479,11 +466,228 @@ static void cancel_edge_warp()
     ob_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
 }
 
+static void move_with_keys(gint keycode, gint state)
+{
+    gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
+    gint opx, px, opy, py;
+    gint dist = 0;
+
+    /* shift means jump to edge */
+    if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
+        gint x, y;
+        ObDirection dir;
+
+        if (keycode == ob_keycode(OB_KEY_RIGHT))
+            dir = OB_DIRECTION_EAST;
+        else if (keycode == ob_keycode(OB_KEY_LEFT))
+            dir = OB_DIRECTION_WEST;
+        else if (keycode == ob_keycode(OB_KEY_DOWN))
+            dir = OB_DIRECTION_SOUTH;
+        else /* if (keycode == ob_keycode(OB_KEY_UP)) */
+            dir = OB_DIRECTION_NORTH;
+
+        client_find_move_directional(moveresize_client, dir, &x, &y);
+        dx = x - moveresize_client->area.x;
+        dy = y - moveresize_client->area.y;
+    } else {
+        /* control means fine grained */
+        if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
+            dist = 1;
+        else
+            dist = KEY_DIST;
+
+        if (keycode == ob_keycode(OB_KEY_RIGHT))
+            dx = dist;
+        else if (keycode == ob_keycode(OB_KEY_LEFT))
+            dx = -dist;
+        else if (keycode == ob_keycode(OB_KEY_DOWN))
+            dy = dist;
+        else /* if (keycode == ob_keycode(OB_KEY_UP)) */
+            dy = -dist;
+    }
+
+    screen_pointer_pos(&opx, &opy);
+    XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
+    /* steal the motion events this causes */
+    XSync(ob_display, FALSE);
+    {
+        XEvent ce;
+        while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
+    }
+    screen_pointer_pos(&px, &py);
+
+    cur_x += dx;
+    cur_y += dy;
+    do_move(TRUE, dist);
+
+    /* because the cursor moves even though the window does
+       not nessesarily (resistance), this adjusts where the curor
+       thinks it started so that it keeps up with where the window
+       actually is */
+    start_x += (px - opx) - (cur_x - ox);
+    start_y += (py - opy) - (cur_y - oy);
+}
+
+static void resize_with_keys(gint keycode, gint state)
+{
+    gint dw = 0, dh = 0, pdx = 0, pdy = 0, opx, opy, px, py;
+    gint dist = 0;
+    ObDirection dir;
+    ObCorner cor;
+
+    /* pick the edge if it needs to move */
+    if (keycode == ob_keycode(OB_KEY_RIGHT)) {
+        dir = OB_DIRECTION_EAST;
+        if (key_resize_edge != OB_DIRECTION_WEST &&
+            key_resize_edge != OB_DIRECTION_EAST)
+        {
+            key_resize_edge = OB_DIRECTION_EAST;
+            return;
+        }
+    }
+    if (keycode == ob_keycode(OB_KEY_LEFT)) {
+        dir = OB_DIRECTION_WEST;
+        if (key_resize_edge != OB_DIRECTION_WEST &&
+            key_resize_edge != OB_DIRECTION_EAST)
+        {
+            key_resize_edge = OB_DIRECTION_WEST;
+            return;
+        }
+    }
+    if (keycode == ob_keycode(OB_KEY_UP)) {
+        dir = OB_DIRECTION_NORTH;
+        if (key_resize_edge != OB_DIRECTION_NORTH &&
+            key_resize_edge != OB_DIRECTION_SOUTH)
+        {
+            key_resize_edge = OB_DIRECTION_NORTH;
+            return;
+        }
+    }
+    if (keycode == ob_keycode(OB_KEY_DOWN)) {
+        dir = OB_DIRECTION_SOUTH;
+        if (key_resize_edge != OB_DIRECTION_NORTH &&
+            key_resize_edge != OB_DIRECTION_SOUTH)
+        {
+            key_resize_edge = OB_DIRECTION_SOUTH;
+            return;
+        }
+    }
+
+    /* shift means jump to edge */
+    if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
+        gint x, y, w, h;
+
+        if (keycode == ob_keycode(OB_KEY_RIGHT))
+            dir = OB_DIRECTION_EAST;
+        else if (keycode == ob_keycode(OB_KEY_LEFT))
+            dir = OB_DIRECTION_WEST;
+        else if (keycode == ob_keycode(OB_KEY_DOWN))
+            dir = OB_DIRECTION_SOUTH;
+        else /* if (keycode == ob_keycode(OB_KEY_UP)) */
+            dir = OB_DIRECTION_NORTH;
+
+        client_find_resize_directional(moveresize_client, key_resize_edge,
+                                       key_resize_edge == dir,
+                                       &x, &y, &w, &h);
+        dw = w - moveresize_client->area.width;
+        dh = h - moveresize_client->area.height;
+    } else {
+        gint distw, disth;
+
+        /* control means fine grained */
+        if (moveresize_client->size_inc.width > 1)
+            distw = moveresize_client->size_inc.width;
+        else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
+            distw = 1;
+        else
+            distw = KEY_DIST;
+        if (moveresize_client->size_inc.height > 1)
+            disth = moveresize_client->size_inc.height;
+        else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
+            disth = 1;
+        else
+            disth = KEY_DIST;
+
+        if (key_resize_edge == OB_DIRECTION_WEST) {
+            if (dir == OB_DIRECTION_WEST)
+                dw = (dist = distw);
+            else
+                dw = -(dist = distw);
+        }
+        else if (key_resize_edge == OB_DIRECTION_EAST) {
+            if (dir == OB_DIRECTION_EAST)
+                dw = (dist = distw);
+            else
+                dw = -(dist = distw);
+        }
+        else if (key_resize_edge == OB_DIRECTION_NORTH) {
+            if (dir == OB_DIRECTION_NORTH)
+                dh = (dist = disth);
+            else
+                dh = -(dist = disth);
+        }
+        else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
+            if (dir == OB_DIRECTION_SOUTH)
+                dh = (dist = disth);
+            else
+                dh = -(dist = disth);
+        }
+    }
+
+    /* which corner is locked, for resistance */
+    if (key_resize_edge == OB_DIRECTION_WEST)
+        cor = OB_CORNER_TOPRIGHT;
+    else if (key_resize_edge == OB_DIRECTION_EAST)
+        cor = OB_CORNER_TOPLEFT;
+    else if (key_resize_edge == OB_DIRECTION_NORTH)
+        cor = OB_CORNER_BOTTOMLEFT;
+    else if (key_resize_edge == OB_DIRECTION_SOUTH)
+        cor = OB_CORNER_TOPLEFT;
+
+    calc_resize(TRUE, dist, &dw, &dh, cor);
+    if (key_resize_edge == OB_DIRECTION_WEST)
+        cur_x -= dw;
+    else if (key_resize_edge == OB_DIRECTION_NORTH)
+        cur_y -= dh;
+    cur_w += dw;
+    cur_h += dh;
+
+    /* how to move the pointer to keep up with the change */
+    if (key_resize_edge == OB_DIRECTION_WEST)
+        pdx = -dw;
+    else if (key_resize_edge == OB_DIRECTION_EAST)
+        pdx = dw;
+    else if (key_resize_edge == OB_DIRECTION_NORTH)
+        pdy = -dh;
+    else if (key_resize_edge == OB_DIRECTION_SOUTH)
+        pdy = dh;
+    
+    screen_pointer_pos(&opx, &opy);
+    XWarpPointer(ob_display, None, None, 0, 0, 0, 0, pdx, pdy);
+    /* steal the motion events this causes */
+    XSync(ob_display, FALSE);
+    {
+        XEvent ce;
+        while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
+    }
+    screen_pointer_pos(&px, &py);
+
+    do_resize();
+
+    /* because the cursor moves even though the window does
+       not nessesarily (resistance), this adjusts where the cursor
+       thinks it started so that it keeps up with where the window
+       actually is */
+    start_x += (px - opx) - dw;
+    start_y += (py - opy) - dh;
+
+}
+
 gboolean moveresize_event(XEvent *e)
 {
     gboolean used = FALSE;
 
-    g_assert(moveresize_in_progress);
+    if (!moveresize_in_progress) return FALSE;
 
     if (e->type == ButtonPress) {
         if (!button) {
@@ -501,51 +705,72 @@ gboolean moveresize_event(XEvent *e)
         if (moving) {
             cur_x = start_cx + e->xmotion.x_root - start_x;
             cur_y = start_cy + e->xmotion.y_root - start_y;
-            do_move(FALSE);
+            do_move(FALSE, 0);
             do_edge_warp(e->xmotion.x_root, e->xmotion.y_root);
         } else {
+            gint dw, dh;
+
             if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
-                cur_x = start_cw - (e->xmotion.x_root - start_x);
-                cur_y = start_ch - (e->xmotion.y_root - start_y);
+                dw = -(e->xmotion.x_root - start_x);
+                dh = -(e->xmotion.y_root - start_y);
                 lockcorner = OB_CORNER_BOTTOMRIGHT;
             } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
-                cur_x = start_cw;
-                cur_y = start_ch - (e->xmotion.y_root - start_y);
+                dw = 0;
+                dh = -(e->xmotion.y_root - start_y);
                 lockcorner = OB_CORNER_BOTTOMRIGHT;
             } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
-                cur_x = start_cw + (e->xmotion.x_root - start_x);
-                cur_y = start_ch - (e->xmotion.y_root - start_y);
+                dw = (e->xmotion.x_root - start_x);
+                dh = -(e->xmotion.y_root - start_y);
                 lockcorner = OB_CORNER_BOTTOMLEFT;
             } else if (corner == prop_atoms.net_wm_moveresize_size_right) { 
-                cur_x = start_cw + (e->xmotion.x_root - start_x);
-                cur_y = start_ch;
+                dw = (e->xmotion.x_root - start_x);
+                dh = 0;
                 lockcorner = OB_CORNER_BOTTOMLEFT;
             } else if (corner ==
                        prop_atoms.net_wm_moveresize_size_bottomright) {
-                cur_x = start_cw + (e->xmotion.x_root - start_x);
-                cur_y = start_ch + (e->xmotion.y_root - start_y);
+                dw = (e->xmotion.x_root - start_x);
+                dh = (e->xmotion.y_root - start_y);
                 lockcorner = OB_CORNER_TOPLEFT;
             } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
-                cur_x = start_cw;
-                cur_y = start_ch + (e->xmotion.y_root - start_y);
+                dw = 0;
+                dh = (e->xmotion.y_root - start_y);
                 lockcorner = OB_CORNER_TOPLEFT;
             } else if (corner ==
                        prop_atoms.net_wm_moveresize_size_bottomleft) {
-                cur_x = start_cw - (e->xmotion.x_root - start_x);
-                cur_y = start_ch + (e->xmotion.y_root - start_y);
+                dw = -(e->xmotion.x_root - start_x);
+                dh = (e->xmotion.y_root - start_y);
                 lockcorner = OB_CORNER_TOPRIGHT;
             } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
-                cur_x = start_cw - (e->xmotion.x_root - start_x);
-                cur_y = start_ch;
+                dw = -(e->xmotion.x_root - start_x);
+                dh = 0;
                 lockcorner = OB_CORNER_TOPRIGHT;
             } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
-                cur_x = start_cw + (e->xmotion.x_root - start_x);
-                cur_y = start_ch + (e->xmotion.y_root - start_y);
+                dw = (e->xmotion.x_root - start_x);
+                dh = (e->xmotion.y_root - start_y);
                 lockcorner = OB_CORNER_TOPLEFT;
             } else
                 g_assert_not_reached();
 
-            calc_resize(FALSE);
+            dw -= cur_w - start_cw;
+            dh -= cur_h - start_ch;
+
+            calc_resize(FALSE, 0, &dw, &dh, lockcorner);
+            cur_w += dw;
+            cur_h += dh;
+
+            if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
+                corner == prop_atoms.net_wm_moveresize_size_left ||
+                corner == prop_atoms.net_wm_moveresize_size_bottomleft)
+            {
+                cur_x -= dw;
+            }
+            if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
+                corner == prop_atoms.net_wm_moveresize_size_top ||
+                corner == prop_atoms.net_wm_moveresize_size_topright)
+            {
+                cur_y -= dh;
+            }
+
             do_resize();
         }
         used = TRUE;
@@ -562,72 +787,10 @@ gboolean moveresize_event(XEvent *e)
                    e->xkey.keycode == ob_keycode(OB_KEY_UP))
         {
             if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
-                gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
-
-                if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
-                    dx = MAX(KEY_DIST, moveresize_client->size_inc.width);
-                else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
-                    dx = -MAX(KEY_DIST, moveresize_client->size_inc.width);
-                else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
-                    dy = MAX(KEY_DIST, moveresize_client->size_inc.height);
-                else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */
-                    dy = -MAX(KEY_DIST, moveresize_client->size_inc.height);
-
-                cur_x += dx;
-                cur_y += dy;
-                XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
-                /* steal the motion events this causes */
-                XSync(ob_display, FALSE);
-                {
-                    XEvent ce;
-                    while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
-                }
-
-                calc_resize(TRUE);
-                do_resize();
-
-                /* because the cursor moves even though the window does
-                   not nessesarily (resistance), this adjusts where the curor
-                   thinks it started so that it keeps up with where the window
-                   actually is */
-                start_x += dx - (cur_x - ox);
-                start_y += dy - (cur_y - oy);
-
+                resize_with_keys(e->xkey.keycode, e->xkey.state);
                 used = TRUE;
             } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
-                gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
-                gint opx, px, opy, py;
-
-                if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
-                    dx = KEY_DIST;
-                else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
-                    dx = -KEY_DIST;
-                else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
-                    dy = KEY_DIST;
-                else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */
-                    dy = -KEY_DIST;
-
-                cur_x += dx;
-                cur_y += dy;
-                screen_pointer_pos(&opx, &opy);
-                XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
-                /* steal the motion events this causes */
-                XSync(ob_display, FALSE);
-                {
-                    XEvent ce;
-                    while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
-                }
-                screen_pointer_pos(&px, &py);
-
-                do_move(TRUE);
-
-                /* because the cursor moves even though the window does
-                   not nessesarily (resistance), this adjusts where the curor
-                   thinks it started so that it keeps up with where the window
-                   actually is */
-                start_x += (px - opx) - (cur_x - ox);
-                start_y += (py - opy) - (cur_y - oy);
-
+                move_with_keys(e->xkey.keycode, e->xkey.state);
                 used = TRUE;
             }
         }