diff --git a/debian/libmuffin0.symbols b/debian/libmuffin0.symbols index 9ccc4eac4..819d48d76 100644 --- a/debian/libmuffin0.symbols +++ b/debian/libmuffin0.symbols @@ -2146,6 +2146,7 @@ libmuffin.so.0 libmuffin0 #MINVER# meta_display_get_tab_current@Base 5.3.0 meta_display_get_tab_list@Base 5.3.0 meta_display_get_tab_next@Base 5.3.0 + meta_display_get_tab_in_direction@Base 6.0.1 meta_display_get_type@Base 5.3.0 meta_display_get_workspace_manager@Base 5.3.0 meta_display_get_x11_display@Base 5.3.0 diff --git a/src/core/display.c b/src/core/display.c index c9e2c1982..6dc855eaf 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -2418,6 +2418,94 @@ find_tab_backward (MetaDisplay *display, return NULL; } +static bool +tab_position_nearer(MetaWindow* test, + MetaWindow* current, + MetaWindow* target) +{ + int test_center_x = test->rect.x + test->rect.width / 2; + int test_center_y = test->rect.y + test->rect.height / 2; + int current_center_x = current->rect.x + current->rect.width / 2; + int current_center_y = current->rect.y + current->rect.height / 2; + int target_center_x = target->rect.x + target->rect.width / 2; + int target_center_y = target->rect.y + target->rect.height / 2; + + float test_distance = sqrt(pow(test_center_x - current_center_x, 2) + + pow(test_center_y - current_center_y, 2)); + float target_distance = sqrt(pow(target_center_x - current_center_x, 2) + + pow(target_center_y - current_center_y, 2)); + + return (test_distance < target_distance); +} + +static bool +tab_position_behind(MetaWindow* test, + MetaWindow* current, + MetaDirection direction) +{ + int test_center_x = test->rect.x + test->rect.width / 2; + int test_center_y = test->rect.y + test->rect.height / 2; + int current_center_x = current->rect.x + current->rect.width / 2; + int current_center_y = current->rect.y + current->rect.height / 2; + + return ((direction == META_DIRECTION_RIGHT && + test_center_x > current_center_x) || + (direction == META_DIRECTION_LEFT && + test_center_x < current_center_x) || + (direction == META_DIRECTION_UP && + test_center_y < current_center_y) || + (direction == META_DIRECTION_DOWN && + test_center_y > current_center_y)); +} + +static bool +tab_is_next_in_direction (MetaWindow* test, + MetaWindow* current, + MetaWindow* target, + MetaDirection direction) +{ + return (tab_position_behind(test, current, direction) && + (target == current || tab_position_nearer(test, current, target))); +} + +static MetaWindow* +find_tab_in_direction (MetaDisplay *display, + MetaTabList type, + MetaWorkspace *workspace, + GList *start, + MetaDirection direction) +{ + GList *result; + GList *tmp; + + g_return_val_if_fail (start != NULL, NULL); + g_return_val_if_fail (workspace != NULL, NULL); + + result = start; + tmp = start->next; + + while (tmp != NULL) { + MetaWindow *window = tmp->data; + if (IN_TAB_CHAIN (window, type) && + !window->minimized && + tab_is_next_in_direction(window, start->data, result->data, direction)) + result = tmp; + tmp = tmp->next; + } + + tmp = workspace->mru_list; + while (tmp != start && tmp != NULL) { + MetaWindow *window = tmp->data; + if (IN_TAB_CHAIN (window, type) && + !window->minimized && + tab_is_next_in_direction(window, start->data, result->data, direction)) + result = tmp; + tmp = tmp->next; + } + + return result->data; +} + static int mru_cmp (gconstpointer a, gconstpointer b) @@ -2592,6 +2680,40 @@ meta_display_get_tab_current (MetaDisplay *display, return NULL; } +/** + * meta_display_get_tab_in_direction: + * @display: a #MetaDisplay + * @type: type of tab list + * @workspace: origin workspace + * @window: (nullable): starting window + * @direction: The direction that should be searched. + * + * Determine the nearest window in the given direction. + * + * Returns: (transfer none): The next window in the given direction + * + */ +MetaWindow* +meta_display_get_tab_in_direction (MetaDisplay *display, + MetaTabList type, + MetaWorkspace *workspace, + MetaWindow *window, + MetaDirection direction) +{ + gboolean skip; + GList *tab_list; + MetaWindow *ret; + tab_list = meta_display_get_tab_list (display, type, workspace); + + if (tab_list == NULL) + return NULL; + + ret = find_tab_in_direction (display, type, workspace, tab_list, direction); + + g_list_free (tab_list); + return ret; +} + MetaGravity meta_resize_gravity_from_grab_op (MetaGrabOp op) { diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 5e1665c99..fb27e1664 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -3491,6 +3491,67 @@ handle_cycle (MetaDisplay *display, do_choose_window (display, event_window, event, binding, backwards); } +static void +handle_switch_tile_action (MetaDisplay *display, + MetaWindow *event_window, + ClutterKeyEvent *event, + MetaKeyBinding *binding, + MetaDirection direction) +{ + MetaWorkspaceManager *workspace_manager = display->workspace_manager; + MetaTabList type = binding->handler->data; + MetaWindow *window; + + window = meta_display_get_tab_in_direction (display, + type, + workspace_manager->active_workspace, + NULL, + direction); + + if (window) + meta_window_activate (window, event->time); +} + +static void +handle_switch_tile_action_right (MetaDisplay *display, + MetaWindow *event_window, + ClutterKeyEvent *event, + MetaKeyBinding *binding, + gpointer dummy) +{ + handle_switch_tile_action (display, event_window, event, binding, META_DIRECTION_RIGHT); +} + +static void +handle_switch_tile_action_left (MetaDisplay *display, + MetaWindow *event_window, + ClutterKeyEvent *event, + MetaKeyBinding *binding, + gpointer dummy) +{ + handle_switch_tile_action (display, event_window, event, binding, META_DIRECTION_LEFT); +} + +static void +handle_switch_tile_action_up (MetaDisplay *display, + MetaWindow *event_window, + ClutterKeyEvent *event, + MetaKeyBinding *binding, + gpointer dummy) +{ + handle_switch_tile_action (display, event_window, event, binding, META_DIRECTION_UP); +} + +static void +handle_switch_tile_action_down (MetaDisplay *display, + MetaWindow *event_window, + ClutterKeyEvent *event, + MetaKeyBinding *binding, + gpointer dummy) +{ + handle_switch_tile_action (display, event_window, event, binding, META_DIRECTION_DOWN); +} + static void handle_toggle_fullscreen (MetaDisplay *display, MetaWindow *window, @@ -4598,6 +4659,34 @@ init_builtin_key_bindings (MetaDisplay *display) META_KEYBINDING_ACTION_PUSH_TILE_DOWN, handle_tile_action, META_TILE_BOTTOM); + add_builtin_keybinding (display, + "switch-to-tile-left", + common_keybindings, + META_KEY_BINDING_NONE, + META_KEYBINDING_ACTION_SWITCH_TO_TILE_LEFT, + handle_switch_tile_action_left, META_TAB_LIST_NORMAL); + + add_builtin_keybinding (display, + "switch-to-tile-right", + common_keybindings, + META_KEY_BINDING_NONE, + META_KEYBINDING_ACTION_SWITCH_TO_TILE_RIGHT, + handle_switch_tile_action_right, META_TAB_LIST_NORMAL); + + add_builtin_keybinding (display, + "switch-to-tile-up", + common_keybindings, + META_KEY_BINDING_NONE, + META_KEYBINDING_ACTION_SWITCH_TO_TILE_UP, + handle_switch_tile_action_up, META_TAB_LIST_NORMAL); + + add_builtin_keybinding (display, + "switch-to-tile-down", + common_keybindings, + META_KEY_BINDING_NONE, + META_KEYBINDING_ACTION_SWITCH_TO_TILE_DOWN, + handle_switch_tile_action_down, META_TAB_LIST_NORMAL); + add_builtin_keybinding (display, "toggle-above", common_keybindings, diff --git a/src/meta/display.h b/src/meta/display.h index c18d3ec47..9b9f4178a 100644 --- a/src/meta/display.h +++ b/src/meta/display.h @@ -133,6 +133,13 @@ MetaWindow* meta_display_get_tab_next (MetaDisplay *display, MetaWindow *window, gboolean backward); +META_EXPORT +MetaWindow* meta_display_get_tab_in_direction (MetaDisplay *display, + MetaTabList type, + MetaWorkspace *workspace, + MetaWindow *window, + MetaDirection direction); + META_EXPORT MetaWindow* meta_display_get_tab_current (MetaDisplay *display, MetaTabList type, diff --git a/src/meta/prefs.h b/src/meta/prefs.h index ef319b714..d2b1e7fb2 100644 --- a/src/meta/prefs.h +++ b/src/meta/prefs.h @@ -330,6 +330,10 @@ gboolean meta_prefs_get_invert_flip_direction (void); * @META_KEYBINDING_ACTION_PUSH_TILE_RIGHT: FILLME * @META_KEYBINDING_ACTION_PUSH_TILE_UP: FILLME * @META_KEYBINDING_ACTION_PUSH_TILE_DOWN: FILLME + * @META_KEYBINDING_ACTION_SWITCH_TO_TILE_LEFT: FILLME + * @META_KEYBINDING_ACTION_SWITCH_TO_TILE_RIGHT: FILLME + * @META_KEYBINDING_ACTION_SWITCH_TO_TILE_UP: FILLME + * @META_KEYBINDING_ACTION_SWITCH_TO_TILE_DOWN: FILLME * @META_KEYBINDING_ACTION_TOGGLE_ABOVE: FILLME * @META_KEYBINDING_ACTION_MAXIMIZE: FILLME * @META_KEYBINDING_ACTION_UNMAXIMIZE: FILLME @@ -432,6 +436,10 @@ typedef enum _MetaKeyBindingAction META_KEYBINDING_ACTION_PUSH_TILE_RIGHT, META_KEYBINDING_ACTION_PUSH_TILE_UP, META_KEYBINDING_ACTION_PUSH_TILE_DOWN, + META_KEYBINDING_ACTION_SWITCH_TO_TILE_LEFT, + META_KEYBINDING_ACTION_SWITCH_TO_TILE_RIGHT, + META_KEYBINDING_ACTION_SWITCH_TO_TILE_UP, + META_KEYBINDING_ACTION_SWITCH_TO_TILE_DOWN, META_KEYBINDING_ACTION_TOGGLE_ABOVE, META_KEYBINDING_ACTION_MAXIMIZE, META_KEYBINDING_ACTION_UNMAXIMIZE,