Fixes not being able to tab out of a workspace which contains no windows.

2002-06-26  Mark McLoughlin  <mark@skynet.ie>

        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.
This commit is contained in:
Mark McLoughlin 2002-06-27 05:08:32 +00:00 committed by Mark McLoughlin
parent f0a811421f
commit 6b72d622a5
8 changed files with 256 additions and 121 deletions

View File

@ -1,3 +1,42 @@
2002-06-26 Mark McLoughlin <mark@skynet.ie>
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 <mark@skynet.ie>
* src/fixedtip.c: (meta_fixed_tip_show):

View File

@ -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

View File

@ -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;
}
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,44 +2263,49 @@ 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;
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;
}
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");
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;

View File

@ -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,

View File

@ -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;
@ -805,47 +906,17 @@ meta_window_grab_all_keys (MetaWindow *window)
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
"Grabbing all keys on window %s\n", window->desc);
retval = grab_all_keys_and_keyboard (window->display, grabwindow);
if (retval)
{
/* 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;
}
return retval;
}
void
@ -854,23 +925,11 @@ 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);
meta_topic (META_DEBUG_KEYBINDINGS,
"Ungrabbing keyboard with timestamp %lu\n",
timestamp);
XUngrabKeyboard (window->display->xdisplay, timestamp);
meta_error_trap_pop (window->display);
ungrab_all_keys_and_keyboard (window->display, grabwindow);
window->grab_on_frame = FALSE;
window->all_keys_grabbed = FALSE;
@ -1069,7 +1128,9 @@ 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,
@ -1077,6 +1138,9 @@ meta_display_process_key_event (MetaDisplay *display,
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,27 +2334,12 @@ 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");
if (meta_display_begin_grab_op (display,
window,
screen,
NULL,
META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING,
FALSE,
0,
@ -2296,17 +2349,15 @@ handle_workspace_switch (MetaDisplay *display,
{
MetaWorkspace *next;
next = meta_workspace_get_neighbor (window->screen->active_workspace,
next = meta_workspace_get_neighbor (screen->active_workspace,
motion);
g_assert (next);
meta_ui_tab_popup_select (window->screen->tab_popup,
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);
}
meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
}
}

View File

@ -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);

View File

@ -77,6 +77,7 @@ struct _MetaScreen
guint vertical_workspaces : 1;
guint keys_grabbed : 1;
guint all_keys_grabbed : 1;
int closing;
};

View File

@ -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,