diff --git a/ChangeLog b/ChangeLog index 0bd9998c4..427e4b9f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2005-01-23 Elijah Newren + + Restore original stacking when aborting an alt-esc window switch + operation. Fixes #123576. + + * src/display.c: (GRAB_OP_IS_WINDOW_SWITCH): new macro, + (meta_display_close): clear grab_old_window_stacking if non-NULL, + (event_callback): restore stack positions if alt-esc op cancelled + with button press, (meta_display_begin_grab_op): store the old + stacking positions, (meta_display_end_grab_op): free the old stack + positions + + * src/display.h: (struct _MetaDisplay): add a + grab_old_window_stacking list + + * src/keybindings.c: (process_tab_grab): restore stack positions + if alt-esc op cancelled with an errant key press + + * src/stack.c: (compare_just_window_stack_position): new + GCompareFunc function, (meta_stack_get_positions): get current + stack positions, (compare_pointers): new GCompareFunc function, + (lists_contain_same_windows): simple utility func to see if two + lists contains the same windows, (meta_stack_set_positions): new + function to set the positions of all the windows in the stack + + * src/stack.h: (meta_stack_get_postions, + meta_stack_set_positions): new functions + 2005-01-23 Elijah Newren Patch from John Paul Wallington to fix #163420. diff --git a/src/display.c b/src/display.c index 28b05e4bf..26a38f2a8 100644 --- a/src/display.c +++ b/src/display.c @@ -63,6 +63,12 @@ #define USE_GDK_DISPLAY +#define GRAB_OP_IS_WINDOW_SWITCH(g) \ + (g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \ + g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \ + g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL || \ + g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK) + typedef struct { MetaDisplay *display; @@ -790,6 +796,9 @@ meta_display_close (MetaDisplay *display) meta_prefs_remove_listener (prefs_changed_callback, display); meta_display_remove_autoraise_callback (display); + + if (display->grab_old_window_stacking) + g_list_free (display->grab_old_window_stacking); #ifdef USE_GDK_DISPLAY /* Stop caring about events */ @@ -1574,6 +1583,16 @@ event_callback (XEvent *event, (display->grab_window ? display->grab_window->desc : "none")); + if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) + { + MetaScreen *screen; + meta_topic (META_DEBUG_WINDOW_OPS, + "Syncing to old stack positions.\n"); + screen = + meta_display_screen_for_root (display, event->xany.window); + meta_stack_set_positions (screen->stack, + display->grab_old_window_stacking); + } meta_display_end_grab_op (display, event->xbutton.time); } @@ -3289,6 +3308,16 @@ meta_display_begin_grab_op (MetaDisplay *display, g_assert (display->grab_window != NULL || display->grab_screen != NULL); g_assert (display->grab_op != META_GRAB_OP_NONE); + /* Save the old stacking */ + if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) + { + meta_topic (META_DEBUG_WINDOW_OPS, + "Saving old stack positions; old pointer was %p.\n", + display->grab_old_window_stacking); + display->grab_old_window_stacking = + meta_stack_get_positions (screen->stack); + } + /* Do this last, after everything is set up. */ switch (op) { @@ -3340,10 +3369,7 @@ meta_display_end_grab_op (MetaDisplay *display, if (display->grab_window != NULL) display->grab_window->shaken_loose = FALSE; - 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_ESCAPING_NORMAL || - display->grab_op == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK || + if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) || display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING) { meta_ui_tab_popup_free (display->grab_screen->tab_popup); @@ -3355,6 +3381,15 @@ meta_display_end_grab_op (MetaDisplay *display, display->ungrab_should_not_cause_focus_window = display->grab_xwindow; } + if (display->grab_old_window_stacking != NULL) + { + meta_topic (META_DEBUG_WINDOW_OPS, + "Clearing out the old stack position, which was %p.\n", + display->grab_old_window_stacking); + g_list_free (display->grab_old_window_stacking); + display->grab_old_window_stacking = NULL; + } + if (display->grab_wireframe_active) { display->grab_wireframe_active = FALSE; diff --git a/src/display.h b/src/display.h index a122c35a5..6fd41c586 100644 --- a/src/display.h +++ b/src/display.h @@ -265,6 +265,7 @@ struct _MetaDisplay MetaResizePopup *grab_resize_popup; GTimeVal grab_last_moveresize_time; Time grab_motion_notify_time; + GList* grab_old_window_stacking; /* we use property updates as sentinels for certain window focus events * to avoid some race conditions on EnterNotify events diff --git a/src/keybindings.c b/src/keybindings.c index 27e82ce09..154920ebb 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -2475,6 +2475,11 @@ process_tab_grab (MetaDisplay *display, /* end grab */ meta_topic (META_DEBUG_KEYBINDINGS, "Ending tabbing/cycling, uninteresting key pressed\n"); + + meta_topic (META_DEBUG_KEYBINDINGS, + "Syncing to old stack positions.\n"); + meta_stack_set_positions (screen->stack, + screen->display->grab_old_window_stacking); } return key_used; diff --git a/src/stack.c b/src/stack.c index f55c61591..a2ffb1e33 100644 --- a/src/stack.c +++ b/src/stack.c @@ -1466,6 +1466,110 @@ meta_stack_windows_cmp (MetaStack *stack, return 0; /* not reached */ } +static int +compare_just_window_stack_position (void *a, + void *b) +{ + MetaWindow *window_a = a; + MetaWindow *window_b = b; + + if (window_a->stack_position < window_b->stack_position) + return -1; /* move window_a earlier in list */ + else if (window_a->stack_position > window_b->stack_position) + return 1; + else + return 0; /* not reached */ +} + +GList* +meta_stack_get_positions (MetaStack *stack) +{ + GList *tmp; + + /* Make sure to handle any adds or removes */ + meta_stack_ensure_sorted (stack); + + tmp = g_list_copy (stack->sorted); + tmp = g_list_sort (tmp, (GCompareFunc) compare_just_window_stack_position); + + return tmp; +} + +gint +compare_pointers (gconstpointer a, + gconstpointer b) +{ + if (a > b) + return 1; + else if (a < b) + return -1; + else + return 0; +} + +static gboolean +lists_contain_same_windows (GList *a, + GList *b) +{ + GList *copy1, *copy2; + GList *tmp1, *tmp2; + + if (g_list_length (a) != g_list_length (b)) + return FALSE; + + tmp1 = copy1 = g_list_sort (g_list_copy (a), compare_pointers); + tmp2 = copy2 = g_list_sort (g_list_copy (b), compare_pointers); + + while (tmp1 && tmp1->data == tmp2->data) /* tmp2 is non-NULL if tmp1 is */ + { + tmp1 = tmp1->next; + tmp2 = tmp2->next; + } + + g_list_free (copy1); + g_list_free (copy2); + + return (tmp1 == NULL); /* tmp2 is non-NULL if tmp1 is */ +} + +void +meta_stack_set_positions (MetaStack *stack, + GList *windows) +{ + int i; + GList *tmp; + + /* Make sure any adds or removes aren't in limbo -- is this needed? */ + meta_stack_ensure_sorted (stack); + + if (!lists_contain_same_windows (windows, stack->sorted)) + { + meta_warning ("This list of windows has somehow changed; not resetting " + "positions of the windows.\n"); + return; + } + + g_list_free (stack->sorted); + stack->sorted = g_list_copy (windows); + + stack->need_resort = TRUE; + stack->need_constrain = TRUE; + + i = 0; + tmp = windows; + while (tmp != NULL) + { + MetaWindow *w = tmp->data; + w->stack_position = i++; + tmp = tmp->next; + } + + meta_topic (META_DEBUG_STACK, + "Reset the stack positions of (nearly) all windows\n"); + + meta_stack_sync_to_server (stack); +} + void meta_window_set_stack_position_no_sync (MetaWindow *window, int position) diff --git a/src/stack.h b/src/stack.h index 0b8d05e2c..5cbcf807f 100644 --- a/src/stack.h +++ b/src/stack.h @@ -140,4 +140,8 @@ int meta_stack_windows_cmp (MetaStack *stack, void meta_window_set_stack_position (MetaWindow *window, int position); +GList* meta_stack_get_positions (MetaStack *stack); +void meta_stack_set_positions (MetaStack *stack, + GList *windows); + #endif