warp desktops when you hit the edge of the screen while moving a window
authorDana Jansens <danakj@orodu.net>
Sat, 23 Jun 2007 19:52:09 +0000 (19:52 +0000)
committerDana Jansens <danakj@orodu.net>
Sat, 23 Jun 2007 19:52:09 +0000 (19:52 +0000)
data/rc.xml
data/rc.xsd
openbox/config.c
openbox/config.h
openbox/moveresize.c
openbox/screen.c
openbox/screen.h

index 1a4230c..6bbc34a 100644 (file)
   <!-- number of pixels the mouse must move before a drag begins -->
   <doubleClickTime>200</doubleClickTime>
   <!-- in milliseconds (1000 = 1 second) -->
+  <screenEdgeWarpTime>400</screenEdgeWarpTime>
+  <!-- time before changing desktops when the pointer touches the edge of the
+       screen while moving a window, in milliseconds (1000 = 1 second),
+       0 disables warping -->
 
   <context name="Frame">
     <mousebind button="A-Left" action="Press">
index 3e6b312..89bed98 100644 (file)
     <xsd:complexType name="mouse">
         <xsd:element minOccurs="0" name="dragThreshold" type="xsd:integer"/>
         <xsd:element minOccurs="0" name="doubleClickTime" type="xsd:integer"/>
+        <xsd:element minOccurs="0" name="screenEdgeWarpTime" type="xsd:integer"/>
         <xsd:element maxOccurs="unbounded" name="context" type="ob:context"/>
     </xsd:complexType>
     <xsd:complexType name="menu">
index 51e169e..96f3ba8 100644 (file)
@@ -79,6 +79,7 @@ guint config_keyboard_reset_state;
 
 gint config_mouse_threshold;
 gint config_mouse_dclicktime;
+gint config_mouse_screenedgetime;
 
 guint    config_menu_hide_delay;
 gboolean config_menu_middle;
@@ -422,6 +423,8 @@ static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         config_mouse_threshold = parse_int(doc, n);
     if ((n = parse_find_node("doubleClickTime", node)))
         config_mouse_dclicktime = parse_int(doc, n);
+    if ((n = parse_find_node("screenEdgeWarpTime", node)))
+        config_mouse_screenedgetime = parse_int(doc, n);
 
     n = parse_find_node("context", node);
     while (n) {
@@ -887,6 +890,7 @@ void config_startup(ObParseInst *i)
 
     config_mouse_threshold = 8;
     config_mouse_dclicktime = 200;
+    config_mouse_screenedgetime = 400;
 
     bind_default_mouse();
 
index e8c70eb..8a365f8 100644 (file)
@@ -153,6 +153,9 @@ extern gint config_mouse_threshold;
 /*! Number of milliseconds within which 2 clicks must occur to be a
   double-click */
 extern gint config_mouse_dclicktime;
+/*! Number of milliseconds that the mouse has to be on the screen edge before
+  a screen edge event is triggered */
+extern gint config_mouse_screenedgetime;
 
 /*! Number of pixels to resist while crossing another window's edge */
 extern gint config_resist_win;
index 01cbb79..05c5f59 100644 (file)
@@ -25,6 +25,7 @@
 #include "frame.h"
 #include "openbox.h"
 #include "resist.h"
+#include "mainloop.h"
 #include "popup.h"
 #include "moveresize.h"
 #include "config.h"
@@ -53,12 +54,16 @@ static gint cur_x, cur_y;
 static guint button;
 static guint32 corner;
 static ObCorner lockcorner;
+static ObDirection edge_warp_dir = -1;
 #ifdef SYNC
 static gboolean waiting_for_sync;
 #endif
 
 static ObPopup *popup = NULL;
 
+static void do_edge_warp(gint x, gint y);
+static void cancel_edge_warp();
+
 static void client_dest(ObClient *client, gpointer data)
 {
     if (moveresize_client == client)
@@ -302,6 +307,9 @@ void moveresize_end(gboolean cancel)
                          TRUE, TRUE, FALSE);
     }
 
+    /* dont edge warp after its ended */
+    cancel_edge_warp();
+
     moveresize_in_progress = FALSE;
     moveresize_client = NULL;
 }
@@ -412,6 +420,65 @@ static void calc_resize(gboolean keyboard)
         moveresize_client->frame->size.bottom;
 }
 
+static gboolean edge_warp_delay_func(gpointer data)
+{
+    guint d;
+
+    d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE);
+    if (d != screen_desktop) screen_set_desktop(d, TRUE);
+
+    edge_warp_dir = -1;
+
+    return FALSE; /* don't repeat */
+}
+
+static void do_edge_warp(gint x, gint y)
+{
+    guint i, d;
+    ObDirection dir;
+
+    if (!config_mouse_screenedgetime) return;
+
+    dir = -1;
+
+    for (i = 0; i < screen_num_monitors; ++i) {
+        Rect *a = screen_physical_area_monitor(i);
+        if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST;
+        if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST;
+        if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH;
+        if (y == RECT_BOTTOM(*a)) dir = OB_DIRECTION_SOUTH;
+
+        /* try check for xinerama boundaries */
+        if ((x + 1 == RECT_LEFT(*a) || x - 1 == RECT_RIGHT(*a)) &&
+            (dir == OB_DIRECTION_WEST || dir == OB_DIRECTION_EAST))
+        {
+            dir = -1;
+        }
+        if ((y + 1 == RECT_TOP(*a) || y - 1 == RECT_BOTTOM(*a)) &&
+            (dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH))
+        {
+            dir = -1;
+        }
+        g_free(a);
+    }
+
+    if (dir != edge_warp_dir) {
+        if (dir == (ObDirection)-1)
+            cancel_edge_warp();
+        else
+            ob_main_loop_timeout_add(ob_main_loop,
+                                     config_mouse_screenedgetime * 1000,
+                                     edge_warp_delay_func,
+                                     NULL, NULL, NULL);
+        edge_warp_dir = dir;
+    }
+}
+
+static void cancel_edge_warp()
+{
+    ob_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
+}
+
 gboolean moveresize_event(XEvent *e)
 {
     gboolean used = FALSE;
@@ -435,6 +502,7 @@ gboolean moveresize_event(XEvent *e)
             cur_x = start_cx + e->xmotion.x_root - start_x;
             cur_y = start_cy + e->xmotion.y_root - start_y;
             do_move(FALSE);
+            do_edge_warp(e->xmotion.x_root, e->xmotion.y_root);
         } else {
             if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
                 cur_x = start_cw - (e->xmotion.x_root - start_x);
index 926b21e..1a01bfb 100644 (file)
@@ -49,7 +49,7 @@
 #define ROOT_EVENTMASK (StructureNotifyMask | PropertyChangeMask | \
                         EnterWindowMask | LeaveWindowMask | \
                         SubstructureRedirectMask | FocusChangeMask | \
-                        ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
+                        ButtonPressMask | ButtonReleaseMask)
 
 static gboolean screen_validate_layout(ObDesktopLayout *l);
 static gboolean replace_wm();
@@ -830,22 +830,14 @@ void screen_desktop_popup(guint d, gboolean show)
     }
 }
 
-guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
-                           gboolean dialog, gboolean done, gboolean cancel)
+guint screen_find_desktop(guint from, ObDirection dir,
+                          gboolean wrap, gboolean linear)
 {
     guint r, c;
-    static guint d = (guint)-1;
-    guint ret, oldd;
+    guint d;
 
-    if (d == (guint)-1)
-        d = screen_desktop;
-
-    if ((cancel || done) && dialog)
-        goto show_cycle_dialog;
-
-    oldd = d;
+    d = from;
     get_row_col(d, &r, &c);
-
     if (linear) {
         switch (dir) {
         case OB_DIRECTION_EAST:
@@ -853,16 +845,20 @@ guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
                 ++d;
             else if (wrap)
                 d = 0;
+            else
+                return from;
             break;
         case OB_DIRECTION_WEST:
             if (d > 0)
                 --d;
             else if (wrap)
                 d = screen_num_desktops - 1;
+            else
+                return from;
             break;
         default:
-            assert(0);
-            return screen_desktop;
+            g_assert_not_reached();
+            return from;
         }
     } else {
         switch (dir) {
@@ -872,16 +868,14 @@ guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
                 if (wrap)
                     c = 0;
                 else
-                    goto show_cycle_dialog;
+                    return from;
             }
             d = translate_row_col(r, c);
             if (d >= screen_num_desktops) {
-                if (wrap) {
+                if (wrap)
                     ++c;
-                } else {
-                    d = oldd;
-                    goto show_cycle_dialog;
-                }
+                else
+                    return from;
             }
             break;
         case OB_DIRECTION_WEST:
@@ -890,16 +884,14 @@ guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
                 if (wrap)
                     c = screen_desktop_layout.columns - 1;
                 else
-                    goto show_cycle_dialog;
+                    return from;
             }
             d = translate_row_col(r, c);
             if (d >= screen_num_desktops) {
-                if (wrap) {
+                if (wrap)
                     --c;
-                } else {
-                    d = oldd;
-                    goto show_cycle_dialog;
-                }
+                else
+                    return from;
             }
             break;
         case OB_DIRECTION_SOUTH:
@@ -908,16 +900,14 @@ guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
                 if (wrap)
                     r = 0;
                 else
-                    goto show_cycle_dialog;
+                    return from;
             }
             d = translate_row_col(r, c);
             if (d >= screen_num_desktops) {
-                if (wrap) {
+                if (wrap)
                     ++r;
-                } else {
-                    d = oldd;
-                    goto show_cycle_dialog;
-                }
+                else
+                    return from;
             }
             break;
         case OB_DIRECTION_NORTH:
@@ -926,30 +916,41 @@ guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
                 if (wrap)
                     r = screen_desktop_layout.rows - 1;
                 else
-                    goto show_cycle_dialog;
+                    return from;
             }
             d = translate_row_col(r, c);
             if (d >= screen_num_desktops) {
-                if (wrap) {
+                if (wrap)
                     --r;
-                } else {
-                    d = oldd;
-                    goto show_cycle_dialog;
-                }
+                else
+                    return from;
             }
             break;
         default:
-            assert(0);
-            return d = screen_desktop;
+            g_assert_not_reached();
+            return from;
         }
 
         d = translate_row_col(r, c);
     }
+    return d;
+}
+
+guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
+                           gboolean dialog, gboolean done, gboolean cancel)
+{
+    static guint d = (guint)-1;
+    guint ret;
+
+    if (d == (guint)-1)
+        d = screen_desktop;
 
-show_cycle_dialog:
-    if (dialog && !cancel && !done) {
+    if ((!cancel && !done) || !dialog)
+        d = screen_find_desktop(d, dir, wrap, linear);
+
+    if (dialog && !cancel && !done)
         screen_desktop_popup(d, TRUE);
-    else
+    else
         screen_desktop_popup(0, FALSE);
     ret = d;
 
index 041d9cc..c2c57f0 100644 (file)
@@ -76,6 +76,9 @@ void screen_remove_desktop(gboolean current);
 guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
                            gboolean dialog, gboolean done, gboolean cancel);
 
+guint screen_find_desktop(guint from, ObDirection dir,
+                          gboolean wrap, gboolean linear);
+
 /*! Show/hide the desktop popup (pager) for the given desktop */
 void screen_desktop_popup(guint d, gboolean show);