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
2 changes: 1 addition & 1 deletion data/org.cinnamon.gestures.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
gettext-domain="@GETTEXT_PACKAGE@">
<key name="enabled" type="b">
<default>false</default>
<summary>Enables gesture support using Touchegg.</summary>
<summary>Enables gesture support.</summary>
</key>
<key name="swipe-percent-threshold" type="u">
<default>60</default>
Expand Down
35 changes: 23 additions & 12 deletions files/usr/share/cinnamon/cinnamon-settings/modules/cs_gestures.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
gi.require_version('Gtk', '3.0')
from gi.repository import Gio, Gtk

from bin import util
from bin.SettingsWidgets import SidePage, SettingsWidget
from xapp.GSettingsWidgets import *

Expand Down Expand Up @@ -90,8 +91,15 @@ def __init__(self, content_box):
self.disabled_box = None

def on_module_selected(self):
installed = GLib.find_program_in_path("touchegg")
alive = self.test_daemon_alive()
self.is_wayland = util.get_session_type() == "wayland"

# On X11, check for touchegg; on Wayland, native gestures are used
if self.is_wayland:
installed = True
alive = True
else:
installed = GLib.find_program_in_path("touchegg")
alive = self.test_daemon_alive()

if self.gesture_settings is None:
self.gesture_settings = Gio.Settings(schema_id=SCHEMA)
Expand Down Expand Up @@ -263,21 +271,24 @@ def sort_by_direction(key1, key2):
self.disabled_retry_button.set_visible(False)
self.disabled_page_disable_button.set_visible(False)

if not installed:
text = _("The touchegg package must be installed for gesture support.")
self.disabled_retry_button.show()
elif not self.gesture_settings.get_boolean("enabled"):
text = ""
if not self.gesture_settings.get_boolean("enabled"):
self.disabled_page_switch.set_visible(True)
text = _("Gestures are disabled")
elif not alive:
text = _("The Touchegg service is not running")
if self.gesture_settings.get_boolean("enabled"):
self.disabled_page_disable_button.set_visible(True)
self.disabled_retry_button.show()
elif not self.is_wayland:
# X11-specific: check for touchegg
if not installed:
text = _("The touchegg package must be installed for gesture support.")
self.disabled_retry_button.show()
elif not alive:
text = _("The Touchegg service is not running")
if self.gesture_settings.get_boolean("enabled"):
self.disabled_page_disable_button.set_visible(True)
self.disabled_retry_button.show()

self.sidePage.stack.set_transition_type(Gtk.StackTransitionType.NONE)

if not enabled or not alive or not installed:
if not enabled or (not self.is_wayland and (not alive or not installed)):
self.disabled_label.set_markup(f"<big><b>{text}</b></big>")
page = "disabled"
else:
Expand Down
18 changes: 17 additions & 1 deletion js/misc/mprisPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,9 +538,25 @@ var MprisPlayerManager = class MprisPlayerManager {
});
}

_isInstance(busName) {
// MPRIS instances are in the form
// org.mpris.MediaPlayer2.name.instanceXXXX
// ...except for VLC, which to this day uses
// org.mpris.MediaPlayer2.name-XXXX
return busName.split('.').length > 4 ||
/^org\.mpris\.MediaPlayer2\.vlc-\d+$/.test(busName);
}

_addPlayer(busName, owner) {
if (this._players[owner]) {
return; // Already tracking this player
// If we already have a player for this owner, prefer the instance
// bus name over the base name - it's more specific and some players
// register both.
let existing = this._players[owner];
if (this._isInstance(busName) && !this._isInstance(existing.getBusName())) {
existing._busName = busName;
}
return;
}

let player = new MprisPlayer(busName, owner);
Expand Down
31 changes: 13 additions & 18 deletions js/ui/gestures/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

const { GLib, Gio, Cinnamon, Meta, Cvc } = imports.gi;
const Main = imports.ui.main;
const { GestureType } = imports.ui.gestures.ToucheggTypes;
const { MprisController } = imports.ui.gestures.mprisController;
const { GestureType } = imports.ui.gestures.gestureTypes;
const { getMprisPlayerManager } = imports.misc.mprisPlayer;
const Magnifier = imports.ui.magnifier;

const touchpad_settings = new Gio.Settings({ schema_id: "org.cinnamon.desktop.peripherals.touchpad" });

const CONTINUOUS_ACTION_POLL_INTERVAL = 50 * 1000;
const CONTINUOUS_ACTION_POLL_INTERVAL = 50; // milliseconds

var make_action = (settings, definition, device) => {
var threshold = 100;
Expand Down Expand Up @@ -65,10 +65,7 @@ var cleanup = () => {
mixer = null;
}

if (mpris_controller != null) {
mpris_controller.shutdown();
mpris_controller = null;
}
mpris_manager = null;
}

var BaseAction = class {
Expand Down Expand Up @@ -142,7 +139,7 @@ var WindowOpAction = class extends BaseAction {
const window = global.display.get_focus_window();

if (window == null) {
global.logWarning("WorkspaceSwitchAction: no focus window");
global.logWarning("WindowOpAction: no focus window");
return
}

Expand Down Expand Up @@ -438,13 +435,13 @@ var VolumeAction = class extends BaseAction {
}
}

var mpris_controller = null;
var mpris_manager = null;
var init_mpris_controller = () => {
if (mpris_controller != null) {
if (mpris_manager != null) {
return;
}

mpris_controller = new MprisController();
mpris_manager = getMprisPlayerManager();
}

var MediaAction = class extends BaseAction {
Expand All @@ -453,28 +450,26 @@ var MediaAction = class extends BaseAction {
}

do_action(direction, percentage, time) {
const player = mpris_controller.get_player();
const player = mpris_manager.getBestPlayer();

if (player == null) {
return;
}

if (this.definition.action === "MEDIA_PLAY_PAUSE") {
player.toggle_play()
player.playPause();
}
else
if (this.definition.action === "MEDIA_NEXT") {
player.next_track();
player.next();
}
else
if (this.definition.action === "MEDIA_PREVIOUS") {
player.previous_track();
player.previous();
}
}
}

const ZOOM_SAMPLE_RATE = 20 * 1000 // 20 ms; g_get_monotonic_time() returns microseconds

var ZoomAction = class extends BaseAction {
constructor(definition, device, threshold) {
super(definition, device, threshold);
Expand All @@ -484,7 +479,7 @@ var ZoomAction = class extends BaseAction {

if (definition.custom_value !== "") {
try {
let adjust = parseInt(definition.custom_value) * 1000;
let adjust = parseInt(definition.custom_value);
this.poll_interval = this.poll_interval + adjust;
} catch (e) {}
}
Expand Down
File renamed without changes.
81 changes: 30 additions & 51 deletions js/ui/gestures/gesturesManager.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-

const { Gio, GObject, Cinnamon, Meta } = imports.gi;
const Util = imports.misc.util;
const { Gio, Meta } = imports.gi;
const SignalManager = imports.misc.signalManager;
const ScreenSaver = imports.misc.screenSaver;
const Main = imports.ui.main;

const actions = imports.ui.gestures.actions;
const {
const {
GestureType,
GestureDirection,
DeviceType,
GestureTypeString,
GestureDirectionString,
GesturePhaseString,
DeviceTypeString
} = imports.ui.gestures.ToucheggTypes;
} = imports.ui.gestures.gestureTypes;
const { NativeGestureSource } = imports.ui.gestures.nativeGestureSource;
const { ToucheggGestureSource } = imports.ui.gestures.toucheggGestureSource;

const SCHEMA = "org.cinnamon.gestures";
const TOUCHPAD_SCHEMA = "org.cinnamon.desktop.peripherals.touchpad"

const NON_GESTURE_KEYS = [
"enabled",
Expand Down Expand Up @@ -86,20 +84,24 @@ var GestureDefinition = class {

var GesturesManager = class {
constructor(wm) {
if (Meta.is_wayland_compositor()) {
global.log("Gestures disabled on Wayland");
return;
}

this.signalManager = new SignalManager.SignalManager(null);
this.settings = new Gio.Settings({ schema_id: SCHEMA })
this.current_gesture = null;
this.live_actions = new Map();

if (Meta.is_wayland_compositor()) {
this.gestureSource = new NativeGestureSource();
} else {
this.gestureSource = new ToucheggGestureSource();
}

this.migrate_settings();

this.signalManager.connect(this.settings, "changed", this.settings_or_devices_changed, this);
this.screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
this.client = null;
this.current_gesture = null;

this.gestureSource.connect('gesture-begin', this.gesture_begin.bind(this));
this.gestureSource.connect('gesture-update', this.gesture_update.bind(this));
this.gestureSource.connect('gesture-end', this.gesture_end.bind(this));

this.settings_or_devices_changed()
}
Expand Down Expand Up @@ -142,50 +144,27 @@ var GesturesManager = class {
}
}

setup_client() {
if (this.client == null) {
global.log('Set up Touchegg client');
actions.init_mixer();
actions.init_mpris_controller();

this.client = new Cinnamon.ToucheggClient();

this.signalManager.connect(this.client, "gesture-begin", this.gesture_begin, this);
this.signalManager.connect(this.client, "gesture-update", this.gesture_update, this);
this.signalManager.connect(this.client, "gesture-end", this.gesture_end, this);
}
}

shutdown_client() {
if (this.client == null) {
return;
}

global.log('Shutdown Touchegg client');
this.signalManager.disconnect("gesture-begin");
this.signalManager.disconnect("gesture-update");
this.signalManager.disconnect("gesture-end");
this.client = null;

actions.cleanup();
}

settings_or_devices_changed(settings, key) {
if (this.settings.get_boolean("enabled")) {
this.setup_actions();
return;
}

this.shutdown_client();
this.gestureSource.shutdown();
actions.cleanup();
}

gesture_active() {
return this.current_gesture != null;
}

setup_actions() {
// Make sure the client is setup
this.setup_client();
// Make sure gesture source is set up
if (!this.gestureSource.isActive()) {
actions.init_mixer();
actions.init_mpris_controller();
this.gestureSource.setup();
}

this.live_actions = new Map();

Expand Down Expand Up @@ -250,13 +229,13 @@ var GesturesManager = class {
return definition;
}

gesture_begin(client, type, direction, percentage, fingers, device, elapsed_time) {
gesture_begin(source, type, direction, percentage, fingers, device, elapsed_time) {
if (this.current_gesture != null) {
global.logWarning("New gesture started before another was completed. Clearing the old one");
this.current_gesture = null;
}

if (this.screenSaverProxy.screenSaverActive) {
if (Main.screensaverController?.locked) {
debug_gesture(`Ignoring 'gesture-begin', screensaver is active`);
return;
}
Expand All @@ -277,7 +256,7 @@ var GesturesManager = class {
this.current_gesture.begin(direction, percentage, elapsed_time);
}

gesture_update(client, type, direction, percentage, fingers, device, elapsed_time) {
gesture_update(source, type, direction, percentage, fingers, device, elapsed_time) {
if (this.current_gesture == null) {
debug_gesture("Gesture update but there's no current one.");
return;
Expand All @@ -294,7 +273,7 @@ var GesturesManager = class {
this.current_gesture.update(direction, percentage, elapsed_time);
}

gesture_end(client, type, direction, percentage, fingers, device, elapsed_time) {
gesture_end(source, type, direction, percentage, fingers, device, elapsed_time) {
if (this.current_gesture == null) {
debug_gesture("Gesture end but there's no current one.");
return;
Expand Down
Loading
Loading