diff --git a/ChangeLog b/ChangeLog index 0347ca6bf..077c43044 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +2002-06-26 Mark McLoughlin + + Fixes not being able to tab out of a + workspace which contains no windows. + + * src/core.c: (meta_core_begin_grab_op): upd + for meta_display_begin_grab_op change. + (meta_core_get_grab_frame): allow for + grab_window == NULL. + + * src/display.[ch]: + (meta_display_screen_for_xwindow): implement. + (meta_display_begin_grab_op): grab on the root window + if window == NULL. + (meta_display_end_grab_op): use grab_screen instead of + grab_window. + + * src/keybindings.c: + (grab_all_keys_and_keyboard): split out from + meta_window_grab_all_keys. + (ungrab_all_keys_and_keyboard): split out from + meta_window_ungrab_all_keys. + (meta_screen_grab_all_keys), (meta_screen_ungrab_all_keys): + implement grabbing and ungrabbing on the root window. + (meta_display_process_key_event): if window == NULL, + check the event is from the same screen and process. Only + happens with workspace switching. + (process_workspace_switch_grab): kill window param and + don't use grab_window. + (handle_tab_forward), (handle_begin_move): upd for + meta_display_begin_grab_op change. + (handle_workspace_switch): remove brokeness. Always do + the grab op on the root window. + + * src/keybindings.h: add meta_screen_{un}grab_all_keys. + + * src/window.c: (meta_window_client_message), (menu_callback): + update for meta_display_begin_grab_op change. + 2002-06-25 Mark McLoughlin * src/fixedtip.c: (meta_fixed_tip_show): diff --git a/src/core.c b/src/core.c index 6f0565e18..eef5d8e6d 100644 --- a/src/core.c +++ b/src/core.c @@ -519,14 +519,16 @@ meta_core_begin_grab_op (Display *xdisplay, { MetaDisplay *display; MetaWindow *window; + MetaScreen *screen; display = meta_display_for_x_display (xdisplay); + screen = meta_display_screen_for_xwindow (display, frame_xwindow); window = meta_display_lookup_x_window (display, frame_xwindow); if (window == NULL || window->frame == NULL) meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); - return meta_display_begin_grab_op (display, window, + return meta_display_begin_grab_op (display, screen, window, op, pointer_already_grabbed, button, modmask, timestamp, root_x, root_y); @@ -562,11 +564,12 @@ meta_core_get_grab_frame (Display *xdisplay) g_assert (display != NULL); g_assert (display->grab_op == META_GRAB_OP_NONE || - display->grab_window != NULL); + display->grab_screen != NULL); g_assert (display->grab_op == META_GRAB_OP_NONE || - display->grab_window->display->xdisplay == xdisplay); + display->grab_screen->display->xdisplay == xdisplay); if (display->grab_op != META_GRAB_OP_NONE && + display->grab_window && display->grab_window->frame) return display->grab_window->frame->xwindow; else diff --git a/src/display.c b/src/display.c index 74160c6f6..cd5af0ffb 100644 --- a/src/display.c +++ b/src/display.c @@ -440,6 +440,7 @@ meta_display_open (const char *name) display->grab_op = META_GRAB_OP_NONE; display->grab_window = NULL; + display->grab_screen = NULL; display->grab_resize_popup = NULL; set_utf8_string_hint (display, @@ -632,6 +633,17 @@ meta_display_screen_for_root (MetaDisplay *display, return NULL; } +MetaScreen* +meta_display_screen_for_xwindow (MetaDisplay *display, + Window xwindow) +{ + XWindowAttributes attr; + + XGetWindowAttributes (display->xdisplay, xwindow, &attr); + + return meta_display_screen_for_x_screen (display, attr.screen); +} + MetaScreen* meta_display_screen_for_x_screen (MetaDisplay *display, Screen *xscreen) @@ -1076,6 +1088,7 @@ event_callback (XEvent *event, op = META_GRAB_OP_RESIZING_SE; meta_display_begin_grab_op (display, + window->screen, window, op, TRUE, @@ -1098,6 +1111,7 @@ event_callback (XEvent *event, if (begin_move && window->has_move_func) { meta_display_begin_grab_op (display, + window->screen, window, META_GRAB_OP_MOVING, TRUE, @@ -2160,6 +2174,7 @@ xcursor_for_op (MetaDisplay *display, gboolean meta_display_begin_grab_op (MetaDisplay *display, + MetaScreen *screen, MetaWindow *window, MetaGrabOp op, gboolean pointer_already_grabbed, @@ -2174,16 +2189,20 @@ meta_display_begin_grab_op (MetaDisplay *display, meta_topic (META_DEBUG_WINDOW_OPS, "Doing grab op %d on window %s button %d pointer already grabbed: %d\n", - op, window->desc, button, pointer_already_grabbed); + op, window ? window->desc : "(null)", button, pointer_already_grabbed); if (display->grab_op != META_GRAB_OP_NONE) { meta_warning ("Attempt to perform window operation %d on window %s when operation %d on %s already in effect\n", - op, window->desc, display->grab_op, display->grab_window->desc); + op, window ? window->desc : "(null)", display->grab_op, + display->grab_window ? display->grab_window->desc : "(null)"); return FALSE; } - grab_xwindow = window->frame ? window->frame->xwindow : window->xwindow; + if (window) + grab_xwindow = window->frame ? window->frame->xwindow : window->xwindow; + else + grab_xwindow = screen->xroot; if (pointer_already_grabbed) display->grab_have_pointer = TRUE; @@ -2227,7 +2246,11 @@ meta_display_begin_grab_op (MetaDisplay *display, if (grab_op_is_keyboard (op)) { - if (meta_window_grab_all_keys (window)) + if (window) + display->grab_have_keyboard = + meta_window_grab_all_keys (window); + + else if (meta_screen_grab_all_keys (screen)) display->grab_have_keyboard = TRUE; if (!display->grab_have_keyboard) @@ -2240,45 +2263,50 @@ meta_display_begin_grab_op (MetaDisplay *display, display->grab_op = op; display->grab_window = window; + display->grab_screen = screen; display->grab_xwindow = grab_xwindow; display->grab_button = button; display->grab_mask = modmask; display->grab_root_x = root_x; display->grab_root_y = root_y; - display->grab_initial_window_pos = display->grab_window->rect; - meta_window_get_position (display->grab_window, - &display->grab_initial_window_pos.x, - &display->grab_initial_window_pos.y); + if (display->grab_window) + { + display->grab_initial_window_pos = display->grab_window->rect; + meta_window_get_position (display->grab_window, + &display->grab_initial_window_pos.x, + &display->grab_initial_window_pos.y); + } meta_topic (META_DEBUG_WINDOW_OPS, "Grab op %d on window %s successful\n", - display->grab_op, display->grab_window->desc); + display->grab_op, window ? window->desc : "(null)"); - g_assert (display->grab_window != NULL); + g_assert (display->grab_window != NULL || display->grab_screen != NULL); g_assert (display->grab_op != META_GRAB_OP_NONE); /* Do this last, after everything is set up. */ switch (op) { case META_GRAB_OP_KEYBOARD_TABBING_NORMAL: - meta_screen_ensure_tab_popup (window->screen, + meta_screen_ensure_tab_popup (screen, META_TAB_LIST_NORMAL); break; case META_GRAB_OP_KEYBOARD_TABBING_DOCK: - meta_screen_ensure_tab_popup (window->screen, + meta_screen_ensure_tab_popup (screen, META_TAB_LIST_DOCKS); break; case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: - meta_screen_ensure_workspace_popup (window->screen); + meta_screen_ensure_workspace_popup (screen); break; default: break; } - meta_window_refresh_resize_popup (display->grab_window); + if (display->grab_window) + meta_window_refresh_resize_popup (display->grab_window); return TRUE; } @@ -2294,8 +2322,8 @@ meta_display_end_grab_op (MetaDisplay *display, display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_DOCK || display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING) { - meta_ui_tab_popup_free (display->grab_window->screen->tab_popup); - display->grab_window->screen->tab_popup = NULL; + meta_ui_tab_popup_free (display->grab_screen->tab_popup); + display->grab_screen->tab_popup = NULL; /* If the ungrab here causes an EnterNotify, ignore it for * sloppy focus @@ -2315,10 +2343,14 @@ meta_display_end_grab_op (MetaDisplay *display, { meta_topic (META_DEBUG_WINDOW_OPS, "Ungrabbing all keys\n"); - meta_window_ungrab_all_keys (display->grab_window); + if (display->grab_window) + meta_window_ungrab_all_keys (display->grab_window); + else + meta_screen_ungrab_all_keys (display->grab_screen); } display->grab_window = NULL; + display->grab_screen = NULL; display->grab_xwindow = None; display->grab_op = META_GRAB_OP_NONE; diff --git a/src/display.h b/src/display.h index 0f03c950f..35313ad19 100644 --- a/src/display.h +++ b/src/display.h @@ -192,6 +192,7 @@ struct _MetaDisplay /* current window operation */ MetaGrabOp grab_op; + MetaScreen *grab_screen; MetaWindow *grab_window; Window grab_xwindow; int grab_button; @@ -231,6 +232,8 @@ MetaScreen* meta_display_screen_for_root (MetaDisplay *display, Window xroot); MetaScreen* meta_display_screen_for_x_screen (MetaDisplay *display, Screen *screen); +MetaScreen* meta_display_screen_for_xwindow (MetaDisplay *display, + Window xindow); void meta_display_grab (MetaDisplay *display); void meta_display_ungrab (MetaDisplay *display); gboolean meta_display_is_double_click (MetaDisplay *display); @@ -267,6 +270,7 @@ Cursor meta_display_create_x_cursor (MetaDisplay *display, MetaCursor cursor); gboolean meta_display_begin_grab_op (MetaDisplay *display, + MetaScreen *screen, MetaWindow *window, MetaGrabOp op, gboolean pointer_already_grabbed, diff --git a/src/keybindings.c b/src/keybindings.c index 58ea46d0b..ca897d9fc 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -125,7 +125,6 @@ static gboolean process_tab_grab (MetaDisplay *display, KeySym keysym); static gboolean process_workspace_switch_grab (MetaDisplay *display, - MetaWindow *window, XEvent *event, KeySym keysym); @@ -782,11 +781,113 @@ meta_window_ungrab_keys (MetaWindow *window) } } +static gboolean +grab_all_keys_and_keyboard (MetaDisplay *display, + Window xwindow) +{ + int result; + + meta_error_trap_push (display); + XGrabKey (display->xdisplay, AnyKey, AnyModifier, + xwindow, True, + GrabModeAsync, GrabModeAsync); + + result = meta_error_trap_pop (display); + if (result != Success) + { + meta_topic (META_DEBUG_KEYBINDINGS, + "Global key grab failed\n"); + return FALSE; + } + + /* Also grab the keyboard, so we get key releases and all key + * presses + */ + meta_error_trap_push (display); + + XGrabKeyboard (display->xdisplay, + xwindow, True, + GrabModeAsync, GrabModeAsync, + meta_display_get_current_time (display)); + + result = meta_error_trap_pop (display); + if (result != Success) + { + meta_topic (META_DEBUG_KEYBINDINGS, + "XGrabKeyboard() failed\n"); + return FALSE; + } + + meta_topic (META_DEBUG_KEYBINDINGS, "Grabbed all keys\n"); + + return TRUE; +} + +static void +ungrab_all_keys_and_keyboard (MetaDisplay *display, + Window xwindow) +{ + Time timestamp; + + timestamp = meta_display_get_current_time (display); + + meta_error_trap_push (display); + XUngrabKey (display->xdisplay, + AnyKey, AnyModifier, + xwindow); + + meta_topic (META_DEBUG_KEYBINDINGS, + "Ungrabbing keyboard with timestamp %lu\n", + timestamp); + XUngrabKeyboard (display->xdisplay, timestamp); + meta_error_trap_pop (display); +} + +gboolean +meta_screen_grab_all_keys (MetaScreen *screen) +{ + gboolean retval; + + if (screen->all_keys_grabbed) + return FALSE; + + if (screen->keys_grabbed) + meta_screen_ungrab_keys (screen); + + meta_topic (META_DEBUG_KEYBINDINGS, + "Grabbing all keys on RootWindow\n"); + retval = grab_all_keys_and_keyboard (screen->display, + screen->xroot); + if (retval) + { + screen->keys_grabbed = FALSE; + screen->all_keys_grabbed = TRUE; + } + + return retval; +} + +void +meta_screen_ungrab_all_keys (MetaScreen *screen) +{ + if (screen->all_keys_grabbed) + { + ungrab_all_keys_and_keyboard (screen->display, + screen->xroot); + + screen->all_keys_grabbed = FALSE; + screen->keys_grabbed = FALSE; + + /* Re-establish our standard bindings */ + meta_screen_grab_keys (screen); + } +} + gboolean meta_window_grab_all_keys (MetaWindow *window) { - int result; Window grabwindow; + gboolean retval; if (window->all_keys_grabbed) return FALSE; @@ -804,48 +905,18 @@ meta_window_grab_all_keys (MetaWindow *window) meta_display_get_current_time (window->display)); grabwindow = window->frame ? window->frame->xwindow : window->xwindow; - - meta_error_trap_push (window->display); - XGrabKey (window->display->xdisplay, AnyKey, AnyModifier, - grabwindow, True, - GrabModeAsync, GrabModeAsync); - - result = meta_error_trap_pop (window->display); - if (result != Success) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Global key grab failed for window %s\n", window->desc); - return FALSE; - } - else - { - /* Also grab the keyboard, so we get key releases and all key - * presses - */ - meta_error_trap_push (window->display); - XGrabKeyboard (window->display->xdisplay, - grabwindow, True, - GrabModeAsync, GrabModeAsync, - meta_display_get_current_time (window->display)); - - result = meta_error_trap_pop (window->display); - if (result != Success) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "XGrabKeyboard() failed for window %s\n", - window->desc); - return FALSE; - } - - meta_topic (META_DEBUG_KEYBINDINGS, - "Grabbed all keys on window %s\n", window->desc); - - window->keys_grabbed = FALSE; - window->all_keys_grabbed = TRUE; - window->grab_on_frame = window->frame != NULL; - return TRUE; + meta_topic (META_DEBUG_KEYBINDINGS, + "Grabbing all keys on window %s\n", window->desc); + retval = grab_all_keys_and_keyboard (window->display, grabwindow); + if (retval) + { + window->keys_grabbed = FALSE; + window->all_keys_grabbed = TRUE; + window->grab_on_frame = window->frame != NULL; } + + return retval; } void @@ -854,24 +925,12 @@ meta_window_ungrab_all_keys (MetaWindow *window) if (window->all_keys_grabbed) { Window grabwindow; - Time timestamp; grabwindow = (window->frame && window->grab_on_frame) ? window->frame->xwindow : window->xwindow; - timestamp = meta_display_get_current_time (window->display); - - meta_error_trap_push (window->display); - XUngrabKey (window->display->xdisplay, - AnyKey, AnyModifier, - grabwindow); + ungrab_all_keys_and_keyboard (window->display, grabwindow); - meta_topic (META_DEBUG_KEYBINDINGS, - "Ungrabbing keyboard with timestamp %lu\n", - timestamp); - XUngrabKeyboard (window->display->xdisplay, timestamp); - meta_error_trap_pop (window->display); - window->grab_on_frame = FALSE; window->all_keys_grabbed = FALSE; window->keys_grabbed = FALSE; @@ -1061,7 +1120,7 @@ process_event (MetaKeyBinding *bindings, meta_topic (META_DEBUG_KEYBINDINGS, "No handler found for this event in this binding table\n"); } - + void meta_display_process_key_event (MetaDisplay *display, MetaWindow *window, @@ -1069,14 +1128,19 @@ meta_display_process_key_event (MetaDisplay *display, { KeySym keysym; gboolean handled; + gboolean all_keys_grabbed; const char *str; + MetaScreen *screen; XAllowEvents (display->xdisplay, all_bindings_disabled ? ReplayKeyboard : AsyncKeyboard, event->xkey.time); if (all_bindings_disabled) return; - + + screen = meta_display_screen_for_xwindow (display, + event->xany.window); + /* window may be NULL */ keysym = XKeycodeToKeysym (display->xdisplay, event->xkey.keycode, 0); @@ -1089,7 +1153,8 @@ meta_display_process_key_event (MetaDisplay *display, str ? str : "(null)", event->xkey.state, window ? window->desc : "(no window)"); - if (window == NULL || !window->all_keys_grabbed) + all_keys_grabbed = window ? window->all_keys_grabbed : screen->all_keys_grabbed; + if (!all_keys_grabbed) { /* Do the normal keybindings */ process_event (display->screen_bindings, @@ -1116,13 +1181,15 @@ meta_display_process_key_event (MetaDisplay *display, handled = FALSE; - if (window == display->grab_window) + if (window ? (window == display->grab_window) : + (screen == display->grab_screen)) { switch (display->grab_op) { case META_GRAB_OP_KEYBOARD_MOVING: meta_topic (META_DEBUG_KEYBINDINGS, "Processing event for keyboard move\n"); + g_assert (window != NULL); handled = process_keyboard_move_grab (display, window, event, keysym); break; @@ -1137,6 +1204,7 @@ meta_display_process_key_event (MetaDisplay *display, case META_GRAB_OP_KEYBOARD_RESIZING_NW: meta_topic (META_DEBUG_KEYBINDINGS, "Processing event for keyboard resize\n"); + g_assert (window != NULL); handled = process_keyboard_resize_grab (display, window, event, keysym); break; @@ -1144,12 +1212,13 @@ meta_display_process_key_event (MetaDisplay *display, case META_GRAB_OP_KEYBOARD_TABBING_DOCK: meta_topic (META_DEBUG_KEYBINDINGS, "Processing event for keyboard tabbing\n"); + g_assert (window != NULL); handled = process_tab_grab (display, window, event, keysym); break; case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: meta_topic (META_DEBUG_KEYBINDINGS, "Processing event for keyboard workspace switching\n"); - handled = process_workspace_switch_grab (display, window, event, keysym); + handled = process_workspace_switch_grab (display, event, keysym); break; default: @@ -1742,16 +1811,13 @@ handle_activate_workspace (MetaDisplay *display, static gboolean process_workspace_switch_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; + screen = display->grab_screen; g_return_val_if_fail (screen->tab_popup != NULL, FALSE); @@ -1952,6 +2018,7 @@ handle_tab_forward (MetaDisplay *display, "Starting tab between windows, showing popup\n"); if (meta_display_begin_grab_op (window->display, + window->screen, display->focus_window ? display->focus_window : window, op_from_tab_type (type), @@ -2120,6 +2187,7 @@ handle_begin_move (MetaDisplay *display, { meta_window_raise (window); meta_display_begin_grab_op (window->display, + window->screen, window, META_GRAB_OP_KEYBOARD_MOVING, FALSE, 0, 0, @@ -2266,47 +2334,30 @@ handle_workspace_switch (MetaDisplay *display, if (screen == NULL) return; - /* FIXME this is all broken, that you need a window to grab on. - * There's no reason we need a window here, in fact it's broken - * that you have to have one. - */ - - 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"); + meta_topic (META_DEBUG_KEYBINDINGS, + "Starting tab between workspaces, showing popup\n"); - if (meta_display_begin_grab_op (display, - window, - META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING, - FALSE, - 0, - event->xkey.state & ~(display->ignored_modifier_mask), - event->xkey.time, - 0, 0)) - { - MetaWorkspace *next; + if (meta_display_begin_grab_op (display, + screen, + NULL, + META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING, + 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); + next = meta_workspace_get_neighbor (screen->active_workspace, + motion); + g_assert (next); - meta_ui_tab_popup_select (window->screen->tab_popup, - (MetaTabEntryKey) next); + meta_ui_tab_popup_select (screen->tab_popup, + (MetaTabEntryKey) next); - /* only after selecting proper window */ - meta_ui_tab_popup_set_showing (window->screen->tab_popup, - TRUE); - } + /* only after selecting proper window */ + meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE); } } diff --git a/src/keybindings.h b/src/keybindings.h index 20187e075..0cc10a360 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -29,6 +29,8 @@ void meta_display_init_keys (MetaDisplay *display); void meta_display_shutdown_keys (MetaDisplay *display); void meta_screen_grab_keys (MetaScreen *screen); void meta_screen_ungrab_keys (MetaScreen *screen); +gboolean meta_screen_grab_all_keys (MetaScreen *screen); +void meta_screen_ungrab_all_keys (MetaScreen *screen); void meta_window_grab_keys (MetaWindow *window); void meta_window_ungrab_keys (MetaWindow *window); gboolean meta_window_grab_all_keys (MetaWindow *window); diff --git a/src/screen.h b/src/screen.h index e44f10349..4fd7de719 100644 --- a/src/screen.h +++ b/src/screen.h @@ -77,6 +77,7 @@ struct _MetaScreen guint vertical_workspaces : 1; guint keys_grabbed : 1; + guint all_keys_grabbed : 1; int closing; }; diff --git a/src/window.c b/src/window.c index 221190525..1d8998ff9 100644 --- a/src/window.c +++ b/src/window.c @@ -3339,6 +3339,7 @@ meta_window_client_message (MetaWindow *window, meta_topic (META_DEBUG_WINDOW_OPS, "Beginning move/resize with button = %d\n", button); meta_display_begin_grab_op (window->display, + window->screen, window, op, FALSE, @@ -5419,6 +5420,7 @@ menu_callback (MetaWindowMenu *menu, case META_MENU_OP_MOVE: meta_window_raise (window); meta_display_begin_grab_op (window->display, + window->screen, window, META_GRAB_OP_KEYBOARD_MOVING, FALSE, 0, 0, @@ -5429,6 +5431,7 @@ menu_callback (MetaWindowMenu *menu, case META_MENU_OP_RESIZE: meta_window_raise (window); meta_display_begin_grab_op (window->display, + window->screen, window, META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, FALSE, 0, 0,