From fb5a3a89989276bba163e33fb37a10c761ee9444 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 9 Jun 2002 03:44:16 +0000 Subject: [PATCH] Apply big patch from blackc@speakeasy.net adding a popup window to the 2002-06-08 Havoc Pennington Apply big patch from blackc@speakeasy.net adding a popup window to the Ctrl+Alt+arrows shortcuts. #83940 2002-06-08 Havoc Pennington * 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. --- ChangeLog | 14 +++ src/common.h | 5 + src/display.c | 17 ++- src/keybindings.c | 303 +++++++++++++++++++++++++++++++++++++++------- src/prefs.c | 16 +++ src/prefs.h | 26 ++++ src/screen.c | 51 ++++++-- src/screen.h | 3 + src/stack.c | 2 +- src/tabpopup.c | 113 +++++++++-------- src/tabpopup.h | 34 +++--- src/workspace.c | 117 ++++++++++++++++-- src/workspace.h | 3 + 13 files changed, 568 insertions(+), 136 deletions(-) diff --git a/ChangeLog b/ChangeLog index 96e12fbd0..47105c594 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2002-06-08 Havoc Pennington + + Apply big patch from blackc@speakeasy.net adding a popup window + to the Ctrl+Alt+arrows shortcuts. #83940 + +2002-06-08 Havoc Pennington + + * 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 * src/display.c (meta_display_open): set net_supporting_wm_check diff --git a/src/common.h b/src/common.h index f7143e8d9..476e9ed85 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 f7144e8af..70b142981 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 79ddafe58..e561486c4 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,6 +1619,49 @@ handle_tab_forward (MetaDisplay *display, } } +static MetaWindow * +get_previous_focus_window (MetaDisplay *display, + MetaScreen *screen) +{ + 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; + } + + if (window && + !meta_window_visible_on_workspace (window, + screen->active_workspace)) + { + 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->active_workspace, + NULL, + TRUE); + } + + if (window && + !meta_window_visible_on_workspace (window, + screen->active_workspace)) + { + window = NULL; + } + + return window; +} + static void handle_focus_previous (MetaDisplay *display, MetaWindow *event_window, @@ -1510,36 +1680,8 @@ handle_focus_previous (MetaDisplay *display, if (screen == NULL) return; - window = NULL; + window = get_previous_focus_window (display, screen); - /* 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; - - if (window && - !meta_window_visible_on_workspace (window, - screen->active_workspace)) - 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->active_workspace, - NULL, - TRUE); - } - - if (window && - !meta_window_visible_on_workspace (window, - screen->active_workspace)) - window = NULL; - 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 010bf4d5f..af5f66f56 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 5531c1bf0..e273acb71 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 20aa302e8..0cfd051df 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 b76d7ac19..d8b938e30 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 b0926e467..ee7e74999 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 54f7828cc..e47629ac2 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 417c94172..67a0c748a 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 548e422e6..92d352ba6 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -19,6 +19,7 @@ * 02111-1307, USA. */ +#include #include "workspace.h" #include "errors.h" #include @@ -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 c55af458e..90c62a5b7 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