Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/Gestures/Gesture.vala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace Gala {
MULTITASKING_VIEW,
ZOOM,
CUSTOM,
CUSTOM_2,
N_ACTIONS
}

Expand Down
134 changes: 134 additions & 0 deletions lib/Gestures/WorkspaceHideTracker.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
*/

public class Gala.WorkspaceHideTracker : Object, GestureTarget {
public signal double compute_progress (Meta.Workspace workspace);
public signal void switching_workspace_progress_updated (double new_progress);
public signal void window_state_changed_progress_updated (double new_progress);

//we don't want to hold a strong reference to the actor because we might've been added to it which would form a reference cycle
private weak Clutter.Actor? _actor;
public Clutter.Actor? actor { get { return _actor; }}
public Meta.Display display { private get; construct; }

private double switch_workspace_progress = 0.0;
private double[] workspace_hide_progress_cache = {};

public WorkspaceHideTracker (Meta.Display display, Clutter.Actor actor) {
Object (display: display);
_actor = actor;
}

construct {
display.list_all_windows ().foreach (setup_window);
display.window_created.connect (setup_window);

unowned var monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
monitor_manager.monitors_changed.connect (recalculate_all_workspaces);

unowned var workspace_manager = display.get_workspace_manager ();
workspace_manager.workspace_added.connect (recalculate_all_workspaces);
workspace_manager.workspace_removed.connect (recalculate_all_workspaces);

recalculate_all_workspaces ();
}

private void setup_window (Meta.Window window) {
window.notify["window-type"].connect (on_window_type_changed);

if (!Utils.get_window_is_normal (window)) {
return;
}

if (window.on_all_workspaces) {
recalculate_all_workspaces ();
} else {
recalculate_workspace (window);
}

window.position_changed.connect (recalculate_workspace);
window.size_changed.connect (recalculate_workspace);
window.workspace_changed.connect (recalculate_all_workspaces);
window.focused.connect (recalculate_workspace);
window.notify["on-all-workspaces"].connect (recalculate_all_workspaces);
window.notify["fullscreen"].connect (recalculate_workspace_pspec);
window.notify["minimized"].connect (recalculate_workspace_pspec);
window.notify["above"].connect (recalculate_workspace_pspec);
window.unmanaged.connect (recalculate_workspace);
}

private void on_window_type_changed (Object obj, ParamSpec pspec) {
var window = (Meta.Window) obj;

window.notify["window-type"].disconnect (on_window_type_changed);
window.position_changed.disconnect (recalculate_workspace);
window.size_changed.disconnect (recalculate_workspace);
window.workspace_changed.disconnect (recalculate_all_workspaces);
window.focused.disconnect (recalculate_workspace);
window.notify["on-all-workspaces"].disconnect (recalculate_all_workspaces);
window.notify["fullscreen"].disconnect (recalculate_workspace_pspec);
window.notify["minimized"].disconnect (recalculate_workspace_pspec);
window.notify["above"].disconnect (recalculate_workspace_pspec);
window.unmanaged.disconnect (recalculate_workspace);

setup_window (window);
}

public override void propagate (UpdateType update_type, GestureAction action, double progress) {
if (action != SWITCH_WORKSPACE || update_type == COMMIT) {
return;
}

switch_workspace_progress = progress.abs ();
switching_workspace_progress_updated (get_hidden_progress ());
}

private double get_hidden_progress () {
var n_workspaces = workspace_hide_progress_cache.length;

var left_workspace = int.max ((int) Math.floor (switch_workspace_progress), 0);
var right_workspace = int.min ((int) Math.ceil (switch_workspace_progress), n_workspaces - 1);

var relative_progress = switch_workspace_progress - left_workspace;

return (
workspace_hide_progress_cache[left_workspace] * (1 - relative_progress) +
workspace_hide_progress_cache[right_workspace] * relative_progress
);
}

/**
* Trigger recalculation of all workspaces
*/
public void recalculate_all_workspaces () {
unowned var workspace_manager = display.get_workspace_manager ();
workspace_hide_progress_cache = new double[workspace_manager.n_workspaces];
foreach (unowned var workspace in workspace_manager.get_workspaces ()) {
internal_recalculate_workspace (workspace, false);
}

window_state_changed_progress_updated (get_hidden_progress ());
}

private void internal_recalculate_workspace (Meta.Workspace? workspace, bool send_signal) {
if (workspace == null || workspace.workspace_index >= workspace_hide_progress_cache.length) {
return;
}

workspace_hide_progress_cache[workspace.workspace_index] = compute_progress (workspace);

if (send_signal) {
window_state_changed_progress_updated (get_hidden_progress ());
}
}

private void recalculate_workspace (Meta.Window window) {
internal_recalculate_workspace (window.get_workspace (), true);
}

private void recalculate_workspace_pspec (Object obj, ParamSpec pspec) {
internal_recalculate_workspace (((Meta.Window) obj).get_workspace (), true);
}
}
8 changes: 8 additions & 0 deletions lib/WindowManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,13 @@ namespace Gala {
* @return true if the action should be prohibited, false otherwise
*/
public abstract bool filter_action (GestureAction action);

/**
* Adds target to the multitasking view and window overview so the target responds to the multitasking view
* close/open gesture and shortcuts.
*
* @param target Target to add to multitasking view and window overview
*/
public abstract void add_multitasking_view_target (GestureTarget target);
}
}
3 changes: 2 additions & 1 deletion lib/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ gala_lib_sources = files(
'Gestures/ScrollBackend.vala',
'Gestures/SpringTimeline.vala',
'Gestures/ToucheggBackend.vala',
'Gestures/TouchpadBackend.vala'
'Gestures/TouchpadBackend.vala',
'Gestures/WorkspaceHideTracker.vala'
) + gala_common_enums

gala_resources = gnome.compile_resources(
Expand Down
32 changes: 16 additions & 16 deletions plugins/pip/Main.vala
Original file line number Diff line number Diff line change
Expand Up @@ -97,33 +97,31 @@ public class Gala.Plugins.PIP.Plugin : Gala.Plugin {
return;
}

var popup_window = new PopupWindow (wm.get_display (), active);
var popup_window = new PopupWindow (wm, active);
popup_window.set_container_clip (rect);
popup_window.show.connect (on_popup_window_show);
popup_window.hide.connect (on_popup_window_hide);
add_window (popup_window);
}

private void on_popup_window_show (Clutter.Actor popup_window) {
track_actor (popup_window);
update_region ();
}

private void on_popup_window_hide (Clutter.Actor popup_window) {
untrack_actor (popup_window);
update_region ();
}

private void select_window_at (int x, int y) {
var selected = get_window_actor_at (x, y);
if (selected != null) {
var popup_window = new PopupWindow (wm.get_display (), selected);
popup_window.show.connect (on_popup_window_show);
popup_window.hide.connect (on_popup_window_hide);
var popup_window = new PopupWindow (wm, selected);
add_window (popup_window);
}
}

private void popup_window_reactive_changed (GLib.Object obj, GLib.ParamSpec pspec) requires (obj is PopupWindow) {
var popup_window = (PopupWindow) obj;

if (popup_window.reactive) {
track_actor (popup_window);
} else {
untrack_actor (popup_window);
}

update_region ();
}

private void clear_selection_area () {
if (selection_area != null) {
untrack_actor (selection_area);
Expand Down Expand Up @@ -189,6 +187,8 @@ public class Gala.Plugins.PIP.Plugin : Gala.Plugin {
}

private void add_window (PopupWindow popup_window) {
track_actor (popup_window);
popup_window.notify["reactive"].connect (popup_window_reactive_changed);
popup_window.closed.connect (() => remove_window (popup_window));
windows.add (popup_window);
wm.ui_group.add_child (popup_window);
Expand Down
Loading
Loading