Skip to content

Commit 3bcf71c

Browse files
committed
Allow to push modal without grabbing
1 parent 847ca2e commit 3bcf71c

File tree

11 files changed

+96
-27
lines changed

11 files changed

+96
-27
lines changed

lib/WindowManager.vala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,20 @@ namespace Gala {
137137
public abstract Meta.BackgroundGroup background_group { get; protected set; }
138138

139139
/**
140-
* Enters the modal mode, which means that all events are directed to the stage instead
141-
* of the windows. This is the only way to receive keyboard events besides shortcut listeners.
140+
* Enters the modal mode, which will block keybindings and gestures. See {@link ModalProxy} for
141+
* how to allow certain gestures and keybindings.
142+
* If {@link grab} is true all events will be redirected to the given {@link Clutter.Actor}.
143+
* If {@link grab} is false other actors and shell windows may still receive events.
144+
* Normal windows will never receive keyboard focus though they will still receive pointer events
145+
* if {@link grab} is false and their {@link Meta.WindowActor} is visible.
146+
*
147+
* @param actor The actor to grab events for
148+
* @param grab Whether to grab all events onto the actor
142149
*
143150
* @return a {@link ModalProxy} which is needed to end the modal mode again and provides some
144151
* some basic control on the behavior of the window manager while it is in modal mode.
145152
*/
146-
public abstract ModalProxy push_modal (Clutter.Actor actor);
153+
public abstract ModalProxy push_modal (Clutter.Actor actor, bool grab);
147154

148155
/**
149156
* May exit the modal mode again, unless another component has called {@link push_modal}

plugins/pip/SelectionArea.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public class Gala.Plugins.PIP.SelectionArea : CanvasActor {
126126
wm.get_display ().set_cursor (Meta.Cursor.CROSSHAIR);
127127
grab_key_focus ();
128128

129-
modal_proxy = wm.push_modal (this);
129+
modal_proxy = wm.push_modal (this, true);
130130
}
131131

132132
private void get_selection_rectangle (out int x, out int y, out int width, out int height) {

src/InternalUtils.vala

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,5 +352,40 @@ namespace Gala {
352352
Clutter.get_default_backend ().get_default_seat ().bell_notify ();
353353
#endif
354354
}
355+
356+
/**
357+
* Returns the most recently used "normal" window (as gotten via {@link get_window_is_normal}) in the given workspace.
358+
* If there is a not normal but more recent window (e.g. a menu/tooltip) any_window will be set to that window otherwise
359+
* it will be set to the same window that is returned.
360+
*/
361+
public static Meta.Window? get_mru_window (Meta.Workspace workspace, out Meta.Window? any_window = null) {
362+
any_window = null;
363+
364+
var list = workspace.list_windows ();
365+
366+
if (list.is_empty ()) {
367+
return null;
368+
}
369+
370+
list.sort ((a, b) => {
371+
return (int) b.get_user_time () - (int) a.get_user_time ();
372+
});
373+
374+
foreach (var window in list) {
375+
if (!ShellClientsManager.get_instance ().is_positioned_window (window)) {
376+
if (any_window == null) {
377+
any_window = window;
378+
}
379+
380+
if (!get_window_is_normal (window)) {
381+
continue;
382+
}
383+
384+
return window;
385+
}
386+
}
387+
388+
return null;
389+
}
355390
}
356391
}

src/ShellClients/HideTracker.vala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,12 @@ public class Gala.HideTracker : Object {
138138
focus_overlap = false;
139139
focus_maximized_overlap = false;
140140

141-
foreach (var window in display.get_workspace_manager ().get_active_workspace ().list_windows ()) {
141+
var active_workspace = display.get_workspace_manager ().get_active_workspace ();
142+
143+
Meta.Window? normal_mru_window, any_mru_window;
144+
normal_mru_window = InternalUtils.get_mru_window (active_workspace, out any_mru_window);
145+
146+
foreach (var window in active_workspace.list_windows ()) {
142147
if (window == panel.window) {
143148
continue;
144149
}
@@ -158,7 +163,7 @@ public class Gala.HideTracker : Object {
158163

159164
overlap = true;
160165

161-
if (window != display.focus_window) {
166+
if (window != normal_mru_window && window != any_mru_window) {
162167
continue;
163168
}
164169

src/Widgets/MultitaskingView/MultitaskingView.vala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,13 @@ public class Gala.MultitaskingView : ActorTarget, RootTarget, ActivatableCompone
261261
if (action == SWITCH_WORKSPACE) {
262262
WorkspaceManager.get_default ().freeze_remove ();
263263

264+
var mru_window = InternalUtils.get_mru_window (display.get_workspace_manager ().get_active_workspace ());
265+
264266
if (workspaces_gesture_controller.action_info != null
265267
&& (bool) workspaces_gesture_controller.action_info
266-
&& display.focus_window != null
268+
&& mru_window != null
267269
) {
268-
var moving = display.focus_window;
270+
var moving = mru_window;
269271

270272
StaticWindowContainer.get_instance (display).notify_window_moving (moving);
271273

src/Widgets/PixelPicker.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,6 @@ public class Gala.PixelPicker : Clutter.Actor {
6666
wm.get_display ().set_cursor (Meta.Cursor.CROSSHAIR);
6767
grab_key_focus ();
6868

69-
modal_proxy = wm.push_modal (this);
69+
modal_proxy = wm.push_modal (this, true);
7070
}
7171
}

src/Widgets/SelectionArea.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public class Gala.SelectionArea : CanvasActor {
111111
wm.get_display ().set_cursor (Meta.Cursor.CROSSHAIR);
112112
grab_key_focus ();
113113

114-
modal_proxy = wm.push_modal (this);
114+
modal_proxy = wm.push_modal (this, true);
115115
}
116116

117117
public Graphene.Rect get_selection_rectangle () {

src/Widgets/SessionLocker.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ public class Gala.SessionLocker : Clutter.Actor {
328328
wm.get_display ().get_cursor_tracker ().set_pointer_visible (false);
329329
visible = true;
330330
grab_key_focus ();
331-
modal_proxy = wm.push_modal (this);
331+
modal_proxy = wm.push_modal (this, true);
332332

333333
if (Meta.Prefs.get_gnome_animations () && animate) {
334334
animate_and_lock (animation_time);

src/Widgets/WindowOverview.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public class Gala.WindowOverview : ActorTarget, RootTarget, ActivatableComponent
112112

113113
grab_key_focus ();
114114

115-
modal_proxy = wm.push_modal (this);
115+
modal_proxy = wm.push_modal (this, true);
116116
modal_proxy.set_keybinding_filter (keybinding_filter);
117117
modal_proxy.allow_actions ({ ZOOM });
118118

src/Widgets/WindowSwitcher/WindowSwitcher.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ public class Gala.WindowSwitcher : CanvasActor, GestureTarget, RootTarget {
445445
}
446446

447447
private void push_modal () {
448-
modal_proxy = wm.push_modal (this);
448+
modal_proxy = wm.push_modal (this, true);
449449
modal_proxy.allow_actions ({ SWITCH_WINDOWS });
450450
modal_proxy.set_keybinding_filter ((binding) => {
451451
var action = Meta.Prefs.get_keybinding_action (binding.get_name ());

0 commit comments

Comments
 (0)