[Xfce4-commits] <xfwm4:master> Add tiling feature (bug #6648)

Olivier Fourdan noreply at xfce.org
Mon Feb 13 09:18:01 CET 2012


Updating branch refs/heads/master
         to 7727187a768f73d8d3647d28dfa7057b7a3e4288 (commit)
       from 2597c6529e0ff877da7065bedd5cbcc2d9facb70 (commit)

commit 7727187a768f73d8d3647d28dfa7057b7a3e4288
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Mon Feb 13 09:16:03 2012 +0100

    Add tiling feature (bug #6648)

 settings-dialogs/xfwm4-settings.c |    4 +
 src/client.c                      |  166 +++++++++++++++---
 src/client.h                      |   15 ++
 src/events.c                      |   19 ++-
 src/moveresize.c                  |  360 +++++++++++++++++++++++--------------
 src/settings.c                    |    4 +
 src/settings.h                    |    4 +
 7 files changed, 408 insertions(+), 164 deletions(-)

diff --git a/settings-dialogs/xfwm4-settings.c b/settings-dialogs/xfwm4-settings.c
index 4528099..49f45b2 100644
--- a/settings-dialogs/xfwm4-settings.c
+++ b/settings-dialogs/xfwm4-settings.c
@@ -278,6 +278,10 @@ static const ShortcutTemplate shortcut_values[] = {
   { N_("Move window to workspace 10"), "move_window_workspace_10_key", NULL, },
   { N_("Move window to workspace 11"), "move_window_workspace_11_key", NULL, },
   { N_("Move window to workspace 12"), "move_window_workspace_12_key", NULL, },
+  { N_("Tile window to the top"), "tile_up_key", NULL, },
+  { N_("Tile window to the bottom"), "tile_down_key", NULL, },
+  { N_("Tile window to the left"), "tile_left_key", NULL, },
+  { N_("Tile window to the right"), "tile_right_key", NULL, },
   { N_("Show desktop"), "show_desktop_key", NULL },
   { N_("Upper workspace"), "up_workspace_key", NULL },
   { N_("Bottom workspace"), "down_workspace_key", NULL },
diff --git a/src/client.c b/src/client.c
index 1eb4e59..1149cb2 100644
--- a/src/client.c
+++ b/src/client.c
@@ -108,7 +108,7 @@ struct _ButtonPressData
 static void
 clientUpdateIconPix (Client * c);
 static void
-clientNewMaxSize (Client * c, XWindowChanges *wc);
+clientNewMaxSize (Client * c, XWindowChanges *wc, GdkRectangle *, tilePositionType tile);
 
 Display *
 clientGetXDisplay (Client * c)
@@ -980,7 +980,11 @@ clientGetMWMHints (Client * c, gboolean update)
         /* If client is maximized, we need to update its coordonates and size as well */
         if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
         {
-            clientNewMaxSize (c, &wc);
+            GdkRectangle rect;
+            myScreenFindMonitorAtPoint (screen_info,
+                                        frameX (c) + (frameWidth (c) / 2),
+                                        frameY (c) + (frameHeight (c) / 2), &rect);
+            clientNewMaxSize (c, &wc, &rect, TILE_NONE);
         }
 
         clientConfigure (c, &wc, CWX | CWY | CWWidth | CWHeight, CFG_FORCE_REDRAW);
@@ -3029,7 +3033,7 @@ clientRemoveMaximizeFlag (Client * c)
 static void
 clientNewMaxState (Client * c, XWindowChanges *wc, int mode)
 {
-    if (mode & CLIENT_FLAG_MAXIMIZED_HORIZ)
+    if (FLAG_TEST (mode, CLIENT_FLAG_MAXIMIZED_HORIZ))
     {
         if (!FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ))
         {
@@ -3039,11 +3043,13 @@ clientNewMaxState (Client * c, XWindowChanges *wc, int mode)
         {
             FLAG_UNSET (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ);
             wc->x = c->old_x;
+            wc->y = c->old_y;
             wc->width = c->old_width;
+            wc->height = c->old_height;
         }
     }
 
-    if (mode & CLIENT_FLAG_MAXIMIZED_VERT)
+    if (FLAG_TEST (mode, CLIENT_FLAG_MAXIMIZED_VERT))
     {
         if (!FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_VERT))
         {
@@ -3052,38 +3058,33 @@ clientNewMaxState (Client * c, XWindowChanges *wc, int mode)
         else
         {
             FLAG_UNSET (c->flags, CLIENT_FLAG_MAXIMIZED_VERT);
+            wc->x = c->old_x;
             wc->y = c->old_y;
+            wc->width = c->old_width;
             wc->height = c->old_height;
         }
     }
 }
 
 static void
-clientNewMaxSize (Client * c, XWindowChanges *wc)
+clientNewMaxSize (Client * c, XWindowChanges *wc, GdkRectangle *rect, tilePositionType tile)
 {
     ScreenInfo *screen_info;
-    GdkRectangle rect;
-    int cx, cy, full_x, full_y, full_w, full_h;
+    int full_x, full_y, full_w, full_h;
     int tmp_x, tmp_y, tmp_w, tmp_h;
 
     tmp_x = frameX (c);
     tmp_y = frameY (c);
     tmp_h = frameHeight (c);
     tmp_w = frameWidth (c);
-
-    cx = tmp_x + (tmp_w / 2);
-    cy = tmp_y + (tmp_h / 2);
-
     screen_info = c->screen_info;
 
-    myScreenFindMonitorAtPoint (screen_info, cx, cy, &rect);
-
-    full_x = MAX (screen_info->params->xfwm_margins[STRUTS_LEFT], rect.x);
-    full_y = MAX (screen_info->params->xfwm_margins[STRUTS_TOP], rect.y);
+    full_x = MAX (screen_info->params->xfwm_margins[STRUTS_LEFT], rect->x);
+    full_y = MAX (screen_info->params->xfwm_margins[STRUTS_TOP], rect->y);
     full_w = MIN (screen_info->width - screen_info->params->xfwm_margins[STRUTS_RIGHT],
-                  rect.x + rect.width) - full_x;
+                  rect->x + rect->width) - full_x;
     full_h = MIN (screen_info->height - screen_info->params->xfwm_margins[STRUTS_BOTTOM],
-                  rect.y + rect.height) - full_y;
+                  rect->y + rect->height) - full_y;
 
     if (FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED))
     {
@@ -3100,7 +3101,27 @@ clientNewMaxSize (Client * c, XWindowChanges *wc)
     if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ))
     {
         /* Adjust size to the widest size available, for the current vertical position/height */
-        clientMaxSpace (screen_info, &full_x, &tmp_y, &full_w, &tmp_h);
+        switch (tile)
+        {
+            case TILE_UP:
+                tmp_h = full_h / 2;
+                tmp_y = full_y;
+                clientMaxSpace (screen_info, &full_x, &tmp_y, &full_w, &tmp_h);
+                wc->y = tmp_y + frameTop (c);
+                wc->height = tmp_h - frameTop (c) - frameBottom (c);
+                break;
+            case TILE_DOWN:
+                tmp_h = full_h / 2;
+                tmp_y = full_y + full_h / 2;
+                clientMaxSpace (screen_info, &full_x, &tmp_y, &full_w, &tmp_h);
+                wc->y = tmp_y + frameTop (c);
+                wc->height = tmp_h - frameTop (c) - frameBottom (c);
+                break;
+            default:
+                clientMaxSpace (screen_info, &full_x, &tmp_y, &full_w, &tmp_h);
+                break;
+        }
+
         wc->x = full_x + frameLeft (c);
         wc->width = full_w - frameLeft (c) - frameRight (c);
 
@@ -3110,7 +3131,27 @@ clientNewMaxSize (Client * c, XWindowChanges *wc)
     if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_VERT))
     {
         /* Adjust size to the tallest size available, for the current horizontal position/width */
-        clientMaxSpace (screen_info, &tmp_x, &full_y, &tmp_w, &full_h);
+        switch (tile)
+        {
+            case TILE_LEFT:
+                tmp_x = full_x;
+                tmp_w = full_w / 2;
+                clientMaxSpace (screen_info, &tmp_x, &full_y, &tmp_w, &full_h);
+                wc->x = tmp_x + frameLeft (c);
+                wc->width = tmp_w - frameLeft (c) - frameRight (c);
+                break;
+            case TILE_RIGHT:
+                tmp_x = full_x + full_w /2;
+                tmp_w = full_w / 2;
+                clientMaxSpace (screen_info, &tmp_x, &full_y, &tmp_w, &full_h);
+                wc->x = tmp_x + frameLeft (c);
+                wc->width = tmp_w - frameLeft (c) - frameRight (c);
+                break;
+            default:
+                clientMaxSpace (screen_info, &tmp_x, &full_y, &tmp_w, &full_h);
+                break;
+        }
+
         wc->y = full_y + frameTop (c);
         wc->height = full_h - frameTop (c) - frameBottom (c);
 
@@ -3123,8 +3164,8 @@ clientToggleMaximized (Client * c, int mode, gboolean restore_position)
 {
     DisplayInfo *display_info;
     ScreenInfo *screen_info;
-
     XWindowChanges wc;
+    GdkRectangle rect;
 
     g_return_if_fail (c != NULL);
     TRACE ("entering clientToggleMaximized");
@@ -3137,19 +3178,22 @@ clientToggleMaximized (Client * c, int mode, gboolean restore_position)
 
     screen_info = c->screen_info;
     display_info = screen_info->display_info;
+    myScreenFindMonitorAtPoint (screen_info,
+                                frameX (c) + (frameWidth (c) / 2),
+                                frameY (c) + (frameHeight (c) / 2), &rect);
 
     wc.x = c->x;
     wc.y = c->y;
     wc.width = c->width;
     wc.height = c->height;
 
-    if (!FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_VERT) && (restore_position))
+    if (restore_position && !FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_VERT))
     {
         c->old_y = c->y;
         c->old_height = c->height;
     }
 
-    if (!FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ) && (restore_position))
+    if (restore_position && !FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ))
     {
         c->old_x = c->x;
         c->old_width = c->width;
@@ -3159,7 +3203,7 @@ clientToggleMaximized (Client * c, int mode, gboolean restore_position)
     clientNewMaxState (c, &wc, mode);
 
     /* 2) Compute the new size, based on the state */
-    clientNewMaxSize (c, &wc);
+    clientNewMaxSize (c, &wc, &rect, TILE_NONE);
 
     /* 3) Update size and position fields */
     c->x = wc.x;
@@ -3177,7 +3221,81 @@ clientToggleMaximized (Client * c, int mode, gboolean restore_position)
 
     /* Maximized windows w/out border cannot be resized, update allowed actions */
     clientSetNetActions (c);
-    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED) && (restore_position))
+    if (restore_position && FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED))
+    {
+        clientConfigure (c, &wc, CWWidth | CWHeight | CWX | CWY, CFG_FORCE_REDRAW);
+    }
+    clientSetNetState (c);
+}
+
+void
+clientTile (Client * c, gint cx, gint cy, tilePositionType tile)
+{
+    DisplayInfo *display_info;
+    ScreenInfo *screen_info;
+    XWindowChanges wc;
+    GdkRectangle rect;
+    int mode;
+
+    g_return_if_fail (c != NULL);
+    TRACE ("entering clientTile");
+    TRACE ("Tiling client \"%s\" (0x%lx)", c->name, c->window);
+
+    if (!CLIENT_CAN_TILE_WINDOW (c))
+    {
+        return;
+    }
+
+    screen_info = c->screen_info;
+    display_info = screen_info->display_info;
+    myScreenFindMonitorAtPoint (screen_info, cx, cy, &rect);
+
+    wc.x = c->x;
+    wc.y = c->y;
+    wc.width = c->width;
+    wc.height = c->height;
+
+    switch (tile)
+    {
+        case TILE_LEFT:
+        case TILE_RIGHT:
+            mode = CLIENT_FLAG_MAXIMIZED_VERT;
+            break;
+        case TILE_UP:
+        case TILE_DOWN:
+            mode = CLIENT_FLAG_MAXIMIZED_HORIZ;
+            break;
+        default:
+            return;
+            break;
+    }
+
+    if (!FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
+    {
+        c->old_x = c->x;
+        c->old_y = c->y;
+        c->old_width = c->width;
+        c->old_height = c->height;
+    }
+
+    FLAG_UNSET (c->flags, CLIENT_FLAG_MAXIMIZED);
+    clientNewMaxState (c, &wc, mode);
+    clientNewMaxSize (c, &wc, &rect, tile);
+
+    c->x = wc.x;
+    c->y = wc.y;
+    c->height = wc.height;
+    c->width = wc.width;
+
+    setNetFrameExtents (display_info,
+                        c->window,
+                        frameTop (c),
+                        frameLeft (c),
+                        frameRight (c),
+                        frameBottom (c));
+
+    clientSetNetActions (c);
+    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED))
     {
         clientConfigure (c, &wc, CWWidth | CWHeight | CWX | CWY, CFG_FORCE_REDRAW);
     }
diff --git a/src/client.h b/src/client.h
index d080711..a87bd91 100644
--- a/src/client.h
+++ b/src/client.h
@@ -220,6 +220,7 @@
 #define CLIENT_CAN_FILL_WINDOW(c)       (FLAG_TEST(c->xfwm_flags, XFWM_FLAG_HAS_RESIZE | \
                                                                   XFWM_FLAG_IS_RESIZABLE) && \
                                          !FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN | CLIENT_FLAG_MAXIMIZED))
+#define CLIENT_CAN_TILE_WINDOW(c)       (CLIENT_CAN_MAXIMIZE_WINDOW(c) | (c->type & WINDOW_NORMAL))
 
 typedef enum
 {
@@ -236,6 +237,16 @@ typedef enum
 }
 netWindowType;
 
+typedef enum
+{
+    TILE_NONE = 0,
+    TILE_LEFT,
+    TILE_RIGHT,
+    TILE_DOWN,
+    TILE_UP
+}
+tilePositionType;
+
 struct _Client
 {
     /* Reference to our screen structure */
@@ -421,6 +432,10 @@ void                     clientRemoveMaximizeFlag               (Client *);
 void                     clientToggleMaximized                  (Client *,
                                                                  int,
                                                                  gboolean);
+void                     clientTile                             (Client *,
+                                                                 gint,
+                                                                 gint,
+                                                                 tilePositionType);
 void                     clientUpdateOpacity                    (Client *);
 void                     clientUpdateAllOpacity                 (ScreenInfo *);
 void                     clientSetOpacity                       (Client *,
diff --git a/src/events.c b/src/events.c
index 665d4f5..73c5051 100644
--- a/src/events.c
+++ b/src/events.c
@@ -428,7 +428,24 @@ handleKeyPress (DisplayInfo *display_info, XKeyEvent * ev)
                 clientFill (c, CLIENT_FILL_VERT);
                 break;
             case KEY_FILL_HORIZ:
-                    clientFill (c, CLIENT_FILL_HORIZ);
+                clientFill (c, CLIENT_FILL_HORIZ);
+                break;
+            case KEY_TILE_DOWN:
+                clientTile (c, frameX (c) + frameWidth (c) / 2,
+                               frameY (c) + frameHeight (c) / 2,
+                               TILE_DOWN);
+            case KEY_TILE_LEFT:
+                clientTile (c, frameX (c) + frameWidth (c) / 2,
+                               frameY (c) + frameHeight (c) / 2,
+                               TILE_LEFT);
+            case KEY_TILE_RIGHT:
+                clientTile (c, frameX (c) + frameWidth (c) / 2,
+                               frameY (c) + frameHeight (c) / 2,
+                               TILE_RIGHT);
+            case KEY_TILE_UP:
+                clientTile (c, frameX (c) + frameWidth (c) / 2,
+                               frameY (c) + frameHeight (c) / 2,
+                               TILE_UP);
                 break;
             default:
                 break;
diff --git a/src/moveresize.c b/src/moveresize.c
index 48e5428..40fe38a 100644
--- a/src/moveresize.c
+++ b/src/moveresize.c
@@ -56,6 +56,8 @@
     ButtonReleaseMask | \
     LeaveWindowMask
 
+#define TILE_DISTANCE 15
+
 typedef struct _MoveResizeData MoveResizeData;
 struct _MoveResizeData
 {
@@ -605,13 +607,210 @@ clientButtonReleaseFilter (XEvent * xevent, gpointer data)
     return EVENT_FILTER_CONTINUE;
 }
 
-static eventFilterStatus
-clientMoveEventFilter (XEvent * xevent, gpointer data)
+static void
+clientMoveWarp (Client * c, XMotionEvent *xevent)
 {
+    static guint32 lastresist = 0;
     static int edge_scroll_x = 0;
     static int edge_scroll_y = 0;
+    ScreenInfo *screen_info;
+    DisplayInfo *display_info;
+    gboolean warp_pointer = FALSE;
+    int msx, msy, maxx, maxy;
+    int rx, ry, delta;
+
+    g_return_if_fail (c != NULL);
+    TRACE ("entering clientMoveWarp");
+
+    screen_info = c->screen_info;
+    display_info = screen_info->display_info;
+
+    if (xevent == NULL)
+    {
+        /* Cleanup */
+        edge_scroll_x = 0;
+        edge_scroll_y = 0;
+        return;
+    }
+
+    if ((screen_info->params->wrap_windows) && (screen_info->params->wrap_resistance))
+    {
+
+        msx = xevent->x_root;
+        msy = xevent->y_root;
+        maxx = screen_info->width - 1;
+        maxy = screen_info->height - 1;
+        rx = 0;
+        ry = 0;
+        warp_pointer = FALSE;
+
+        if ((msx == 0) || (msx == maxx))
+        {
+            if ((xevent->time - lastresist) > 250)  /* ms */
+            {
+                edge_scroll_x = 0;
+            }
+            else
+            {
+                edge_scroll_x++;
+            }
+            if (msx == 0)
+            {
+                rx = 1;
+            }
+            else
+            {
+                rx = -1;
+            }
+            warp_pointer = TRUE;
+            lastresist = xevent->time;
+        }
+        if ((msy == 0) || (msy == maxy))
+        {
+            if ((xevent->time - lastresist) > 250)  /* ms */
+            {
+                edge_scroll_y = 0;
+            }
+            else
+            {
+                edge_scroll_y++;
+            }
+            if (msy == 0)
+            {
+                ry = 1;
+            }
+            else
+            {
+                ry = -1;
+            }
+            warp_pointer = TRUE;
+            lastresist = xevent->time;
+        }
+
+        if (edge_scroll_x > screen_info->params->wrap_resistance)
+        {
+            edge_scroll_x = 0;
+            if ((msx == 0) || (msx == maxx))
+            {
+                delta = MAX (9 * maxx / 10, maxx - 5 * screen_info->params->wrap_resistance);
+                if (msx == 0)
+                {
+                    if (workspaceMove (screen_info, 0, -1, c, xevent->time))
+                    {
+                        rx = delta;
+                    }
+                }
+                else
+                {
+                    if (workspaceMove (screen_info, 0, 1, c, xevent->time))
+                    {
+                        rx = -delta;
+                    }
+                }
+                warp_pointer = TRUE;
+            }
+            lastresist = 0;
+        }
+        if (edge_scroll_y > screen_info->params->wrap_resistance)
+        {
+            edge_scroll_y = 0;
+            if ((msy == 0) || (msy == maxy))
+            {
+                delta = MAX (9 * maxy / 10, maxy - 5 * screen_info->params->wrap_resistance);
+                if (msy == 0)
+                {
+                    if (workspaceMove (screen_info, -1, 0, c, xevent->time))
+                    {
+                        ry = delta;
+                    }
+                }
+                else
+                {
+                    if (workspaceMove (screen_info, 1, 0, c, xevent->time))
+                    {
+                        ry = -delta;
+                    }
+                }
+                warp_pointer = TRUE;
+            }
+            lastresist = 0;
+        }
+
+        if (warp_pointer)
+        {
+            XWarpPointer (display_info->dpy, None, None, 0, 0, 0, 0, rx, ry);
+            msx += rx;
+            msy += ry;
+        }
+
+        xevent->x_root = msx;
+        xevent->y_root = msy;
+    }
+}
+
+static gboolean
+clientMoveTile (Client *c, XMotionEvent *xevent)
+{
+    ScreenInfo *screen_info;
+    DisplayInfo *display_info;
+    GdkRectangle rect;
+    int x, y, disp_x, disp_y, disp_max_x, disp_max_y, dist;
+
+    screen_info = c->screen_info;
+    display_info = screen_info->display_info;
+
+    if (screen_info->params->wrap_windows)
+    {
+        return FALSE;
+    }
+
+    x = xevent->x;
+    y = xevent->y;
+
+    myScreenFindMonitorAtPoint (screen_info, x, y, &rect);
+    disp_x = rect.x;
+    disp_y = rect.y;
+    disp_max_x = rect.x + rect.width;
+    disp_max_y = rect.y + rect.height;
+
+    dist = MIN (TILE_DISTANCE, frameDecorationTop (screen_info) / 2);
+    if ((x >= disp_x - 1) && (x < disp_x + dist) &&
+        (y >= disp_y - 1) && (y < disp_max_y + 1))
+    {
+        TRACE ("event (%i,%i) monitor (%i,%i) %ix%i tile LEFT", x, y, disp_x, disp_y, disp_max_x, disp_max_y);
+        clientTile (c, x, y, TILE_LEFT);
+        return TRUE;
+    }
+    if ((x >= disp_max_x - dist) && (x < disp_max_x + 1) &&
+        (y >= disp_y - 1) && (y < disp_max_y + 1))
+    {
+        TRACE ("event (%i,%i) monitor (%i,%i) %ix%i tile RIGHT", x, y, disp_x, disp_y, disp_max_x, disp_max_y);
+        clientTile (c, x, y, TILE_RIGHT);
+        return TRUE;
+    }
+    if ((x >= disp_x - 1) && (x < disp_max_x + 1) &&
+        (y >= disp_y - 1) && (y < disp_y + dist))
+    {
+        TRACE ("event (%i,%i) monitor (%i,%i) %ix%i tile UP", x, y, disp_x, disp_y, disp_max_x, disp_max_y);
+        clientTile (c, x, y, TILE_UP);
+        return TRUE;
+    }
+    if ((x >= disp_x - 1) && (x < disp_max_x + 1) &&
+        (y >= disp_max_y - dist) && (y < disp_max_y + 1))
+    {
+        TRACE ("event (%i,%i) monitor (%i,%i) %ix%i tile DOWN", x, y, disp_x, disp_y, disp_max_x, disp_max_y);
+        clientTile (c, x, y, TILE_DOWN);
+        return TRUE;
+    }
+
+    TRACE ("event (%i,%i) monitor (%i,%i) %ix%i *no* tile", x, y, disp_x, disp_y, disp_max_x, disp_max_y);
+    return FALSE;
+}
+
+static eventFilterStatus
+clientMoveEventFilter (XEvent * xevent, gpointer data)
+{
     static gboolean toggled_maximize = FALSE;
-    static guint32 lastresist = 0;
     unsigned long configure_flags;
     ScreenInfo *screen_info;
     DisplayInfo *display_info;
@@ -619,9 +818,8 @@ clientMoveEventFilter (XEvent * xevent, gpointer data)
     MoveResizeData *passdata = (MoveResizeData *) data;
     Client *c = NULL;
     gboolean moving = TRUE;
-    gboolean warp_pointer = FALSE;
     XWindowChanges wc;
-    int prev_x, prev_y, delta;
+    int prev_x, prev_y;
 
     TRACE ("entering clientMoveEventFilter");
 
@@ -730,140 +928,33 @@ clientMoveEventFilter (XEvent * xevent, gpointer data)
         }
         if ((screen_info->workspace_count > 1) && !(passdata->is_transient))
         {
-            if ((screen_info->params->wrap_windows) && (screen_info->params->wrap_resistance))
-            {
-                int msx, msy, maxx, maxy;
-                int rx, ry;
-
-                msx = xevent->xmotion.x_root;
-                msy = xevent->xmotion.y_root;
-                maxx = screen_info->width - 1;
-                maxy = screen_info->height - 1;
-                rx = 0;
-                ry = 0;
-                warp_pointer = FALSE;
-
-                if ((msx == 0) || (msx == maxx))
-                {
-                    if ((xevent->xmotion.time - lastresist) > 250)  /* ms */
-                    {
-                        edge_scroll_x = 0;
-                    }
-                    else
-                    {
-                        edge_scroll_x++;
-                    }
-                    if (msx == 0)
-                    {
-                        rx = 1;
-                    }
-                    else
-                    {
-                        rx = -1;
-                    }
-                    warp_pointer = TRUE;
-                    lastresist = xevent->xmotion.time;
-                }
-                if ((msy == 0) || (msy == maxy))
-                {
-                    if ((xevent->xmotion.time - lastresist) > 250)  /* ms */
-                    {
-                        edge_scroll_y = 0;
-                    }
-                    else
-                    {
-                        edge_scroll_y++;
-                    }
-                    if (msy == 0)
-                    {
-                        ry = 1;
-                    }
-                    else
-                    {
-                        ry = -1;
-                    }
-                    warp_pointer = TRUE;
-                    lastresist = xevent->xmotion.time;
-                }
-
-                if (edge_scroll_x > screen_info->params->wrap_resistance)
-                {
-                    edge_scroll_x = 0;
-                    if ((msx == 0) || (msx == maxx))
-                    {
-                        delta = MAX (9 * maxx / 10, maxx - 5 * screen_info->params->wrap_resistance);
-                        if (msx == 0)
-                        {
-                            if (workspaceMove (screen_info, 0, -1, c, xevent->xmotion.time))
-                            {
-                                rx = delta;
-                            }
-                        }
-                        else
-                        {
-                            if (workspaceMove (screen_info, 0, 1, c, xevent->xmotion.time))
-                            {
-                                rx = -delta;
-                            }
-                        }
-                        warp_pointer = TRUE;
-                    }
-                    lastresist = 0;
-                }
-                if (edge_scroll_y > screen_info->params->wrap_resistance)
-                {
-                    edge_scroll_y = 0;
-                    if ((msy == 0) || (msy == maxy))
-                    {
-                        delta = MAX (9 * maxy / 10, maxy - 5 * screen_info->params->wrap_resistance);
-                        if (msy == 0)
-                        {
-                            if (workspaceMove (screen_info, -1, 0, c, xevent->xmotion.time))
-                            {
-                                ry = delta;
-                            }
-                        }
-                        else
-                        {
-                            if (workspaceMove (screen_info, 1, 0, c, xevent->xmotion.time))
-                            {
-                                ry = -delta;
-                            }
-                        }
-                        warp_pointer = TRUE;
-                    }
-                    lastresist = 0;
-                }
-
-                if (warp_pointer)
-                {
-                    XWarpPointer (display_info->dpy, None, None, 0, 0, 0, 0, rx, ry);
-                    msx += rx;
-                    msy += ry;
-                }
-
-                xevent->xmotion.x_root = msx;
-                xevent->xmotion.y_root = msy;
-            }
+            clientMoveWarp (c, (XMotionEvent *) xevent);
         }
 
-        if (FLAG_TEST_ALL(c->flags, CLIENT_FLAG_MAXIMIZED)
-            && (screen_info->params->restore_on_move))
+        if ((screen_info->params->restore_on_move) && FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
         {
-            if (xevent->xmotion.y_root - passdata->my > 15)
+
+            if ((ABS (xevent->xmotion.x_root - passdata->mx) > 15) ||
+                (ABS (xevent->xmotion.y_root - passdata->my) > 15))
             {
                 /* to keep the distance from the edges of the window proportional. */
-                double xratio;
+                double xratio = .5;
 
-                xratio = (xevent->xmotion.x_root - c->x) / (double)c->width;
-                clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED, FALSE);
+                if (FLAG_TEST(c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ))
+                {
+                    xratio = (xevent->xmotion.x_root - c->x) / (double)c->width;
+                    if (FLAG_TEST(c->flags, CLIENT_FLAG_MAXIMIZED_VERT))
+                    {
+                       toggled_maximize = TRUE;
+                    }
+                }
+                clientToggleMaximized (c, c->flags & CLIENT_FLAG_MAXIMIZED, FALSE);
                 passdata->move_resized = TRUE;
                 passdata->ox = c->x;
                 passdata->mx = CLAMP(c->x + c->width * xratio, c->x, c->x + c->width);
                 passdata->oy = c->y;
                 passdata->my = c->y - frameTop(c) / 2;
                 configure_flags = CFG_FORCE_REDRAW;
-                toggled_maximize = TRUE;
             }
             else
             {
@@ -876,9 +967,9 @@ clientMoveEventFilter (XEvent * xevent, gpointer data)
         c->y = passdata->oy + (xevent->xmotion.y_root - passdata->my);
 
         clientSnapPosition (c, prev_x, prev_y);
-        if (screen_info->params->restore_on_move)
+        if ((screen_info->params->restore_on_move) && toggled_maximize)
         {
-            if ((clientConstrainPos (c, FALSE) & CLIENT_CONSTRAINED_TOP) && toggled_maximize)
+            if (clientConstrainPos (c, FALSE) & CLIENT_CONSTRAINED_TOP)
             {
                 clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED, FALSE);
                 configure_flags = CFG_FORCE_REDRAW;
@@ -891,7 +982,7 @@ clientMoveEventFilter (XEvent * xevent, gpointer data)
                 passdata->my = c->y - frameTop(c) / 2;
             }
         }
-        else
+        else if (!clientMoveTile (c, (XMotionEvent *) xevent))
         {
             clientConstrainPos(c, FALSE);
         }
@@ -941,9 +1032,8 @@ clientMoveEventFilter (XEvent * xevent, gpointer data)
     if (!moving)
     {
         TRACE ("event loop now finished");
-        edge_scroll_x = 0;
-        edge_scroll_y = 0;
         toggled_maximize = FALSE;
+        clientMoveWarp (c, NULL);
         gtk_main_quit ();
     }
 
@@ -975,14 +1065,6 @@ clientMove (Client * c, XEvent * ev)
     }
 
     TRACE ("moving client \"%s\" (0x%lx)", c->name, c->window);
-
-    if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED) &&
-        !FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED))
-    {
-        /* Partial maximization, clear it up */
-        clientRemoveMaximizeFlag (c);
-    }
-
     screen_info = c->screen_info;
     display_info = screen_info->display_info;
 
diff --git a/src/settings.c b/src/settings.c
index fd84fe4..c96fcfa 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -611,6 +611,10 @@ loadKeyBindings (ScreenInfo *screen_info)
     parseShortcut (screen_info, KEY_STICK_WINDOW, "stick_window_key", shortcuts);
     parseShortcut (screen_info, KEY_SWITCH_APPLICATION, "switch_application_key", shortcuts);
     parseShortcut (screen_info, KEY_SWITCH_WINDOW, "switch_window_key", shortcuts);
+    parseShortcut (screen_info, KEY_TILE_DOWN, "tile_down_key", shortcuts);
+    parseShortcut (screen_info, KEY_TILE_LEFT, "tile_left_key", shortcuts);
+    parseShortcut (screen_info, KEY_TILE_RIGHT, "tile_right_key", shortcuts);
+    parseShortcut (screen_info, KEY_TILE_UP, "tile_up_key", shortcuts);
     parseShortcut (screen_info, KEY_TOGGLE_ABOVE, "above_key", shortcuts);
     parseShortcut (screen_info, KEY_TOGGLE_FULLSCREEN, "fullscreen_key", shortcuts);
     parseShortcut (screen_info, KEY_UP_WORKSPACE, "up_workspace_key", shortcuts);
diff --git a/src/settings.h b/src/settings.h
index 6642d2a..ba5ce00 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -100,6 +100,10 @@ enum
     KEY_STICK_WINDOW,
     KEY_SWITCH_APPLICATION,
     KEY_SWITCH_WINDOW,
+    KEY_TILE_DOWN,
+    KEY_TILE_LEFT,
+    KEY_TILE_RIGHT,
+    KEY_TILE_UP,
     KEY_TOGGLE_ABOVE,
     KEY_TOGGLE_FULLSCREEN,
     KEY_UP_WORKSPACE,


More information about the Xfce4-commits mailing list