merge r7648-51 from trunk
authorDana Jansens <danakj@orodu.net>
Sat, 23 Jun 2007 20:09:26 +0000 (20:09 +0000)
committerDana Jansens <danakj@orodu.net>
Sat, 23 Jun 2007 20:09:26 +0000 (20:09 +0000)
13 files changed:
data/rc.xml
data/rc.xsd
openbox/action.c
openbox/client_list_combined_menu.c
openbox/client_list_menu.c
openbox/config.c
openbox/config.h
openbox/menu.c
openbox/menu.h
openbox/menuframe.c
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 0357dee..e802cf3 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 4268987..bea1245 100644 (file)
@@ -2038,72 +2038,13 @@ void action_break_chroot(union ActionData *data)
 void action_add_desktop(union ActionData *data)
 {
     client_action_start(data);
-    screen_set_num_desktops(screen_num_desktops+1);
-
-    /* move all the clients over */
-    if (data->addremovedesktop.current) {
-        GList *it;
-
-        for (it = client_list; it; it = g_list_next(it)) {
-            ObClient *c = it->data;
-            if (c->desktop != DESKTOP_ALL && c->desktop >= screen_desktop)
-                client_set_desktop(c, c->desktop+1, FALSE, TRUE);
-        }
-    }
-
+    screen_add_desktop(data->addremovedesktop.current);
     client_action_end(data, config_focus_under_mouse);
 }
 
 void action_remove_desktop(union ActionData *data)
 {
-    guint rmdesktop, movedesktop;
-    GList *it, *stacking_copy;
-
-    if (screen_num_desktops < 2) return;
-
     client_action_start(data);
-
-    /* what desktop are we removing and moving to? */
-    if (data->addremovedesktop.current)
-        rmdesktop = screen_desktop;
-    else
-        rmdesktop = screen_num_desktops - 1;
-    if (rmdesktop < screen_num_desktops - 1)
-        movedesktop = rmdesktop + 1;
-    else
-        movedesktop = rmdesktop;
-
-    /* make a copy of the list cuz we're changing it */
-    stacking_copy = g_list_copy(stacking_list);
-    for (it = g_list_last(stacking_copy); it; it = g_list_previous(it)) {
-        if (WINDOW_IS_CLIENT(it->data)) {
-            ObClient *c = it->data;
-            guint d = c->desktop;
-            if (d != DESKTOP_ALL && d >= movedesktop) {
-                client_set_desktop(c, c->desktop - 1, TRUE, TRUE);
-                ob_debug("moving window %s\n", c->title);
-            }
-            /* raise all the windows that are on the current desktop which
-               is being merged */
-            if ((screen_desktop == rmdesktop - 1 ||
-                 screen_desktop == rmdesktop) &&
-                (d == DESKTOP_ALL || d == screen_desktop))
-            {
-                stacking_raise(CLIENT_AS_WINDOW(c));
-                ob_debug("raising window %s\n", c->title);
-            }
-        }
-    }
-
-    /* act like we're changing desktops */
-    if (screen_desktop < screen_num_desktops - 1) {
-        gint d = screen_desktop;
-        screen_desktop = screen_last_desktop;
-        screen_set_desktop(d, TRUE);
-        ob_debug("fake desktop change\n");
-    }
-
-    screen_set_num_desktops(screen_num_desktops-1);
-
+    screen_remove_desktop(data->addremovedesktop.current);
     client_action_end(data, config_focus_under_mouse);
 }
index af2819b..e416cab 100644 (file)
 
 ObMenu *combined_menu;
 
+#define CLIENT -1
+#define ADD_DESKTOP -2
+#define REMOVE_DESKTOP -3
+
 static gboolean self_update(ObMenuFrame *frame, gpointer data)
 {
     ObMenu *menu = frame->menu;
@@ -45,7 +49,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
         gboolean empty = TRUE;
         gboolean onlyiconic = TRUE;
 
-        menu_add_separator(menu, -1, screen_desktop_names[desktop]);
+        menu_add_separator(menu, CLIENT, screen_desktop_names[desktop]);
         for (it = focus_order; it; it = g_list_next(it)) {
             ObClient *c = it->data;
             if (client_normal(c) && (!c->skip_taskbar || c->iconic) &&
@@ -57,11 +61,11 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
 
                 if (c->iconic) {
                     gchar *title = g_strdup_printf("(%s)", c->icon_title);
-                    e = menu_add_normal(menu, -1, title, NULL, FALSE);
+                    e = menu_add_normal(menu, CLIENT, title, NULL, FALSE);
                     g_free(title);
                 } else {
                     onlyiconic = FALSE;
-                    e = menu_add_normal(menu, -1, c->title, NULL, FALSE);
+                    e = menu_add_normal(menu, CLIENT, c->title, NULL, FALSE);
                 }
 
                 if (config_menu_client_list_icons
@@ -83,13 +87,19 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
             /* no entries or only iconified windows, so add a
              * way to go to this desktop without uniconifying a window */
             if (!empty)
-                menu_add_separator(menu, -1, NULL);
+                menu_add_separator(menu, CLIENT, NULL);
 
             e = menu_add_normal(menu, desktop, _("Go there..."), NULL, TRUE);
             if (desktop == screen_desktop)
                 e->data.normal.enabled = FALSE;
         }
     }
+
+    menu_add_separator(menu, CLIENT, _("Manage desktops"));
+    menu_add_normal(menu, ADD_DESKTOP, _("&Add new desktop"), NULL, TRUE);
+    menu_add_normal(menu, REMOVE_DESKTOP, _("&Remove last desktop"),
+                    NULL, TRUE);
+
     return TRUE; /* always show the menu */
 }
 
@@ -97,10 +107,18 @@ static void menu_execute(ObMenuEntry *self, ObMenuFrame *f,
                          ObClient *c, guint state, gpointer data,
                          Time time)
 {
-    if (self->id == -1) {
+    if (self->id == CLIENT) {
         if (self->data.normal.data) /* it's set to NULL if its destroyed */
             client_activate(self->data.normal.data, FALSE, TRUE);
     }
+    else if (self->id == ADD_DESKTOP) {
+        screen_add_desktop(FALSE);
+        menu_frame_hide_all();
+    }
+    else if (self->id == REMOVE_DESKTOP) {
+        screen_remove_desktop(FALSE);
+        menu_frame_hide_all();
+    }
     else
         screen_set_desktop(self->id, TRUE);
 }
index 936c312..d7e2dfb 100644 (file)
@@ -37,6 +37,10 @@ typedef struct
     guint desktop;
 } DesktopData;
 
+#define CLIENT -1
+#define ADD_DESKTOP -2
+#define REMOVE_DESKTOP -3
+
 static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
 {
     ObMenu *menu = frame->menu;
@@ -59,11 +63,11 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
 
             if (c->iconic) {
                 gchar *title = g_strdup_printf("(%s)", c->icon_title);
-                e = menu_add_normal(menu, -1, title, NULL, FALSE);
+                e = menu_add_normal(menu, CLIENT, title, NULL, FALSE);
                 g_free(title);
             } else {
                 onlyiconic = FALSE;
-                e = menu_add_normal(menu, -1, c->title, NULL, FALSE);
+                e = menu_add_normal(menu, CLIENT, c->title, NULL, FALSE);
             }
 
             if (config_menu_client_list_icons
@@ -84,12 +88,13 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
         /* no entries or only iconified windows, so add a
          * way to go to this desktop without uniconifying a window */
         if (!empty)
-            menu_add_separator(menu, -1, NULL);
+            menu_add_separator(menu, CLIENT, NULL);
 
         e = menu_add_normal(menu, d->desktop, _("Go there..."), NULL, TRUE);
         if (d->desktop == screen_desktop)
             e->data.normal.enabled = FALSE;
     }
+
     return TRUE; /* always show */
 }
 
@@ -97,7 +102,7 @@ static void desk_menu_execute(ObMenuEntry *self, ObMenuFrame *f,
                               ObClient *c, guint state, gpointer data,
                               Time time)
 {
-    if (self->id == -1) {
+    if (self->id == CLIENT) {
         if (self->data.normal.data) /* it's set to NULL if its destroyed */
             client_activate(self->data.normal.data, FALSE, TRUE);
     }
@@ -144,9 +149,27 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
         desktop_menus = g_slist_append(desktop_menus, submenu);
     }
 
+    menu_add_separator(menu, CLIENT, NULL);
+    menu_add_normal(menu, ADD_DESKTOP, _("&Add new desktop"), NULL, TRUE);
+    menu_add_normal(menu, REMOVE_DESKTOP, _("&Remove last desktop"),
+                    NULL, TRUE);
+
     return TRUE; /* always show */
 }
 
+static void self_execute(ObMenuEntry *self, ObMenuFrame *f,
+                         ObClient *c, guint state, gpointer data)
+{
+    if (self->id == ADD_DESKTOP) {
+        screen_add_desktop(FALSE);
+        menu_frame_hide_all();
+    }
+    else if (self->id == REMOVE_DESKTOP) {
+        screen_remove_desktop(FALSE);
+        menu_frame_hide_all();
+    }
+}
+
 static void client_dest(ObClient *client, gpointer data)
 {
     /* This concise function removes all references to a closed
@@ -176,6 +199,7 @@ void client_list_menu_startup(gboolean reconfig)
 
     menu = menu_new(MENU_NAME, _("Desktops"), TRUE, NULL);
     menu_set_update_func(menu, self_update);
+    menu_set_execute_func(menu, self_execute);
 }
 
 void client_list_menu_shutdown(gboolean reconfig)
index 2eb8e13..bc3aba9 100644 (file)
@@ -78,6 +78,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;
@@ -423,6 +424,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) {
@@ -926,6 +929,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 c82eab8..b4035b1 100644 (file)
@@ -57,7 +57,8 @@ static void parse_menu_separator(ObParseInst *i,
 static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
                        gpointer data);
 static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
-                               gchar **strippedlabel, guint *position);
+                               gchar **strippedlabel, guint *position,
+                               gboolean *always_show);
 
 
 static void client_dest(ObClient *client, gpointer data)
@@ -202,11 +203,13 @@ static ObMenu* menu_from_name(gchar *name)
                            ((c) >= 'a' && (c) <= 'z'))
 
 static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
-                               gchar **strippedlabel, guint *position)
+                               gchar **strippedlabel, guint *position,
+                               gboolean *always_show)
 {
     gunichar shortcut = 0;
     
     *position = 0;
+    *always_show = FALSE;
 
     g_assert(strippedlabel != NULL);
 
@@ -231,6 +234,7 @@ static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
             if (VALID_SHORTCUT(*(i+1))) {
                 shortcut = g_unichar_tolower(g_utf8_get_char(i+1));
                 *position = i - *strippedlabel;
+                *always_show = TRUE;
 
                 /* remove the & from the string */
                 for (; *i != '\0'; ++i)
@@ -339,7 +343,8 @@ ObMenu* menu_new(const gchar *name, const gchar *title,
     self->data = data;
 
     self->shortcut = parse_shortcut(title, allow_shortcut_selection,
-                                    &self->title, &self->shortcut_position);
+                                    &self->title, &self->shortcut_position,
+                                    &self->shortcut_always_show);
 
     g_hash_table_replace(menu_hash, self->name, self);
 
@@ -670,7 +675,8 @@ void menu_entry_set_label(ObMenuEntry *self, const gchar *label,
         g_free(self->data.normal.label);
         self->data.normal.shortcut =
             parse_shortcut(label, allow_shortcut, &self->data.normal.label,
-                           &self->data.normal.shortcut_position);
+                           &self->data.normal.shortcut_position,
+                           &self->data.normal.shortcut_always_show);
         break;
     default:
         g_assert_not_reached();
index 47b65fb..02e5548 100644 (file)
@@ -65,6 +65,8 @@ struct _ObMenu
     gunichar shortcut;
     /*! The shortcut's position in the string */
     guint shortcut_position;
+    /*! If the shortcut was specified by & and should always be drawn */
+    gboolean shortcut_always_show;
 
     /*! If the shortcut key should be shown in menu entries even when it
       is the first character in the string */
@@ -106,6 +108,8 @@ struct _ObNormalMenuEntry {
     gunichar shortcut;
     /*! The shortcut's position in the string */
     guint shortcut_position;
+    /*! If the shortcut was specified by & and should always be drawn */
+    gboolean shortcut_always_show;
 
     /* state */
     gboolean enabled;
index fdb24af..12cb306 100644 (file)
@@ -400,6 +400,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
         text_a->texture[0].data.text.string = self->entry->data.normal.label;
         if (self->entry->data.normal.shortcut &&
             (self->frame->menu->show_all_shortcuts ||
+             self->entry->data.normal.shortcut_always_show ||
              self->entry->data.normal.shortcut_position > 0))
         {
             text_a->texture[0].data.text.shortcut = TRUE;
@@ -415,6 +416,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
         sub = self->entry->data.submenu.submenu;
         text_a->texture[0].data.text.string = sub ? sub->title : "";
         if (sub->shortcut && (self->frame->menu->show_all_shortcuts ||
+                              sub->shortcut_always_show ||
                               sub->shortcut_position > 0))
         {
             text_a->texture[0].data.text.shortcut = TRUE;
index 534cd01..3d411a8 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 c39204d..6dd7bc2 100644 (file)
@@ -48,7 +48,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();
@@ -631,6 +631,72 @@ void screen_set_desktop(guint num, gboolean dofocus)
         screen_desktop_user_time = event_curtime;
 }
 
+void screen_add_desktop(gboolean current)
+{
+    screen_set_num_desktops(screen_num_desktops+1);
+
+    /* move all the clients over */
+    if (current) {
+        GList *it;
+
+        for (it = client_list; it; it = g_list_next(it)) {
+            ObClient *c = it->data;
+            if (c->desktop != DESKTOP_ALL && c->desktop >= screen_desktop)
+                client_set_desktop(c, c->desktop+1, FALSE, TRUE);
+        }
+    }
+}
+
+void screen_remove_desktop(gboolean current)
+{
+    guint rmdesktop, movedesktop;
+    GList *it, *stacking_copy;
+
+    if (screen_num_desktops <= 1) return;
+
+    /* what desktop are we removing and moving to? */
+    if (current)
+        rmdesktop = screen_desktop;
+    else
+        rmdesktop = screen_num_desktops - 1;
+    if (rmdesktop < screen_num_desktops - 1)
+        movedesktop = rmdesktop + 1;
+    else
+        movedesktop = rmdesktop;
+
+    /* make a copy of the list cuz we're changing it */
+    stacking_copy = g_list_copy(stacking_list);
+    for (it = g_list_last(stacking_copy); it; it = g_list_previous(it)) {
+        if (WINDOW_IS_CLIENT(it->data)) {
+            ObClient *c = it->data;
+            guint d = c->desktop;
+            if (d != DESKTOP_ALL && d >= movedesktop) {
+                client_set_desktop(c, c->desktop - 1, TRUE, TRUE);
+                ob_debug("moving window %s\n", c->title);
+            }
+            /* raise all the windows that are on the current desktop which
+               is being merged */
+            if ((screen_desktop == rmdesktop - 1 ||
+                 screen_desktop == rmdesktop) &&
+                (d == DESKTOP_ALL || d == screen_desktop))
+            {
+                stacking_raise(CLIENT_AS_WINDOW(c));
+                ob_debug("raising window %s\n", c->title);
+            }
+        }
+    }
+
+    /* act like we're changing desktops */
+    if (screen_desktop < screen_num_desktops - 1) {
+        gint d = screen_desktop;
+        screen_desktop = screen_last_desktop;
+        screen_set_desktop(d, TRUE);
+        ob_debug("fake desktop change\n");
+    }
+
+    screen_set_num_desktops(screen_num_desktops-1);
+}
+
 static void get_row_col(guint d, guint *r, guint *c)
 {
     switch (screen_desktop_layout.orientation) {
@@ -760,22 +826,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;
-
-    if (d == (guint)-1)
-        d = screen_desktop;
-
-    if ((cancel || done) && dialog)
-        goto show_cycle_dialog;
+    guint d;
 
-    oldd = d;
+    d = from;
     get_row_col(d, &r, &c);
-
     if (linear) {
         switch (dir) {
         case OB_DIRECTION_EAST:
@@ -783,16 +841,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) {
@@ -802,16 +864,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:
@@ -820,16 +880,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:
@@ -838,16 +896,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:
@@ -856,30 +912,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 6ad1819..c2c57f0 100644 (file)
@@ -67,10 +67,18 @@ void screen_resize();
 void screen_set_num_desktops(guint num);
 /*! Change the current desktop */
 void screen_set_desktop(guint num, gboolean dofocus);
+/*! Add a new desktop either at the end or inserted at the current desktop */
+void screen_add_desktop(gboolean current);
+/*! Remove a desktop, either at the end or the current desktop */
+void screen_remove_desktop(gboolean current);
+
 /*! Interactively change desktops */
 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);