diff --git a/lib/DragDropAction.vala b/lib/DragDropAction.vala index f22e95169..fdf50fc20 100644 --- a/lib/DragDropAction.vala +++ b/lib/DragDropAction.vala @@ -186,6 +186,10 @@ namespace Gala { } public override bool handle_event (Clutter.Event event) { + if (!actor.reactive){ + return Clutter.EVENT_PROPAGATE; + } + if (!(DragDropActionType.SOURCE in drag_type)) { return Clutter.EVENT_PROPAGATE; } diff --git a/lib/WindowManager.vala b/lib/WindowManager.vala index 6c8304a5e..ea1f84064 100644 --- a/lib/WindowManager.vala +++ b/lib/WindowManager.vala @@ -211,5 +211,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); } } diff --git a/plugins/pip/Main.vala b/plugins/pip/Main.vala index c5976e7e2..b0fedd1ff 100644 --- a/plugins/pip/Main.vala +++ b/plugins/pip/Main.vala @@ -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); @@ -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); diff --git a/plugins/pip/PopupWindow.vala b/plugins/pip/PopupWindow.vala index 31c1e3a81..23f436e1f 100644 --- a/plugins/pip/PopupWindow.vala +++ b/plugins/pip/PopupWindow.vala @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { +public class Gala.Plugins.PIP.PopupWindow : RootTarget, ActorTarget { private int button_size; private int container_margin; private const uint FADE_OUT_TIMEOUT = 200; @@ -15,7 +15,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { public signal void closed (); - public Meta.Display display { get; construct; } + public WindowManager wm { get; construct; } public Meta.WindowActor window_actor { get; construct; } private Clutter.Clone clone; // clone itself @@ -26,6 +26,11 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { private Clutter.Actor resize_button; private DragDropAction move_action; + private GestureController gesture_controller; + private PropertyTarget opacity_target; + private double custom_progress = 0.0; + private double multitasking_view_progress = 0.0; + private float begin_resize_width = 0.0f; private float begin_resize_height = 0.0f; private float resize_start_x = 0.0f; @@ -45,11 +50,13 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { height = src_height * ratio; } - public PopupWindow (Meta.Display display, Meta.WindowActor window_actor) { - Object (display: display, window_actor: window_actor); + public PopupWindow (WindowManager wm, Meta.WindowActor window_actor) { + Object (wm: wm, window_actor: window_actor); } construct { + unowned var display = wm.get_display (); + var scale = display.get_monitor_scale (display.get_current_monitor ()); button_size = Gala.Utils.scale_to_int (36, scale); @@ -71,9 +78,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { rounded_container.add_child (clone_container); rounded_container.add_effect (new RoundedCornersEffect (6, scale)); - container = new Clutter.Actor () { - reactive = true - }; + container = new Clutter.Actor (); container.add_child (rounded_container); container.add_effect (new ShadowEffect ("window", scale)); @@ -118,7 +123,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { window_actor.notify["allocation"].connect (on_allocation_changed); container.set_position (container_margin, container_margin); - update_clone_clip (); + on_allocation_changed (); unowned var window = window_actor.get_meta_window (); window.unmanaged.connect (on_close_click_clicked); @@ -126,37 +131,54 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { unowned var workspace_manager = display.get_workspace_manager (); workspace_manager.active_workspace_changed.connect (update_window_focus); + + gesture_controller = new GestureController (CUSTOM, wm); + add_gesture_controller (gesture_controller); + + opacity_target = new PropertyTarget (CUSTOM, this, "opacity", typeof (uint), 255u, 0u); + add_target (opacity_target); + + wm.add_multitasking_view_target (this); } - public override void show () { - base.show (); + private double get_opacity_progress () { + return double.max (custom_progress, multitasking_view_progress); + } - opacity = 0; + public override void start_progress (GestureAction action) { + if (action != CUSTOM && action != MULTITASKING_VIEW) { + return; + } - save_easing_state (); - set_easing_duration (Utils.get_animation_duration (200)); - opacity = 255; - restore_easing_state (); + move_action.cancel (); + stop_resizing (); + hide_buttons (); + reactive = false; } - public override void hide () { - opacity = 255; + public override void end_progress (GestureAction action) { + if (action != CUSTOM && action != MULTITASKING_VIEW) { + return; + } - var duration = Utils.get_animation_duration (200); - save_easing_state (); - set_easing_duration (duration); - opacity = 0; - restore_easing_state (); + reactive = get_current_progress (CUSTOM) == 0.0 && get_current_progress (MULTITASKING_VIEW) == 0.0; + } - if (duration == 0) { - base.hide (); - } else { - ulong completed_id = 0; - completed_id = transitions_completed.connect (() => { - disconnect (completed_id); - base.hide (); - }); + public override void update_progress (GestureAction action, double progress) { + switch (action) { + case MULTITASKING_VIEW: + multitasking_view_progress = progress; + break; + + case CUSTOM: + custom_progress = progress; + break; + + default: + break; } + + opacity_target.propagate (UPDATE, CUSTOM, get_opacity_progress ()); } public override bool enter_event (Clutter.Event event) { @@ -176,6 +198,11 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { } public override bool leave_event (Clutter.Event event) { + hide_buttons (); + return Clutter.EVENT_PROPAGATE; + } + + private void hide_buttons () { var duration = Utils.get_animation_duration (300); close_button.save_easing_state (); @@ -187,8 +214,6 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { resize_button.set_easing_duration (duration); resize_button.opacity = 0; resize_button.restore_easing_state (); - - return Clutter.EVENT_PROPAGATE; } public void set_container_clip (Graphene.Rect? container_clip) { @@ -199,18 +224,17 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { private Clutter.Actor on_move_begin () { #if HAS_MUTTER48 - display.set_cursor (Meta.Cursor.MOVE); + wm.get_display ().set_cursor (Meta.Cursor.MOVE); #else - display.set_cursor (Meta.Cursor.DND_IN_DRAG); + wm.get_display ().set_cursor (Meta.Cursor.DND_IN_DRAG); #endif return this; } private void on_move_end () { - reactive = true; update_screen_position (); - display.set_cursor (Meta.Cursor.DEFAULT); + wm.get_display ().set_cursor (Meta.Cursor.DEFAULT); } private bool on_resize_button_press (Clutter.Event event) { @@ -228,7 +252,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { grab = resize_button.get_stage ().grab (resize_button); resize_button.event.connect (on_resize_event); - display.set_cursor (Meta.Cursor.SE_RESIZE); + wm.get_display ().set_cursor (Meta.Cursor.SE_RESIZE); return Clutter.EVENT_PROPAGATE; } @@ -289,7 +313,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { update_screen_position (); - display.set_cursor (Meta.Cursor.DEFAULT); + wm.get_display ().set_cursor (Meta.Cursor.DEFAULT); } private void on_allocation_changed () { @@ -316,6 +340,8 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { } private void update_window_focus () { + unowned var display = wm.get_display (); + unowned Meta.Window focus_window = display.get_focus_window (); if ((focus_window != null && !Utils.get_window_is_normal (focus_window)) || (previous_focus != null && !Utils.get_window_is_normal (previous_focus))) { @@ -328,9 +354,9 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { unowned var window = window_actor.get_meta_window (); if (window.appears_focused && window.located_on_workspace (active_workspace)) { - hide (); + gesture_controller.goto (1.0); } else if (!window_actor.is_destroyed ()) { - show (); + gesture_controller.goto (0.0); } previous_focus = focus_window; @@ -422,7 +448,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { private void place_window_in_screen () { off_screen = false; - var workarea_rect = display.get_workspace_manager ().get_active_workspace ().get_work_area_all_monitors (); + var workarea_rect = wm.get_display ().get_workspace_manager ().get_active_workspace ().get_work_area_all_monitors (); var screen_limit_start_x = workarea_rect.x; var screen_limit_end_x = workarea_rect.x + workarea_rect.width - width; @@ -448,6 +474,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { set_easing_mode (Clutter.AnimationMode.EASE_OUT_BACK); set_easing_duration (duration); + unowned var display = wm.get_display (); var monitor_rect = display.get_monitor_geometry (display.get_current_monitor ()); int monitor_x = monitor_rect.x; @@ -495,6 +522,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { } private bool coord_is_in_other_monitor (float coord, Clutter.Orientation axis) { + unowned var display = wm.get_display (); int n_monitors = display.get_n_monitors (); if (n_monitors == 1) { @@ -534,6 +562,8 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor { } private void activate () { + warning ("Activate"); + if (off_screen) { place_window_in_screen (); } else { diff --git a/src/WindowManager.vala b/src/WindowManager.vala index 0ab8e0968..7ee8b3cb8 100644 --- a/src/WindowManager.vala +++ b/src/WindowManager.vala @@ -1726,6 +1726,14 @@ namespace Gala { return modal_stack.peek_head ().filter_action (action); } + public void add_multitasking_view_target (GestureTarget target) { + multitasking_view.add_target (target); + + if (window_overview is WindowOverview) { + ((WindowOverview) window_overview).add_target (target); + } + } + public override void confirm_display_change () { unowned var monitor_manager = get_display ().get_context ().get_backend ().get_monitor_manager (); var timeout = monitor_manager.get_display_configuration_timeout ();