Skip to content

Commit df41516

Browse files
committed
keybindings: Fix workspace navigation while dragging a window
with the mouse. Fixes linuxmint/cinnamon#11069.
1 parent 6821ae3 commit df41516

File tree

4 files changed

+197
-7
lines changed

4 files changed

+197
-7
lines changed

data/org.cinnamon.muffin.gschema.xml.in

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
</description>
4545
</key>
4646

47+
<key name="invert-workspace-flip-direction" type="b">
48+
<default>false</default>
49+
<summary>Inverts the direction the left and right arrows take you when
50+
you switch workspaces during a window drag</summary>
51+
<description>
52+
Changes left-right arrow keys to window-centric directions rather than
53+
workspace-centric
54+
</description>
55+
</key>
56+
4757
<key name="dynamic-workspaces" type="b">
4858
<default>false</default>
4959
<summary>Workspaces are managed dynamically</summary>

src/core/keybindings.c

Lines changed: 167 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,16 +2032,48 @@ strip_self_mod (guint keyval,
20322032
*stripped_mod = event_state & ~mod;
20332033
}
20342034

2035+
static gboolean
2036+
is_workspace_action (gint action)
2037+
{
2038+
if (action == META_MOTION_LEFT || action == META_MOTION_RIGHT)
2039+
{
2040+
return TRUE;
2041+
}
2042+
2043+
switch (action)
2044+
{
2045+
case META_MOTION_LEFT:
2046+
case META_MOTION_RIGHT:
2047+
case META_KEYBINDING_ACTION_WORKSPACE_1:
2048+
case META_KEYBINDING_ACTION_WORKSPACE_2:
2049+
case META_KEYBINDING_ACTION_WORKSPACE_3:
2050+
case META_KEYBINDING_ACTION_WORKSPACE_4:
2051+
case META_KEYBINDING_ACTION_WORKSPACE_5:
2052+
case META_KEYBINDING_ACTION_WORKSPACE_6:
2053+
case META_KEYBINDING_ACTION_WORKSPACE_7:
2054+
case META_KEYBINDING_ACTION_WORKSPACE_8:
2055+
case META_KEYBINDING_ACTION_WORKSPACE_9:
2056+
case META_KEYBINDING_ACTION_WORKSPACE_10:
2057+
case META_KEYBINDING_ACTION_WORKSPACE_11:
2058+
case META_KEYBINDING_ACTION_WORKSPACE_12:
2059+
return TRUE;
2060+
}
2061+
2062+
return FALSE;
2063+
}
2064+
20352065
static gboolean
20362066
process_event (MetaDisplay *display,
20372067
MetaWindow *window,
20382068
ClutterKeyEvent *event,
2039-
gboolean allow_release)
2069+
gboolean allow_release,
2070+
gboolean mouse_grab_move)
20402071
{
20412072
MetaKeyBindingManager *keys = &display->key_binding_manager;
20422073
xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode;
20432074
MetaResolvedKeyCombo resolved_combo = { &keycode, 1 };
20442075
MetaKeyBinding *binding;
2076+
MetaKeyBindingAction action;
20452077

20462078
/* we used to have release-based bindings but no longer. */
20472079
if (event->type == CLUTTER_KEY_RELEASE && !allow_release)
@@ -2059,6 +2091,11 @@ process_event (MetaDisplay *display,
20592091
(!window && binding->flags & META_KEY_BINDING_PER_WINDOW))
20602092
goto not_found;
20612093

2094+
action = binding->handler->data;
2095+
2096+
if (mouse_grab_move && !is_workspace_action (action))
2097+
goto not_found;
2098+
20622099
if (binding->handler == NULL)
20632100
meta_bug ("Binding %s has no handler\n", binding->name);
20642101

@@ -2107,7 +2144,7 @@ process_event (MetaDisplay *display,
21072144
not_found:
21082145
meta_topic (META_DEBUG_KEYBINDINGS,
21092146
"No handler found for this event in this binding table\n");
2110-
return FALSE;
2147+
return mouse_grab_move;
21112148
}
21122149

21132150
static gboolean
@@ -2172,7 +2209,7 @@ process_special_modifier_key (MetaDisplay *display,
21722209
{
21732210
modifier_key_only_pressed = FALSE;
21742211

2175-
if (process_event (display, window, event, FALSE))
2212+
if (process_event (display, window, event, FALSE, FALSE))
21762213
{
21772214
/* As normally, after we've handled a global key
21782215
* binding, we unfreeze the keyboard but keep the grab
@@ -2288,7 +2325,7 @@ process_key_event (MetaDisplay *display,
22882325
MetaWindow *window,
22892326
ClutterKeyEvent *event)
22902327
{
2291-
gboolean keep_grab;
2328+
gboolean keep_grab, mouse_grab_move;
22922329
gboolean all_keys_grabbed;
22932330
gboolean allow_key_up = FALSE;
22942331

@@ -2314,6 +2351,8 @@ process_key_event (MetaDisplay *display,
23142351
}
23152352

23162353
keep_grab = TRUE;
2354+
mouse_grab_move = FALSE;
2355+
23172356
if (all_keys_grabbed)
23182357
{
23192358
if (display->grab_op == META_GRAB_OP_NONE)
@@ -2345,16 +2384,20 @@ process_key_event (MetaDisplay *display,
23452384
meta_topic (META_DEBUG_KEYBINDINGS,
23462385
"Processing event for mouse-only move/resize\n");
23472386
keep_grab = process_mouse_move_resize_grab (display, window, event);
2387+
mouse_grab_move = display->grab_op == META_GRAB_OP_MOVING;
23482388
}
23492389
}
23502390
if (!keep_grab)
23512391
meta_display_end_grab_op (display, event->time);
23522392

2353-
return TRUE;
2393+
if (!mouse_grab_move)
2394+
{
2395+
return TRUE;
2396+
}
23542397
}
23552398

23562399
/* Do the normal keybindings */
2357-
return process_event (display, window, event, allow_key_up);
2400+
return process_event (display, window, event, allow_key_up, mouse_grab_move);
23582401
}
23592402

23602403
/* Handle a key event. May be called recursively: some key events cause
@@ -2396,6 +2439,40 @@ meta_keybindings_process_event (MetaDisplay *display,
23962439
}
23972440
}
23982441

2442+
static void
2443+
handle_workspace_shift (MetaWindow *window,
2444+
ClutterKeyEvent *event,
2445+
guint keyval)
2446+
{
2447+
MetaWorkspace *target_workspace;
2448+
guint motion = META_MOTION_LEFT;
2449+
gboolean should_handle = FALSE;
2450+
2451+
if (keyval == CLUTTER_KEY_Left || keyval == CLUTTER_KEY_KP_Left)
2452+
{
2453+
motion = meta_prefs_get_invert_flip_direction () ? META_MOTION_RIGHT : META_MOTION_LEFT;
2454+
should_handle = TRUE;
2455+
}
2456+
else
2457+
if (keyval == CLUTTER_KEY_Right || keyval == CLUTTER_KEY_KP_Right)
2458+
{
2459+
motion = meta_prefs_get_invert_flip_direction () ? META_MOTION_LEFT : META_MOTION_RIGHT;
2460+
should_handle = TRUE;
2461+
}
2462+
2463+
if (!should_handle)
2464+
{
2465+
return;
2466+
}
2467+
2468+
target_workspace = meta_workspace_get_neighbor (meta_workspace_manager_get_active_workspace (window->display->workspace_manager), motion);
2469+
2470+
if (target_workspace)
2471+
{
2472+
meta_workspace_activate (target_workspace, event->time);
2473+
}
2474+
}
2475+
23992476
static gboolean
24002477
process_mouse_move_resize_grab (MetaDisplay *display,
24012478
MetaWindow *window,
@@ -2441,6 +2518,90 @@ process_mouse_move_resize_grab (MetaDisplay *display,
24412518
return FALSE;
24422519
}
24432520

2521+
MetaWorkspace *target_workspace;
2522+
gulong mask;
2523+
2524+
/* Only proceed if no mod or only numlock */
2525+
mask = event->modifier_state & ~(CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK | CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK);
2526+
2527+
if (mask != CLUTTER_BUTTON1_MASK)
2528+
return TRUE;
2529+
2530+
gint index = -1;
2531+
2532+
switch (event->keyval)
2533+
{
2534+
case CLUTTER_KEY_Left:
2535+
case CLUTTER_KEY_KP_Left:
2536+
case CLUTTER_KEY_Right:
2537+
case CLUTTER_KEY_KP_Right:
2538+
handle_workspace_shift (window, event, event->keyval);
2539+
return TRUE;
2540+
2541+
case CLUTTER_KEY_KP_1:
2542+
case CLUTTER_KEY_1:
2543+
index = 0;
2544+
break;
2545+
2546+
case CLUTTER_KEY_KP_2:
2547+
case CLUTTER_KEY_2:
2548+
index = 1;
2549+
break;
2550+
2551+
case CLUTTER_KEY_KP_3:
2552+
case CLUTTER_KEY_3:
2553+
index = 2;
2554+
break;
2555+
2556+
case CLUTTER_KEY_KP_4:
2557+
case CLUTTER_KEY_4:
2558+
index = 3;
2559+
break;
2560+
2561+
case CLUTTER_KEY_KP_5:
2562+
case CLUTTER_KEY_5:
2563+
index = 4;
2564+
break;
2565+
2566+
case CLUTTER_KEY_KP_6:
2567+
case CLUTTER_KEY_6:
2568+
index = 5;
2569+
break;
2570+
2571+
case CLUTTER_KEY_KP_7:
2572+
case CLUTTER_KEY_7:
2573+
index = 6;
2574+
break;
2575+
2576+
case CLUTTER_KEY_KP_8:
2577+
case CLUTTER_KEY_8:
2578+
index = 7;
2579+
break;
2580+
2581+
case CLUTTER_KEY_KP_9:
2582+
case CLUTTER_KEY_9:
2583+
index = 8;
2584+
break;
2585+
2586+
case CLUTTER_KEY_KP_0:
2587+
case CLUTTER_KEY_0:
2588+
index = 9;
2589+
break;
2590+
2591+
default:
2592+
break;
2593+
}
2594+
2595+
if (index >= 0)
2596+
{
2597+
target_workspace = meta_workspace_manager_get_workspace_by_index (window->display->workspace_manager, index);
2598+
2599+
if (target_workspace)
2600+
{
2601+
meta_workspace_activate (target_workspace, event->time);
2602+
}
2603+
}
2604+
24442605
return TRUE;
24452606
}
24462607

src/core/prefs.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ static char *iso_next_group_option = NULL;
141141
static MetaX11BackgroundTransition background_transition = META_X11_BACKGROUND_TRANSITION_BLEND;
142142
static gboolean unredirect_fullscreen_windows = FALSE;
143143
static gboolean tile_maximize = FALSE;
144+
static gboolean invert_workspace_flip = FALSE;
144145
static char *gtk_theme = NULL;
145146
static char *bell_sound = NULL;
146147
static gboolean bring_user_activated_windows_to_current_workspace = FALSE;
@@ -421,6 +422,13 @@ static MetaBoolPreference preferences_bool[] =
421422
META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
422423
},
423424
&workspaces_only_on_primary,
425+
},
426+
{
427+
{ "invert-workspace-flip-direction",
428+
SCHEMA_MUFFIN,
429+
META_PREF_INVERT_WORKSPACE_FLIP_DIRECTION,
430+
},
431+
&invert_workspace_flip,
424432
},
425433
{
426434
{ "auto-maximize",
@@ -2395,6 +2403,12 @@ meta_prefs_get_auto_maximize (void)
23952403
return auto_maximize;
23962404
}
23972405

2406+
gboolean
2407+
meta_prefs_get_invert_flip_direction (void)
2408+
{
2409+
return invert_workspace_flip;
2410+
}
2411+
23982412
MetaKeyBindingAction
23992413
meta_prefs_get_keybinding_action (const char *name)
24002414
{

src/meta/prefs.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
* @META_PREF_GTK_THEME: gtk theme name
7272
* @META_PREF_BELL_SOUND: sound to use for audible event bell
7373
* @META_PREF_BRING_WINDOWS_TO_CURRENT_WORKSPACE: behavior when use activates an off-workspace window.
74+
* @META_PREF_INVERT_WORKSPACE_FLIP_DIRECTION: Flip arrow direction when changing workspaces during a window grab move.
7475
*/
7576

7677
/* Keep in sync with GSettings schemas! */
@@ -121,7 +122,8 @@ typedef enum
121122
META_PREF_TILE_MAXIMIZE,
122123
META_PREF_GTK_THEME,
123124
META_PREF_BELL_SOUND,
124-
META_PREF_BRING_WINDOWS_TO_CURRENT_WORKSPACE
125+
META_PREF_BRING_WINDOWS_TO_CURRENT_WORKSPACE,
126+
META_PREF_INVERT_WORKSPACE_FLIP_DIRECTION
125127
} MetaPreference;
126128

127129
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@@ -279,6 +281,9 @@ gint meta_prefs_get_min_win_opacity (void);
279281
META_EXPORT
280282
const char* meta_prefs_get_bell_sound (void);
281283

284+
META_EXPORT
285+
gboolean meta_prefs_get_invert_flip_direction (void);
286+
282287
/**
283288
* MetaKeyBindingAction:
284289
* @META_KEYBINDING_ACTION_NONE: FILLME

0 commit comments

Comments
 (0)