diff --git a/ChangeLog b/ChangeLog index d5afdb128..5004a8550 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2006-08-21 Elijah Newren + + Allow drags & resizes to be reverted by hitting escape. Based on + patch from Thomas Andersen. #126497. + + * src/display.c (grab_op_is_mouse_only): new function, + (meta_display_begin_grab_op): grab the keyboard when moving or + resizing too so that we can get escape keypresses + + * src/display.h (struct _MetaDisplay): add a comment to remind + that grab_was_cancelled is only used in wireframe mode + + * src/keybindings.[ch] (process_mouse_move_resize_grab): add new + function for handling keypresses during mouse-only moving and + resizing, (meta_window_grab_all_keys): add a timestamp parameter + and pass it to meta_window_focus(), + (meta_display_process_key_event): make sure + process_mouse_move_resize_grab() gets called when needed, + (process_keyboard_move_grab, process_keyboard_resize_grab): + rearrange some code slightly and improve the comments to make it + more readable + 2006-08-21 Elijah Newren Fix several bugs with handling of fullscreen windows, causing them diff --git a/src/display.c b/src/display.c index f7a9bcc4e..5e64eb2f2 100644 --- a/src/display.c +++ b/src/display.c @@ -1037,6 +1037,27 @@ meta_displays_list (void) static gboolean dump_events = TRUE; +static gboolean +grab_op_is_mouse_only (MetaGrabOp op) +{ + switch (op) + { + case META_GRAB_OP_MOVING: + case META_GRAB_OP_RESIZING_SE: + case META_GRAB_OP_RESIZING_S: + case META_GRAB_OP_RESIZING_SW: + case META_GRAB_OP_RESIZING_N: + case META_GRAB_OP_RESIZING_NE: + case META_GRAB_OP_RESIZING_NW: + case META_GRAB_OP_RESIZING_W: + case META_GRAB_OP_RESIZING_E: + return TRUE; + + default: + return FALSE; + } +} + static gboolean grab_op_is_mouse (MetaGrabOp op) { @@ -3293,11 +3314,12 @@ meta_display_begin_grab_op (MetaDisplay *display, return FALSE; } - if (grab_op_is_keyboard (op)) + /* Grab keys for keyboard ops and mouse move/resizes; see #126497 */ + if (grab_op_is_keyboard (op) || grab_op_is_mouse_only (op)) { if (window) display->grab_have_keyboard = - meta_window_grab_all_keys (window); + meta_window_grab_all_keys (window, timestamp); else display->grab_have_keyboard = diff --git a/src/display.h b/src/display.h index 65d9da5e8..66181cafd 100644 --- a/src/display.h +++ b/src/display.h @@ -261,7 +261,7 @@ struct _MetaDisplay guint grab_have_pointer : 1; guint grab_have_keyboard : 1; guint grab_wireframe_active : 1; - guint grab_was_cancelled : 1; + guint grab_was_cancelled : 1; /* Only used in wireframe mode */ MetaRectangle grab_wireframe_rect; MetaRectangle grab_wireframe_last_xor_rect; MetaRectangle grab_initial_window_pos; diff --git a/src/keybindings.c b/src/keybindings.c index 9da20ca5f..7a36cd4e9 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -196,6 +196,12 @@ static void handle_run_terminal (MetaDisplay *display, MetaKeyBinding *binding); /* debug */ +static gboolean process_mouse_move_resize_grab (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + KeySym keysym); + static gboolean process_keyboard_move_grab (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, @@ -1294,7 +1300,8 @@ meta_screen_ungrab_all_keys (MetaScreen *screen) } gboolean -meta_window_grab_all_keys (MetaWindow *window) +meta_window_grab_all_keys (MetaWindow *window, + Time timestamp) { Window grabwindow; gboolean retval; @@ -1311,8 +1318,7 @@ meta_window_grab_all_keys (MetaWindow *window) meta_topic (META_DEBUG_FOCUS, "Focusing %s because we're grabbing all its keys\n", window->desc); - meta_window_focus (window, - meta_display_get_current_time (window->display)); + meta_window_focus (window, timestamp); grabwindow = window->frame ? window->frame->xwindow : window->xwindow; @@ -1661,6 +1667,22 @@ meta_display_process_key_event (MetaDisplay *display, { switch (display->grab_op) { + case META_GRAB_OP_MOVING: + case META_GRAB_OP_RESIZING_SE: + case META_GRAB_OP_RESIZING_S: + case META_GRAB_OP_RESIZING_SW: + case META_GRAB_OP_RESIZING_N: + case META_GRAB_OP_RESIZING_NE: + case META_GRAB_OP_RESIZING_NW: + case META_GRAB_OP_RESIZING_W: + case META_GRAB_OP_RESIZING_E: + meta_topic (META_DEBUG_KEYBINDINGS, + "Processing event for mouse-only move/resize\n"); + g_assert (window != NULL); + handled = process_mouse_move_resize_grab (display, screen, + window, event, keysym); + break; + case META_GRAB_OP_KEYBOARD_MOVING: meta_topic (META_DEBUG_KEYBINDINGS, "Processing event for keyboard move\n"); @@ -1717,6 +1739,50 @@ meta_display_process_key_event (MetaDisplay *display, } } +static gboolean +process_mouse_move_resize_grab (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + KeySym keysym) +{ + /* don't care about releases, but eat them, don't end grab */ + if (event->type == KeyRelease) + return TRUE; + + if (keysym == XK_Escape) + { + /* End move or resize and restore to original state. If the + * window was a maximized window that had been "shaken loose" we + * need to remaximize it. In normal cases, we need to do a + * moveresize now to get the position back to the original. In + * wireframe mode, we just need to set grab_was_cancelled to tru + * to avoid avoid moveresizing to the position of the wireframe. + */ + if (window->shaken_loose) + meta_window_maximize (window, + META_MAXIMIZE_HORIZONTAL | + META_MAXIMIZE_VERTICAL); + else if (!display->grab_wireframe_active) + meta_window_move_resize (display->grab_window, + TRUE, + display->grab_initial_window_pos.x, + display->grab_initial_window_pos.y, + display->grab_initial_window_pos.width, + display->grab_initial_window_pos.height); + else + display->grab_was_cancelled = TRUE; + + /* End grab, since this was an "unhandled" keypress */ + return FALSE; + } + + /* The keypress really isn't handled but we just want to ignore it, so + * treat it as handled. + */ + return TRUE; +} + static gboolean process_keyboard_move_grab (MetaDisplay *display, MetaScreen *screen, @@ -1763,23 +1829,26 @@ process_keyboard_move_grab (MetaDisplay *display, if (keysym == XK_Escape) { - /* End resize and restore to original state. - * The move_resize is only needed when !wireframe - * since in wireframe we always moveresize at the end - * of the grab only. + /* End move and restore to original state. If the window was a + * maximized window that had been "shaken loose" we need to + * remaximize it. In normal cases, we need to do a moveresize + * now to get the position back to the original. In wireframe + * mode, we just need to set grab_was_cancelled to tru to avoid + * avoid moveresizing to the position of the wireframe. */ - if (!display->grab_wireframe_active && !window->shaken_loose) + if (window->shaken_loose) + meta_window_maximize (window, + META_MAXIMIZE_HORIZONTAL | + META_MAXIMIZE_VERTICAL); + else if (!display->grab_wireframe_active) meta_window_move_resize (display->grab_window, TRUE, display->grab_initial_window_pos.x, display->grab_initial_window_pos.y, display->grab_initial_window_pos.width, display->grab_initial_window_pos.height); - if(window->shaken_loose) - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - display->grab_was_cancelled = TRUE; + else + display->grab_was_cancelled = TRUE; } /* When moving by increments, we still snap to edges if the move @@ -2012,10 +2081,11 @@ process_keyboard_resize_grab (MetaDisplay *display, if (keysym == XK_Escape) { - /* End resize and restore to original state. - * The move_resize is only needed when !wireframe - * since in wireframe we always moveresize at the end - * of the grab only. + /* End resize and restore to original state. If not in + * wireframe mode, we need to do a moveresize now to get the + * position back to the original. If we are in wireframe mode, + * we need to avoid moveresizing to the position of the + * wireframe. */ if (!display->grab_wireframe_active) meta_window_move_resize (display->grab_window, @@ -2024,7 +2094,8 @@ process_keyboard_resize_grab (MetaDisplay *display, display->grab_initial_window_pos.y, display->grab_initial_window_pos.width, display->grab_initial_window_pos.height); - display->grab_was_cancelled = TRUE; + else + display->grab_was_cancelled = TRUE; return FALSE; } diff --git a/src/keybindings.h b/src/keybindings.h index 0cc10a360..dce9ea284 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -33,7 +33,8 @@ 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); +gboolean meta_window_grab_all_keys (MetaWindow *window, + Time timestamp); void meta_window_ungrab_all_keys (MetaWindow *window); void meta_display_process_key_event (MetaDisplay *display, MetaWindow *window,