diff --git a/data/gala.gschema.xml b/data/gala.gschema.xml index e6bff01ba..b727649b0 100644 --- a/data/gala.gschema.xml +++ b/data/gala.gschema.xml @@ -14,6 +14,12 @@ + + + + + + true @@ -96,6 +102,11 @@ Whether hotcorners should be enabled when fullscreen window is opened + + "none" + What action should be performed on Super + Scroll + + diff --git a/lib/WindowManager.vala b/lib/WindowManager.vala index 38cb294a6..5fc5e184f 100644 --- a/lib/WindowManager.vala +++ b/lib/WindowManager.vala @@ -123,6 +123,12 @@ namespace Gala { */ public abstract Gala.ActivatableComponent workspace_view { get; protected set; } + /* + * This signal is sent when Super + Scroll was performed and WindowManager couldn't handle it + * which probably means that the user doesn't want to switch workspaces on Super + Scroll. + */ + public abstract signal void super_scroll_triggered (uint32 timestamp, double dx, double dy); + /** * Enters the modal mode, which means that all events are directed to the stage instead * of the windows. This is the only way to receive keyboard events besides shortcut listeners. diff --git a/src/SuperScrollAction.vala b/src/SuperScrollAction.vala new file mode 100644 index 000000000..430ba82ec --- /dev/null +++ b/src/SuperScrollAction.vala @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io) + */ + +public class Gala.SuperScrollAction : Clutter.Action { + public signal void triggered (uint32 timestamp, double dx, double dy); + + public Meta.Display display { private get; construct; } + + public SuperScrollAction (Meta.Display display) { + Object (display: display); + } + + public override bool handle_event (Clutter.Event event) { + if ( + event.get_type () == SCROLL && + (event.get_state () & display.compositor_modifiers) != 0 + ) { + double dx = 0.0, dy = 0.0; + switch (event.get_scroll_direction ()) { + case LEFT: + dx = -1.0; + break; + case RIGHT: + dx = 1.0; + break; + case UP: + dy = 1.0; + break; + case DOWN: + dy = -1.0; + break; + default: + break; + } + + // TODO: support natural scroll settings + + triggered (event.get_time (), dx, dy); + + return Clutter.EVENT_STOP; + } + + return Clutter.EVENT_PROPAGATE; + } +} diff --git a/src/WindowManager.vala b/src/WindowManager.vala index 825b11cf3..8886bb827 100644 --- a/src/WindowManager.vala +++ b/src/WindowManager.vala @@ -159,6 +159,21 @@ namespace Gala { #endif } + private void handle_super_scroll (uint32 timestamp, double dx, double dy) { + if (behavior_settings.get_enum ("super-scroll-action") != 1) { + super_scroll_triggered (timestamp, dx, dy); + return; + } + + var d = dx.abs () > dy.abs () ? dx : dy; + + if (d > 0) { + switch_to_next_workspace (Meta.MotionDirection.RIGHT, timestamp); + } else if (d < 0) { + switch_to_next_workspace (Meta.MotionDirection.LEFT, timestamp); + } + } + #if WITH_SYSTEMD private async void start_x11_services (GLib.Task task) { try { @@ -396,6 +411,10 @@ namespace Gala { display.window_created.connect ((window) => window_created (window)); + var scroll_action = new SuperScrollAction (display); + scroll_action.triggered.connect (handle_super_scroll); + stage.add_action_full ("super-scroll-action", CAPTURE, scroll_action); + stage.show (); Idle.add (() => { diff --git a/src/Zoom.vala b/src/Zoom.vala index 29d471d47..db9dc8d98 100644 --- a/src/Zoom.vala +++ b/src/Zoom.vala @@ -19,6 +19,7 @@ public class Gala.Zoom : Object { private ulong wins_handler_id = 0UL; private GestureTracker gesture_tracker; + private GLib.Settings behavior_settings; public Zoom (WindowManager wm) { Object (wm: wm); @@ -32,6 +33,9 @@ public class Gala.Zoom : Object { gesture_tracker = new GestureTracker (ANIMATION_DURATION, ANIMATION_DURATION); gesture_tracker.enable_touchpad (); gesture_tracker.on_gesture_detected.connect (on_gesture_detected); + + behavior_settings = new GLib.Settings ("io.elementary.desktop.wm.behavior"); + wm.super_scroll_triggered.connect (handle_super_scroll); } ~Zoom () { @@ -75,6 +79,20 @@ public class Gala.Zoom : Object { } } + private void handle_super_scroll (uint32 timestamp, double dx, double dy) { + if (behavior_settings.get_enum ("super-scroll-action") != 2) { + return; + } + + var d = dx.abs () > dy.abs () ? dx : dy; + + if (d > 0) { + zoom (SHORTCUT_DELTA, true, AnimationsSettings.get_enable_animations ()); + } else if (d < 0) { + zoom (-SHORTCUT_DELTA, true, AnimationsSettings.get_enable_animations ()); + } + } + private void zoom_with_gesture (GestureDirection direction) { var initial_zoom = current_zoom; var target_zoom = (direction == GestureDirection.IN) diff --git a/src/meson.build b/src/meson.build index 70d9d7b97..9660dd2b8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -14,6 +14,7 @@ gala_bin_sources = files( 'ScreenSaverManager.vala', 'ScreenshotManager.vala', 'SessionManager.vala', + 'SuperScrollAction.vala', 'WindowAttentionTracker.vala', 'WindowGrabTracker.vala', 'WindowListener.vala',