summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@pobox.com>2002-06-09 03:44:16 +0000
committerHavoc Pennington <hp@src.gnome.org>2002-06-09 03:44:16 +0000
commitfb5a3a89989276bba163e33fb37a10c761ee9444 (patch)
treecd40e5b6f93cbdf04acb9fe401ba55c2c494a5aa
parent459d8f9c9de631d3c9ad0012109969ca61473bb6 (diff)
downloadmetacity-fb5a3a89989276bba163e33fb37a10c761ee9444.tar.gz
Apply big patch from blackc@speakeasy.net adding a popup window to the
2002-06-08 Havoc Pennington <hp@pobox.com> Apply big patch from blackc@speakeasy.net adding a popup window to the Ctrl+Alt+arrows shortcuts. #83940 2002-06-08 Havoc Pennington <hp@pobox.com> * src/screen.c (meta_screen_new): select key press/release on the display->no_focus_window, another attempted fix for not getting keybindings when no window is focused. Still doesn't seem to work though. I don't get what's going wrong. (meta_create_offscreen_window): new function, used instead of XCreateSimpleWindow so we get override redirect offscreen windows.
-rw-r--r--ChangeLog14
-rw-r--r--src/common.h5
-rw-r--r--src/display.c17
-rw-r--r--src/keybindings.c289
-rw-r--r--src/prefs.c16
-rw-r--r--src/prefs.h26
-rw-r--r--src/screen.c51
-rw-r--r--src/screen.h3
-rw-r--r--src/stack.c2
-rw-r--r--src/tabpopup.c113
-rw-r--r--src/tabpopup.h34
-rw-r--r--src/workspace.c117
-rw-r--r--src/workspace.h3
13 files changed, 561 insertions, 129 deletions
diff --git a/ChangeLog b/ChangeLog
index 96e12fbd..47105c59 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
2002-06-08 Havoc Pennington <hp@pobox.com>
+ Apply big patch from blackc@speakeasy.net adding a popup window
+ to the Ctrl+Alt+arrows shortcuts. #83940
+
+2002-06-08 Havoc Pennington <hp@pobox.com>
+
+ * src/screen.c (meta_screen_new): select key press/release on the
+ display->no_focus_window, another attempted fix for not getting
+ keybindings when no window is focused. Still doesn't seem to work
+ though. I don't get what's going wrong.
+ (meta_create_offscreen_window): new function, used instead of
+ XCreateSimpleWindow so we get override redirect offscreen windows.
+
+2002-06-08 Havoc Pennington <hp@pobox.com>
+
* src/display.c (meta_display_open): set net_supporting_wm_check
in addition to win_supporting_wm_check, patch from
JeyaSudha for #83365
diff --git a/src/common.h b/src/common.h
index f7143e8d..476e9ed8 100644
--- a/src/common.h
+++ b/src/common.h
@@ -101,6 +101,11 @@ typedef enum
META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
META_GRAB_OP_KEYBOARD_TABBING_DOCK,
+
+ META_GRAB_OP_KEYBOARD_WORKSPACE_UP,
+ META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN,
+ META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT,
+ META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT,
/* Frame button ops */
META_GRAB_OP_CLICKING_MINIMIZE,
diff --git a/src/display.c b/src/display.c
index f7144e8a..70b14298 100644
--- a/src/display.c
+++ b/src/display.c
@@ -766,6 +766,10 @@ grab_op_is_keyboard (MetaGrabOp op)
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
case META_GRAB_OP_KEYBOARD_TABBING_NORMAL:
case META_GRAB_OP_KEYBOARD_TABBING_DOCK:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_UP:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT:
return TRUE;
break;
@@ -2251,6 +2255,13 @@ meta_display_begin_grab_op (MetaDisplay *display,
META_TAB_LIST_DOCKS);
break;
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_UP:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT:
+ meta_workspace_ensure_tab_popup (display, window->screen);
+ break;
+
default:
break;
}
@@ -2268,7 +2279,11 @@ meta_display_end_grab_op (MetaDisplay *display,
return;
if (display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_NORMAL ||
- display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_DOCK)
+ display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_DOCK ||
+ display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT ||
+ display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT ||
+ display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_UP ||
+ display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN)
{
meta_ui_tab_popup_free (display->grab_window->screen->tab_popup);
display->grab_window->screen->tab_popup = NULL;
diff --git a/src/keybindings.c b/src/keybindings.c
index 79ddafe5..e561486c 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -94,6 +94,10 @@ static void handle_move_to_workspace (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding);
+static void handle_workspace_forward (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
static void handle_raise_or_lower (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
@@ -115,6 +119,11 @@ static gboolean process_tab_grab (MetaDisplay *display,
XEvent *event,
KeySym keysym);
+static gboolean process_workspace_tab_grab (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ KeySym keysym);
+
static void regrab_screen_bindings (MetaDisplay *display);
static void regrab_window_bindings (MetaDisplay *display);
@@ -159,13 +168,13 @@ static const MetaKeyHandler screen_handlers[] = {
GINT_TO_POINTER (10) },
{ META_KEYBINDING_WORKSPACE_12, handle_activate_workspace,
GINT_TO_POINTER (11) },
- { META_KEYBINDING_WORKSPACE_LEFT, handle_activate_workspace,
+ { META_KEYBINDING_WORKSPACE_LEFT, handle_workspace_forward,
GINT_TO_POINTER (META_MOTION_LEFT) },
- { META_KEYBINDING_WORKSPACE_RIGHT, handle_activate_workspace,
+ { META_KEYBINDING_WORKSPACE_RIGHT, handle_workspace_forward,
GINT_TO_POINTER (META_MOTION_RIGHT) },
- { META_KEYBINDING_WORKSPACE_UP, handle_activate_workspace,
+ { META_KEYBINDING_WORKSPACE_UP, handle_workspace_forward,
GINT_TO_POINTER (META_MOTION_UP) },
- { META_KEYBINDING_WORKSPACE_DOWN, handle_activate_workspace,
+ { META_KEYBINDING_WORKSPACE_DOWN, handle_workspace_forward,
GINT_TO_POINTER (META_MOTION_DOWN) },
{ META_KEYBINDING_SWITCH_WINDOWS, handle_tab_forward,
GINT_TO_POINTER (META_TAB_LIST_NORMAL) },
@@ -593,10 +602,10 @@ meta_change_keygrab (MetaDisplay *display,
*/
meta_topic (META_DEBUG_KEYBINDINGS,
- "%s keybinding %s mask 0x%x\n",
+ "%s keybinding %s mask 0x%x on 0x%lx\n",
grab ? "Grabbing" : "Ungrabbing",
keysym_name (keysym),
- modmask);
+ modmask, xwindow);
ignored_mask = 0;
while (ignored_mask < (int) display->ignored_modifier_mask)
@@ -1062,7 +1071,7 @@ meta_display_process_key_event (MetaDisplay *display,
return;
}
-
+
if (display->grab_op == META_GRAB_OP_NONE)
return;
@@ -1088,6 +1097,15 @@ meta_display_process_key_event (MetaDisplay *display,
"Processing event for keyboard tabbing\n");
handled = process_tab_grab (display, window, event, keysym);
break;
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_UP:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT:
+ case META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT:
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Processing event for keyboard tabbing workspace\n");
+ handled = process_workspace_tab_grab (display, window, event, keysym);
+ break;
+
default:
break;
}
@@ -1213,6 +1231,7 @@ process_tab_grab (MetaDisplay *display,
KeySym keysym)
{
MetaScreen *screen;
+ MetaKeyBindingAction action;
window = NULL; /* be sure we don't use this, it's irrelevant */
@@ -1229,7 +1248,7 @@ process_tab_grab (MetaDisplay *display,
MetaWindow *target_window;
target_xwindow =
- meta_ui_tab_popup_get_selected (screen->tab_popup);
+ (Window) meta_ui_tab_popup_get_selected (screen->tab_popup);
target_window =
meta_display_lookup_x_window (display, target_xwindow);
@@ -1263,10 +1282,12 @@ process_tab_grab (MetaDisplay *display,
if (is_modifier (display, event->xkey.keycode))
return TRUE;
- switch (keysym)
+ action = meta_prefs_get_keybinding_action(keysym);
+
+ switch (action)
{
- case XK_ISO_Left_Tab:
- case XK_Tab:
+ case META_KEYBINDING_ACTION_SWITCH_PANELS:
+ case META_KEYBINDING_ACTION_SWITCH_WINDOWS:
if (event->xkey.state & ShiftMask)
meta_ui_tab_popup_backward (screen->tab_popup);
else
@@ -1339,7 +1360,7 @@ handle_activate_workspace (MetaDisplay *display,
MetaWorkspace *workspace;
which = GPOINTER_TO_INT (binding->handler->data);
-
+
workspace = NULL;
if (which < 0)
{
@@ -1369,6 +1390,112 @@ handle_activate_workspace (MetaDisplay *display,
}
}
+static gboolean
+process_workspace_tab_grab (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ KeySym keysym)
+{
+ MetaScreen *screen;
+ MetaWorkspace *workspace;
+
+ window = NULL; /* be sure we don't use this, it's irrelevant */
+
+ screen = display->grab_window->screen;
+
+ g_return_val_if_fail (screen->tab_popup != NULL, FALSE);
+
+ if (event->type == KeyRelease &&
+ keycode_is_primary_modifier (display, event->xkey.keycode,
+ display->grab_mask))
+ {
+ /* We're done, move to the new workspace. */
+ MetaWorkspace *target_workspace;
+
+ target_workspace =
+ (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->tab_popup);
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ending workspace tab operation, primary modifier released\n");
+ if (target_workspace)
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ending grab early so we can focus the target workspace\n");
+ meta_display_end_grab_op (display, event->xkey.time);
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Activating target workspace\n");
+
+ switch_to_workspace (display, target_workspace);
+
+ return TRUE; /* we already ended the grab */
+ }
+
+ return FALSE; /* end grab */
+ }
+
+ /* don't care about other releases, but eat them, don't end grab */
+ if (event->type == KeyRelease)
+ return TRUE;
+
+ /* don't end grab on modifier key presses */
+ if (is_modifier (display, event->xkey.keycode))
+ return TRUE;
+
+ /* select the next workspace in the tabpopup */
+ workspace =
+ (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->tab_popup);
+
+ if (workspace)
+ {
+ MetaWorkspace *target_workspace;
+ MetaKeyBindingAction action;
+
+ action = meta_prefs_get_keybinding_action(keysym);
+
+ switch (action)
+ {
+ case META_KEYBINDING_ACTION_WORKSPACE_UP:
+ target_workspace = meta_workspace_get_neighbor (workspace,
+ META_MOTION_UP);
+ break;
+
+ case META_KEYBINDING_ACTION_WORKSPACE_DOWN:
+ target_workspace = meta_workspace_get_neighbor (workspace,
+ META_MOTION_DOWN);
+ break;
+
+ case META_KEYBINDING_ACTION_WORKSPACE_LEFT:
+ target_workspace = meta_workspace_get_neighbor (workspace,
+ META_MOTION_LEFT);
+ break;
+
+ case META_KEYBINDING_ACTION_WORKSPACE_RIGHT:
+ target_workspace = meta_workspace_get_neighbor (workspace,
+ META_MOTION_RIGHT);
+ break;
+
+ default:
+ target_workspace = NULL;
+ break;
+ }
+
+ if (target_workspace)
+ {
+ meta_ui_tab_popup_select (screen->tab_popup,
+ (MetaTabEntryKey) target_workspace);
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Tab key pressed, moving tab focus in popup\n");
+ return TRUE;
+ }
+ }
+
+ /* end grab */
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ending workspace tabbing, uninteresting key pressed\n");
+ return FALSE;
+}
+
static void
handle_toggle_desktop (MetaDisplay *display,
MetaWindow *window,
@@ -1484,7 +1611,7 @@ handle_tab_forward (MetaDisplay *display,
0, 0))
{
meta_ui_tab_popup_select (window->screen->tab_popup,
- window->xwindow);
+ (MetaTabEntryKey) window->xwindow);
/* only after selecting proper window */
meta_ui_tab_popup_set_showing (window->screen->tab_popup,
TRUE);
@@ -1492,44 +1619,34 @@ handle_tab_forward (MetaDisplay *display,
}
}
-static void
-handle_focus_previous (MetaDisplay *display,
- MetaWindow *event_window,
- XEvent *event,
- MetaKeyBinding *binding)
+static MetaWindow *
+get_previous_focus_window (MetaDisplay *display,
+ MetaScreen *screen)
{
- MetaWindow *window;
- MetaScreen *screen;
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Focus previous window\n");
-
- screen = meta_display_screen_for_root (display,
- event->xkey.root);
-
- if (screen == NULL)
- return;
-
- window = NULL;
+ MetaWindow *window = NULL;
/* get previously-focused window, front of list is currently
* focused window
*/
if (display->mru_list &&
display->mru_list->next)
- window = display->mru_list->next->data;
+ {
+ window = display->mru_list->next->data;
+ }
if (window &&
!meta_window_visible_on_workspace (window,
screen->active_workspace))
- window = NULL;
+ {
+ window = NULL;
+ }
if (window == NULL)
{
/* Pick first window in tab order */
window = meta_display_get_tab_next (screen->display,
META_TAB_LIST_NORMAL,
- screen,
+ screen,
screen->active_workspace,
NULL,
TRUE);
@@ -1538,8 +1655,33 @@ handle_focus_previous (MetaDisplay *display,
if (window &&
!meta_window_visible_on_workspace (window,
screen->active_workspace))
- window = NULL;
+ {
+ window = NULL;
+ }
+
+ return window;
+}
+
+static void
+handle_focus_previous (MetaDisplay *display,
+ MetaWindow *event_window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ MetaWindow *window;
+ MetaScreen *screen;
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Focus previous window\n");
+
+ screen = meta_display_screen_for_root (display,
+ event->xkey.root);
+
+ if (screen == NULL)
+ return;
+
+ window = get_previous_focus_window (display, screen);
+
if (window)
{
meta_window_raise (window);
@@ -1753,6 +1895,83 @@ handle_raise_or_lower (MetaDisplay *display,
}
}
+static MetaGrabOp
+op_from_motion_direction (MetaMotionDirection motion)
+{
+ switch (motion)
+ {
+ case META_MOTION_UP:
+ return META_GRAB_OP_KEYBOARD_WORKSPACE_UP;
+ case META_MOTION_DOWN:
+ return META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN;
+ case META_MOTION_LEFT:
+ return META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT;
+ case META_MOTION_RIGHT:
+ return META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT;
+ }
+
+ g_assert_not_reached ();
+
+ return 0;
+}
+
+static void
+handle_workspace_forward (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ int motion;
+ MetaScreen *screen;
+
+ motion = GPOINTER_TO_INT (binding->handler->data);
+
+ g_assert (motion < 0);
+
+ screen = meta_display_screen_for_root (display,
+ event->xkey.root);
+ if (screen == NULL)
+ return;
+
+ if (display->focus_window != NULL)
+ {
+ window = display->focus_window;
+ }
+ else if (window == NULL)
+ {
+ window = get_previous_focus_window (display, screen);
+ }
+
+ if (window)
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Starting tab between workspaces, showing popup\n");
+
+ if (meta_display_begin_grab_op (display,
+ window,
+ op_from_motion_direction (motion),
+ FALSE,
+ 0,
+ event->xkey.state & ~(display->ignored_modifier_mask),
+ event->xkey.time,
+ 0, 0))
+ {
+ MetaWorkspace *next;
+
+ next = meta_workspace_get_neighbor(window->screen->active_workspace,
+ motion);
+ g_assert (next);
+
+ meta_ui_tab_popup_select (window->screen->tab_popup,
+ (MetaTabEntryKey) next);
+
+ /* only after selecting proper window */
+ meta_ui_tab_popup_set_showing (window->screen->tab_popup,
+ TRUE);
+ }
+ }
+}
+
static void
handle_spew_mark (MetaDisplay *display,
MetaWindow *window,
diff --git a/src/prefs.c b/src/prefs.c
index 010bf4d5..af5f66f5 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -1031,3 +1031,19 @@ meta_prefs_get_auto_raise_delay ()
{
return auto_raise_delay;
}
+
+MetaKeyBindingAction
+meta_prefs_get_keybinding_action (unsigned int keysym)
+{
+ int i;
+
+ for (i = (int) G_N_ELEMENTS (screen_bindings) - 1; i >= 0; --i)
+ {
+ if (screen_bindings[i].keysym == keysym)
+ {
+ return (MetaKeyBindingAction) i;
+ }
+ }
+ return META_KEYBINDING_ACTION_NONE;
+}
+
diff --git a/src/prefs.h b/src/prefs.h
index 5531c1bf..e273acb7 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -113,6 +113,31 @@ void meta_prefs_set_num_workspaces (int n_workspaces);
#define META_KEYBINDING_MOVE_WORKSPACE_DOWN "move_to_workspace_down"
#define META_KEYBINDING_RAISE_OR_LOWER "raise_or_lower"
+typedef enum _MetaKeyBindingAction
+{
+ META_KEYBINDING_ACTION_NONE = -1,
+ META_KEYBINDING_ACTION_WORKSPACE_1,
+ META_KEYBINDING_ACTION_WORKSPACE_2,
+ META_KEYBINDING_ACTION_WORKSPACE_3,
+ META_KEYBINDING_ACTION_WORKSPACE_4,
+ META_KEYBINDING_ACTION_WORKSPACE_5,
+ META_KEYBINDING_ACTION_WORKSPACE_6,
+ META_KEYBINDING_ACTION_WORKSPACE_7,
+ META_KEYBINDING_ACTION_WORKSPACE_8,
+ META_KEYBINDING_ACTION_WORKSPACE_9,
+ META_KEYBINDING_ACTION_WORKSPACE_10,
+ META_KEYBINDING_ACTION_WORKSPACE_11,
+ META_KEYBINDING_ACTION_WORKSPACE_12,
+ META_KEYBINDING_ACTION_WORKSPACE_LEFT,
+ META_KEYBINDING_ACTION_WORKSPACE_RIGHT,
+ META_KEYBINDING_ACTION_WORKSPACE_UP,
+ META_KEYBINDING_ACTION_WORKSPACE_DOWN,
+ META_KEYBINDING_ACTION_SWITCH_WINDOWS,
+ META_KEYBINDING_ACTION_SWITCH_PANELS,
+ META_KEYBINDING_ACTION_FOCUS_PREVIOUS,
+ META_KEYBINDING_ACTION_SHOW_DESKTOP
+} MetaKeyBindingAction;
+
typedef struct
{
const char *name;
@@ -124,6 +149,7 @@ void meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
int *n_bindings);
void meta_prefs_get_window_bindings (const MetaKeyPref **bindings,
int *n_bindings);
+MetaKeyBindingAction meta_prefs_get_keybinding_action (unsigned int keysym);
#endif
diff --git a/src/screen.c b/src/screen.c
index 20aa302e..0cfd051d 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -223,8 +223,7 @@ meta_screen_new (MetaDisplay *display,
current_wm_sn_owner = None; /* don't wait for it to die later on */
}
- new_wm_sn_owner = XCreateSimpleWindow (xdisplay, xroot,
- -100, -100, 1, 1, 0, 0, 0);
+ new_wm_sn_owner = meta_create_offscreen_window (xdisplay, xroot);
{
/* Generate a timestamp */
@@ -441,17 +440,16 @@ meta_screen_new (MetaDisplay *display,
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
if (display->leader_window == None)
- display->leader_window = XCreateSimpleWindow (display->xdisplay,
- screen->xroot,
- -100, -100, 1, 1, 0, 0, 0);
-
+ display->leader_window = meta_create_offscreen_window (display->xdisplay,
+ screen->xroot);
+
if (display->no_focus_window == None)
{
- display->no_focus_window = XCreateSimpleWindow (display->xdisplay,
- screen->xroot,
- -100, -100, 1, 1, 0, 0, 0);
+ display->no_focus_window = meta_create_offscreen_window (display->xdisplay,
+ screen->xroot);
+
XSelectInput (display->xdisplay, display->no_focus_window,
- FocusChangeMask);
+ FocusChangeMask | KeyPressMask | KeyReleaseMask);
XMapWindow (display->xdisplay, display->no_focus_window);
}
@@ -857,7 +855,7 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
len = g_slist_length (tab_list);
entries = g_new (MetaTabEntry, len + 1);
- entries[len].xwindow = None;
+ entries[len].key = NULL;
entries[len].title = NULL;
entries[len].icon = NULL;
@@ -870,7 +868,7 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
window = tmp->data;
- entries[i].xwindow = window->xwindow;
+ entries[i].key = (MetaTabEntryKey) window->xwindow;
entries[i].title = window->title;
entries[i].icon = window->icon;
meta_window_get_outer_rect (window, &r);
@@ -910,7 +908,11 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
tmp = tmp->next;
}
- screen->tab_popup = meta_ui_tab_popup_new (entries, screen->number);
+ screen->tab_popup = meta_ui_tab_popup_new (entries,
+ screen->number,
+ len,
+ 5, /* FIXME */
+ TRUE);
g_free (entries);
g_slist_free (tab_list);
@@ -1109,3 +1111,26 @@ meta_screen_update_workspace_layout (MetaScreen *screen)
screen->columns_of_workspaces,
screen->vertical_workspaces);
}
+
+Window
+meta_create_offscreen_window (Display *xdisplay,
+ Window parent)
+{
+ XSetWindowAttributes attrs;
+
+ /* we want to be override redirect because sometimes we
+ * create a window on a screen we aren't managing.
+ * (but on a display we are managing at least one screen for)
+ */
+ attrs.override_redirect = True;
+
+ return XCreateWindow (xdisplay,
+ parent,
+ -100, -100, 1, 1,
+ 0,
+ CopyFromParent,
+ CopyFromParent,
+ CopyFromParent,
+ CWOverrideRedirect,
+ &attrs);
+}
diff --git a/src/screen.h b/src/screen.h
index b76d7ac1..d8b938e3 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -107,6 +107,9 @@ const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *s
void meta_screen_update_workspace_layout (MetaScreen *screen);
+Window meta_create_offscreen_window (Display *xdisplay,
+ Window parent);
+
#endif
diff --git a/src/stack.c b/src/stack.c
index b0926e46..ee7e7499 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -1017,7 +1017,7 @@ meta_stack_get_default_focus_window (MetaStack *stack,
if (topmost_dock == NULL &&
window->type == META_WINDOW_DOCK)
topmost_dock = window;
- else
+ else if (window->type != META_WINDOW_DOCK)
return window;
}
diff --git a/src/tabpopup.c b/src/tabpopup.c
index 54f7828c..e47629ac 100644
--- a/src/tabpopup.c
+++ b/src/tabpopup.c
@@ -34,12 +34,12 @@ typedef struct _TabEntry TabEntry;
struct _TabEntry
{
- Window xwindow;
- char *title;
- GdkPixbuf *icon;
- GtkWidget *widget;
- GdkRectangle rect;
- GdkRectangle inner_rect;
+ MetaTabEntryKey key;
+ char *title;
+ GdkPixbuf *icon;
+ GtkWidget *widget;
+ GdkRectangle rect;
+ GdkRectangle inner_rect;
};
struct _MetaTabPopup
@@ -50,6 +50,7 @@ struct _MetaTabPopup
GList *entries;
TabEntry *current_selected_entry;
GtkWidget *outline_window;
+ gboolean outline;
};
static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf);
@@ -67,7 +68,7 @@ outline_window_expose (GtkWidget *widget,
popup = data;
- if (popup->current_selected_entry == NULL)
+ if (!popup->outline || popup->current_selected_entry == NULL)
return FALSE;
te = popup->current_selected_entry;
@@ -86,19 +87,21 @@ outline_window_expose (GtkWidget *widget,
FALSE,
te->inner_rect.x - 1, te->inner_rect.y - 1,
te->inner_rect.width + 1,
- te->inner_rect.height + 1);
-
+ te->inner_rect.height + 1);
+
return FALSE;
}
MetaTabPopup*
meta_ui_tab_popup_new (const MetaTabEntry *entries,
- int screen_number)
+ int screen_number,
+ int entry_count,
+ int width,
+ gboolean outline)
{
MetaTabPopup *popup;
int i, left, right, top, bottom;
GList *tab_entries;
- int width;
int height;
GtkWidget *table;
GtkWidget *vbox;
@@ -137,38 +140,39 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries,
popup->current = NULL;
popup->entries = NULL;
popup->current_selected_entry = NULL;
+ popup->outline = outline;
tab_entries = NULL;
- i = 0;
- while (entries[i].xwindow != None)
+ for (i = 0; i < entry_count; ++i)
{
TabEntry *te;
te = g_new (TabEntry, 1);
- te->xwindow = entries[i].xwindow;
+ te->key = entries[i].key;
te->title = g_strdup (entries[i].title);
te->icon = entries[i].icon;
g_object_ref (G_OBJECT (te->icon));
te->widget = NULL;
- te->rect.x = entries[i].x;
- te->rect.y = entries[i].y;
- te->rect.width = entries[i].width;
- te->rect.height = entries[i].height;
+ if (outline)
+ {
+ te->rect.x = entries[i].x;
+ te->rect.y = entries[i].y;
+ te->rect.width = entries[i].width;
+ te->rect.height = entries[i].height;
+
+ te->inner_rect.x = entries[i].inner_x;
+ te->inner_rect.y = entries[i].inner_y;
+ te->inner_rect.width = entries[i].inner_width;
+ te->inner_rect.height = entries[i].inner_height;
+ }
- te->inner_rect.x = entries[i].inner_x;
- te->inner_rect.y = entries[i].inner_y;
- te->inner_rect.width = entries[i].inner_width;
- te->inner_rect.height = entries[i].inner_height;
-
tab_entries = g_list_prepend (tab_entries, te);
-
- ++i;
}
popup->entries = g_list_reverse (tab_entries);
- width = 5; /* FIXME */
+ g_assert (width > 0);
height = i / width;
if (i % width)
height += 1;
@@ -316,36 +320,39 @@ display_entry (MetaTabPopup *popup,
gtk_label_set_text (GTK_LABEL (popup->label), te->title);
select_image (te->widget);
- /* Do stuff behind gtk's back */
- gdk_window_hide (popup->outline_window->window);
- meta_core_increment_event_serial (gdk_display);
+ if (popup->outline)
+ {
+ /* Do stuff behind gtk's back */
+ gdk_window_hide (popup->outline_window->window);
+ meta_core_increment_event_serial (gdk_display);
- rect = te->rect;
- rect.x = 0;
- rect.y = 0;
+ rect = te->rect;
+ rect.x = 0;
+ rect.y = 0;
- gdk_window_move_resize (popup->outline_window->window,
- te->rect.x, te->rect.y,
- te->rect.width, te->rect.height);
+ gdk_window_move_resize (popup->outline_window->window,
+ te->rect.x, te->rect.y,
+ te->rect.width, te->rect.height);
- gdk_window_set_background (popup->outline_window->window,
- &popup->outline_window->style->black);
+ gdk_window_set_background (popup->outline_window->window,
+ &popup->outline_window->style->black);
- region = gdk_region_rectangle (&rect);
- inner_region = gdk_region_rectangle (&te->inner_rect);
- gdk_region_subtract (region, inner_region);
- gdk_region_destroy (inner_region);
+ region = gdk_region_rectangle (&rect);
+ inner_region = gdk_region_rectangle (&te->inner_rect);
+ gdk_region_subtract (region, inner_region);
+ gdk_region_destroy (inner_region);
- gdk_window_shape_combine_region (popup->outline_window->window,
- region,
- 0, 0);
+ gdk_window_shape_combine_region (popup->outline_window->window,
+ region,
+ 0, 0);
- gdk_region_destroy (region);
+ gdk_region_destroy (region);
- /* This should piss off gtk a bit, but we don't want to raise
- * above the tab popup
- */
- gdk_window_show_unraised (popup->outline_window->window);
+ /* This should piss off gtk a bit, but we don't want to raise
+ * above the tab popup
+ */
+ gdk_window_show_unraised (popup->outline_window->window);
+ }
/* Must be before we handle an expose for the outline window */
popup->current_selected_entry = te;
@@ -389,7 +396,7 @@ meta_ui_tab_popup_backward (MetaTabPopup *popup)
}
}
-Window
+MetaTabEntryKey
meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
{
if (popup->current)
@@ -398,7 +405,7 @@ meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
te = popup->current->data;
- return te->xwindow;
+ return te->key;
}
else
return None;
@@ -406,7 +413,7 @@ meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
void
meta_ui_tab_popup_select (MetaTabPopup *popup,
- Window xwindow)
+ MetaTabEntryKey key)
{
GList *tmp;
@@ -417,7 +424,7 @@ meta_ui_tab_popup_select (MetaTabPopup *popup,
te = tmp->data;
- if (te->xwindow == xwindow)
+ if (te->key == key)
{
popup->current = tmp;
diff --git a/src/tabpopup.h b/src/tabpopup.h
index 417c9417..67a0c748 100644
--- a/src/tabpopup.h
+++ b/src/tabpopup.h
@@ -30,26 +30,30 @@
typedef struct _MetaTabEntry MetaTabEntry;
typedef struct _MetaTabPopup MetaTabPopup;
+typedef void *MetaTabEntryKey;
struct _MetaTabEntry
{
- Window xwindow;
- const char *title;
- GdkPixbuf *icon;
- int x, y, width, height;
- int inner_x, inner_y, inner_width, inner_height;
+ MetaTabEntryKey key;
+ const char *title;
+ GdkPixbuf *icon;
+ int x, y, width, height;
+ int inner_x, inner_y, inner_width, inner_height;
};
-MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries,
- int screen_number);
-void meta_ui_tab_popup_free (MetaTabPopup *popup);
-void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
- gboolean showing);
-void meta_ui_tab_popup_forward (MetaTabPopup *popup);
-void meta_ui_tab_popup_backward (MetaTabPopup *popup);
-Window meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
-void meta_ui_tab_popup_select (MetaTabPopup *popup,
- Window xwindow);
+MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries,
+ int screen_number,
+ int entry_count,
+ int width,
+ gboolean outline);
+void meta_ui_tab_popup_free (MetaTabPopup *popup);
+void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
+ gboolean showing);
+void meta_ui_tab_popup_forward (MetaTabPopup *popup);
+void meta_ui_tab_popup_backward (MetaTabPopup *popup);
+MetaTabEntryKey meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
+void meta_ui_tab_popup_select (MetaTabPopup *popup,
+ MetaTabEntryKey key);
#endif
diff --git a/src/workspace.c b/src/workspace.c
index 548e422e..92d352ba 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -19,6 +19,7 @@
* 02111-1307, USA.
*/
+#include <config.h>
#include "workspace.h"
#include "errors.h"
#include <X11/Xatom.h>
@@ -512,16 +513,11 @@ meta_workspace_get_work_area (MetaWorkspace *workspace,
*area = workspace->work_area;
}
-MetaWorkspace*
-meta_workspace_get_neighbor (MetaWorkspace *workspace,
- MetaMotionDirection direction)
+static void
+calc_rows_and_cols (MetaScreen *screen, int num_workspaces, int *r, int *c)
{
- int i, num_workspaces, grid_area;
- int rows, cols;
-
- i = meta_workspace_index (workspace);
- num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
-
+ int cols, rows;
+
/*
* 3 rows, 4 columns, horizontal layout:
* +--+--+--+--+
@@ -543,8 +539,8 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
*
*/
- rows = workspace->screen->rows_of_workspaces;
- cols = workspace->screen->columns_of_workspaces;
+ rows = screen->rows_of_workspaces;
+ cols = screen->columns_of_workspaces;
if (rows <= 0 && cols <= 0)
cols = num_workspaces;
@@ -559,6 +555,22 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
if (cols < 1)
cols = 1;
+ *r = rows;
+ *c = cols;
+}
+
+MetaWorkspace*
+meta_workspace_get_neighbor (MetaWorkspace *workspace,
+ MetaMotionDirection direction)
+{
+ int i, num_workspaces, grid_area;
+ int rows, cols;
+
+ i = meta_workspace_index (workspace);
+ num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
+
+ calc_rows_and_cols (workspace->screen, num_workspaces, &rows, &cols);
+
grid_area = rows * cols;
meta_verbose ("Getting neighbor rows = %d cols = %d vert = %d "
@@ -640,3 +652,86 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
return meta_display_get_workspace_by_index (workspace->screen->display,
i);
}
+
+void
+meta_workspace_ensure_tab_popup (MetaDisplay *display,
+ MetaScreen *screen)
+{
+ MetaTabEntry *entries;
+ GdkPixbuf *icon;
+ int len, rows, cols;
+ int i;
+
+ if (screen->tab_popup)
+ return;
+
+ icon = meta_ui_get_default_window_icon (NULL);
+
+ len = meta_screen_get_n_workspaces (screen);
+
+ entries = g_new (MetaTabEntry, len + 1);
+ entries[len].key = NULL;
+ entries[len].title = NULL;
+ entries[len].icon = NULL;
+
+ calc_rows_and_cols (screen, len, &rows, &cols);
+
+ if (screen->vertical_workspaces)
+ {
+ int j, k;
+
+ for (i = 0; i < rows; ++i)
+ {
+ for (j = 0; j < cols; ++j)
+ {
+ MetaWorkspace *workspace;
+ char *title;
+
+ k = i + (j * rows);
+ workspace = meta_display_get_workspace_by_index (display, k);
+
+ g_assert (workspace);
+
+ title = g_strdup_printf (_("Workspace %d"), k + 1);
+
+ entries[i].key = (MetaTabEntryKey) workspace;
+ entries[i].title = title;
+ entries[i].icon = icon;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < len; ++i)
+ {
+ MetaWorkspace *workspace;
+ char *title;
+
+ workspace = meta_display_get_workspace_by_index (display, i);
+
+ g_assert (workspace);
+
+ title = g_strdup_printf (_("Workspace %d"), i + 1);
+
+ entries[i].key = (MetaTabEntryKey) workspace;
+ entries[i].title = title;
+ entries[i].icon = icon;
+ }
+ }
+
+ screen->tab_popup = meta_ui_tab_popup_new (entries,
+ screen->number,
+ len,
+ cols,
+ FALSE);
+
+ for (i = 0; i < len; ++i)
+ g_free((void *) entries[i].title);
+
+ g_free (entries);
+
+ g_object_unref (G_OBJECT (icon));
+
+ /* don't show tab popup, since proper window isn't selected yet */
+}
+
diff --git a/src/workspace.h b/src/workspace.h
index c55af458..90c62a5b 100644
--- a/src/workspace.h
+++ b/src/workspace.h
@@ -69,6 +69,9 @@ void meta_workspace_get_work_area (MetaWorkspace *workspace,
MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace,
MetaMotionDirection direction);
+void meta_workspace_ensure_tab_popup (MetaDisplay *display,
+ MetaScreen *screen);
+
#endif