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/src/SuperScrollAction.vala b/src/SuperScrollAction.vala new file mode 100644 index 000000000..84698cb3a --- /dev/null +++ b/src/SuperScrollAction.vala @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io) + */ + +public class Gala.SuperScrollAction : Clutter.Action { + public signal bool 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 + + return triggered (event.get_time (), dx, dy); + } + + return Clutter.EVENT_PROPAGATE; + } +} diff --git a/src/WindowManager.vala b/src/WindowManager.vala index 5606d0488..8a1b90375 100644 --- a/src/WindowManager.vala +++ b/src/WindowManager.vala @@ -383,6 +383,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 ("wm-super-scroll-action", CAPTURE, scroll_action); + stage.show (); plugin_manager.load_waiting_plugins (); @@ -438,6 +442,23 @@ namespace Gala { } } + + private bool handle_super_scroll (uint32 timestamp, double dx, double dy) { + if (behavior_settings.get_enum ("super-scroll-action") != 1) { + return Clutter.EVENT_PROPAGATE; + } + + 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); + } + + return Clutter.EVENT_STOP; + } + [CCode (instance_pos = -1)] private void handle_cycle_workspaces (Meta.Display display, Meta.Window? window, Clutter.KeyEvent event, Meta.KeyBinding binding) { diff --git a/src/Zoom.vala b/src/Zoom.vala index 9165bd1f7..e833f4134 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); @@ -33,6 +34,12 @@ public class Gala.Zoom : Object { gesture_tracker.enable_touchpad (); gesture_tracker.on_gesture_detected.connect (on_gesture_detected); gesture_tracker.on_gesture_handled.connect ((gesture) => zoom_with_gesture (gesture.direction)); + + behavior_settings = new GLib.Settings ("io.elementary.desktop.wm.behavior"); + + var scroll_action = new SuperScrollAction (display); + scroll_action.triggered.connect (handle_super_scroll); + display.get_stage ().add_action_full ("zoom-super-scroll-action", CAPTURE, scroll_action); } ~Zoom () { @@ -78,6 +85,22 @@ public class Gala.Zoom : Object { return false; } + private bool handle_super_scroll (uint32 timestamp, double dx, double dy) { + if (behavior_settings.get_enum ("super-scroll-action") != 2) { + return Clutter.EVENT_PROPAGATE; + } + + 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 ()); + } + + return Clutter.EVENT_STOP; + } + 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',