Посетила указанная в заголовке юзабилити-идея. В самом деле, если по нажатию alt-tab, WM переходит в режим листания окон, то почему бы прямо оттуда же и не листать рабочие столы? Сказано — сделано. Патч добавляет опенбоксу листание столов по стрелке-влево/стрелке-вправо когда активен список окон:
diff --git a/openbox/actions/cyclewindows.c b/openbox/actions/cyclewindows.c
index 5f0db27..a3cde57 100644
--- a/openbox/actions/cyclewindows.c
+++ b/openbox/actions/cyclewindows.c
@@ -4,6 +4,7 @@
#include "openbox/event.h"
#include "openbox/focus_cycle.h"
#include "openbox/openbox.h"
+#include "openbox/screen.h"
#include "gettext.h"
#include "obt/keyboard.h"
@@ -23,6 +24,8 @@ typedef struct {
/* options for after we're done */
gboolean cancel; /* did the user cancel or not */
guint state; /* keyboard state when finished */
+
+ guint screen_desktop;
} Options;
static gpointer setup_func(xmlNodePtr node,
@@ -70,6 +73,8 @@ static gpointer setup_func(xmlNodePtr node,
o->bar = TRUE;
o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_LIST;
+ o->screen_desktop = screen_desktop;
+
if ((n = obt_xml_find_node(node, "linear")))
o->linear = obt_xml_node_bool(n);
if ((n = obt_xml_find_node(node, "dialog"))) {
@@ -206,6 +211,16 @@ static gboolean i_input_func(guint initial_state,
o->state = e->xkey.state;
return FALSE;
}
+
+ else if ((sym == XK_Left || sym == XK_Right) ) {
+ guint d = screen_find_desktop(screen_desktop,
+ sym == XK_Right ? OB_DIRECTION_EAST : OB_DIRECTION_WEST, TRUE, TRUE);
+
+ screen_set_desktop(d, TRUE, FALSE);
+ run_func(NULL, options);
+ screen_show_desktop_popup(d, FALSE, FALSE);
+ return TRUE;
+ }
}
/* They released the modifiers */
else if (e->type == KeyRelease && initial_state && !(mods & initial_state))
@@ -223,6 +238,8 @@ static void i_cancel_func(gpointer options)
Options *o = options;
o->cancel = TRUE;
o->state = 0;
+
+ screen_set_desktop(o->screen_desktop, TRUE, TRUE);
}
static void i_post_func(gpointer options)
diff --git a/openbox/actions/desktop.c b/openbox/actions/desktop.c
index a3a1f6b..7886b7c 100644
--- a/openbox/actions/desktop.c
+++ b/openbox/actions/desktop.c
@@ -302,7 +302,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
}
if (go) {
- screen_set_desktop(d, TRUE);
+ screen_set_desktop(d, TRUE, TRUE);
if (data->client)
client_bring_helper_windows(data->client);
}
@@ -356,7 +356,7 @@ static gboolean i_pre_func(guint initial_state, gpointer options)
return FALSE;
}
else {
- screen_show_desktop_popup(screen_desktop, TRUE);
+ screen_show_desktop_popup(screen_desktop, TRUE, TRUE);
return TRUE;
}
}
diff --git a/openbox/client.c b/openbox/client.c
index f3b4bda..feff3a6 100644
--- a/openbox/client.c
+++ b/openbox/client.c
@@ -4029,7 +4029,7 @@ static void client_present(ObClient *self, gboolean here, gboolean raise,
if (here)
client_set_desktop(self, screen_desktop, FALSE, TRUE);
else
- screen_set_desktop(self->desktop, FALSE);
+ screen_set_desktop(self->desktop, FALSE, TRUE);
} else if (!self->frame->visible)
/* if its not visible for other reasons, then don't mess
with it */
diff --git a/openbox/client_list_combined_menu.c b/openbox/client_list_combined_menu.c
index c26b6fa..f2027e4 100644
--- a/openbox/client_list_combined_menu.c
+++ b/openbox/client_list_combined_menu.c
@@ -126,10 +126,10 @@ static void menu_execute(ObMenuEntry *self, ObMenuFrame *f,
/* if the window is omnipresent then we need to go to its
desktop */
if (!here && t->desktop == DESKTOP_ALL)
- screen_set_desktop(self->id, FALSE);
+ screen_set_desktop(self->id, FALSE, TRUE);
}
else
- screen_set_desktop(self->id, TRUE);
+ screen_set_desktop(self->id, TRUE, TRUE);
}
}
diff --git a/openbox/client_list_menu.c b/openbox/client_list_menu.c
index f3df2a5..0b5af55 100644
--- a/openbox/client_list_menu.c
+++ b/openbox/client_list_menu.c
@@ -106,10 +106,10 @@ static void desk_menu_execute(ObMenuEntry *self, ObMenuFrame *f,
/* if the window is omnipresent then we need to go to its
desktop */
if (!here && t->desktop == DESKTOP_ALL)
- screen_set_desktop(self->id, FALSE);
+ screen_set_desktop(self->id, FALSE, TRUE);
}
else
- screen_set_desktop(self->id, TRUE);
+ screen_set_desktop(self->id, TRUE, TRUE);
}
static void desk_menu_destroy(ObMenu *menu, gpointer data)
diff --git a/openbox/event.c b/openbox/event.c
index cf089b6..d9d60a4 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -768,7 +768,7 @@ static void event_handle_root(XEvent *e)
"a timestamp");
else
event_sourcetime = e->xclient.data.l[1];
- screen_set_desktop(d, TRUE);
+ screen_set_desktop(d, TRUE, TRUE);
}
} else if (msgtype == OBT_PROP_ATOM(NET_NUMBER_OF_DESKTOPS)) {
guint d = e->xclient.data.l[0];
diff --git a/openbox/moveresize.c b/openbox/moveresize.c
index 3a98db3..a776b7c 100644
--- a/openbox/moveresize.c
+++ b/openbox/moveresize.c
@@ -611,7 +611,7 @@ static gboolean edge_warp_delay_func(gpointer data)
d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE);
if (d != screen_desktop) {
if (config_mouse_screenedgewarp) edge_warp_move_ptr();
- screen_set_desktop(d, TRUE);
+ screen_set_desktop(d, TRUE, TRUE);
}
}
edge_warp_odd = !edge_warp_odd;
diff --git a/openbox/screen.c b/openbox/screen.c
index ffe74a0..5e69a32 100644
--- a/openbox/screen.c
+++ b/openbox/screen.c
@@ -433,13 +433,13 @@ void screen_startup(gboolean reconfig)
NET_CURRENT_DESKTOP, CARDINAL, &d) &&
d < screen_num_desktops)
{
- screen_set_desktop(d, FALSE);
+ screen_set_desktop(d, FALSE, TRUE);
} else if (session_desktop >= 0)
screen_set_desktop(MIN((guint)session_desktop,
- screen_num_desktops), FALSE);
+ screen_num_desktops), FALSE, TRUE);
else
screen_set_desktop(MIN(config_screen_firstdesk,
- screen_num_desktops) - 1, FALSE);
+ screen_num_desktops) - 1, FALSE, TRUE);
screen_last_desktop = screen_desktop;
/* don't start in showing-desktop mode */
@@ -553,7 +553,7 @@ void screen_set_num_desktops(guint num)
/* change our desktop if we're on one that no longer exists! */
if (screen_desktop >= screen_num_desktops)
- screen_set_desktop(num - 1, TRUE);
+ screen_set_desktop(num - 1, TRUE, TRUE);
}
static void screen_fallback_focus(void)
@@ -604,7 +604,7 @@ static gboolean last_desktop_func(gpointer data)
return FALSE; /* don't repeat */
}
-void screen_set_desktop(guint num, gboolean dofocus)
+void screen_set_desktop(guint num, gboolean dofocus, gboolean show_popup)
{
GList *it;
guint previous;
@@ -689,8 +689,8 @@ void screen_set_desktop(guint num, gboolean dofocus)
ob_debug("Moving to desktop %d", num+1);
- if (ob_state() == OB_STATE_RUNNING)
- screen_show_desktop_popup(screen_desktop, FALSE);
+ if (show_popup && ob_state() == OB_STATE_RUNNING)
+ screen_show_desktop_popup(screen_desktop, FALSE, TRUE);
/* ignore enter events caused by the move */
ignore_start = event_start_ignore_all_enters();
@@ -941,7 +941,7 @@ static gboolean hide_desktop_popup_func(gpointer data)
return FALSE; /* don't repeat */
}
-void screen_show_desktop_popup(guint d, gboolean perm)
+void screen_show_desktop_popup(guint d, gboolean perm, gboolean center)
{
const Rect *a;
@@ -949,8 +949,12 @@ void screen_show_desktop_popup(guint d, gboolean perm)
if (!config_desktop_popup_time) return;
a = screen_physical_area_primary(FALSE);
- pager_popup_position(desktop_popup, CenterGravity,
- a->x + a->width / 2, a->y + a->height / 2);
+ if (center)
+ pager_popup_position(desktop_popup, CenterGravity,
+ a->x + a->width / 2, a->y + a->height / 2);
+ else
+ pager_popup_position(desktop_popup, NorthGravity,
+ a->x + a->width / 2, a->y);
pager_popup_icon_size_multiplier(desktop_popup,
(screen_desktop_layout.columns /
screen_desktop_layout.rows) / 2,
diff --git a/openbox/screen.h b/openbox/screen.h
index a6a3995..af1aeb2 100644
--- a/openbox/screen.h
+++ b/openbox/screen.h
@@ -66,7 +66,7 @@ void screen_resize(void);
/*! Change the number of available desktops */
void screen_set_num_desktops(guint num);
/*! Change the current desktop */
-void screen_set_desktop(guint num, gboolean dofocus);
+void screen_set_desktop(guint num, gboolean dofocus, gboolean show_popup);
/*! 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 */
@@ -80,7 +80,7 @@ guint screen_find_desktop(guint from, ObDirection dir,
screen_hide_desktop_popup(). Otherwise it will hide after a
delay.
*/
-void screen_show_desktop_popup(guint d, gboolean permanent);
+void screen_show_desktop_popup(guint d, gboolean permanent, gboolean center);
/*! Hide it */
void screen_hide_desktop_popup(void);
Вроде очевидная фича, странно, что до сих пор нигде нет. Или это я в танке, и в каких-то других WM такое есть?