From 58242fc01a00bbb5e0f7585b64144b4254736a72 Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Wed, 29 May 2024 23:35:26 +0200 Subject: [PATCH 1/7] Allow launching apps at indeces via command line --- src/Application.vala | 29 ++++++++++++++++++++++++++++- src/LauncherManager.vala | 5 +++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Application.vala b/src/Application.vala index 85eb5a61a..3ccd27f8e 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -4,8 +4,21 @@ */ public class Dock.Application : Gtk.Application { + private const string LAUNCH_INDEX = "launch-index"; + + private const OptionEntry[] OPTIONS = { + { LAUNCH_INDEX, 'i', OptionFlags.NONE, OptionArg.INT, null, "Launch the app that's currently at the given index. Should only be used if dock is already running", "INT" }, + }; + public Application () { - Object (application_id: "io.elementary.dock"); + Object ( + application_id: "io.elementary.dock", + flags: ApplicationFlags.HANDLES_COMMAND_LINE + ); + } + + construct { + add_main_option_entries (OPTIONS); } protected override void startup () { @@ -23,6 +36,20 @@ public class Dock.Application : Gtk.Application { gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == DARK; } + protected override int command_line (ApplicationCommandLine command_line) { + var options = command_line.get_options_dict (); + + if (LAUNCH_INDEX in options) { + // Cast to int to automatically get the int from the variant and then to uint for our index + // I like how this looks so I left it instead of something more expressive like get_int32 :P + LauncherManager.get_default ().launch ((uint)(int) options.lookup_value (LAUNCH_INDEX, VariantType.INT32)); + } else { + activate (); + } + + return 0; + } + protected override void activate () { if (active_window == null) { var main_window = new MainWindow (); diff --git a/src/LauncherManager.vala b/src/LauncherManager.vala index a3f47ac95..62134901e 100644 --- a/src/LauncherManager.vala +++ b/src/LauncherManager.vala @@ -312,6 +312,11 @@ settings.set_strv ("launchers", new_pinned_ids); } + public void launch (uint index) { + var context = Gdk.Display.get_default ().get_app_launch_context (); + launchers.nth (index).data.app.launch (context); + } + public void add_launcher_for_id (string app_id) { if (app_id in id_to_app) { id_to_app[app_id].pinned = true; From f423cb339ba4b28795f794be9aa089f55ed04086 Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Thu, 30 May 2024 00:23:19 +0200 Subject: [PATCH 2/7] Use 1 based index and add safeguards --- src/LauncherManager.vala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/LauncherManager.vala b/src/LauncherManager.vala index 62134901e..8c761a813 100644 --- a/src/LauncherManager.vala +++ b/src/LauncherManager.vala @@ -313,8 +313,12 @@ } public void launch (uint index) { + if (index < 1 || index > launchers.length ()) { + return; + } + var context = Gdk.Display.get_default ().get_app_launch_context (); - launchers.nth (index).data.app.launch (context); + launchers.nth (index - 1).data.app.launch (context); } public void add_launcher_for_id (string app_id) { From 788ab227e84057cffb08c35dc31db4c0b9ae6d8d Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Thu, 30 May 2024 13:00:46 +0200 Subject: [PATCH 3/7] Use dbus to grab the accelerators instead of relying on gala to forward them --- data/dock.gschema.xml | 47 +++++++++++++ src/Application.vala | 1 + src/DBus/ShellKeyGrabber.vala | 120 ++++++++++++++++++++++++++++++++++ src/meson.build | 1 + 4 files changed, 169 insertions(+) create mode 100644 src/DBus/ShellKeyGrabber.vala diff --git a/data/dock.gschema.xml b/data/dock.gschema.xml index 96664d1c3..8ecc90868 100644 --- a/data/dock.gschema.xml +++ b/data/dock.gschema.xml @@ -27,4 +27,51 @@ An ordered array of app id's to show as launchers + + + 1']]]> + Launch the first dock item + + + + 2']]]> + Launch the second dock item + + + + 3']]]> + Launch the third dock item + + + + 4']]]> + Launch the fourth dock item + + + + 5']]]> + Launch the fith dock item + + + + 6']]]> + Launch the sixth dock item + + + + 7']]]> + Launch the seventh dock item + + + + 8']]]> + Launch the eigth dock item + + + + 9']]]> + Launch the nineth dock item + + + diff --git a/src/Application.vala b/src/Application.vala index 3ccd27f8e..468905ba1 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -25,6 +25,7 @@ public class Dock.Application : Gtk.Application { base.startup (); Granite.init (); + ShellKeyGrabber.init (); unowned var granite_settings = Granite.Settings.get_default (); unowned var gtk_settings = Gtk.Settings.get_default (); diff --git a/src/DBus/ShellKeyGrabber.vala b/src/DBus/ShellKeyGrabber.vala new file mode 100644 index 000000000..fedeb57f8 --- /dev/null +++ b/src/DBus/ShellKeyGrabber.vala @@ -0,0 +1,120 @@ +/** + * ActionMode: + * @NONE: block action + * @NORMAL: allow action when in window mode, e.g. when the focus is in an application window + * @OVERVIEW: allow action while the overview is active + * @LOCK_SCREEN: allow action when the screen is locked, e.g. when the screen shield is shown + * @UNLOCK_SCREEN: allow action in the unlock dialog + * @LOGIN_SCREEN: allow action in the login screen + * @SYSTEM_MODAL: allow action when a system modal dialog (e.g. authentification or session dialogs) is open + * @LOOKING_GLASS: allow action in looking glass + * @POPUP: allow action while a shell menu is open + */ + +[Flags] +public enum ActionMode { + NONE = 0, + NORMAL = 1 << 0, + OVERVIEW = 1 << 1, + LOCK_SCREEN = 1 << 2, + UNLOCK_SCREEN = 1 << 3, + LOGIN_SCREEN = 1 << 4, + SYSTEM_MODAL = 1 << 5, + LOOKING_GLASS = 1 << 6, + POPUP = 1 << 7, +} + +[Flags] +public enum Meta.KeyBindingFlags { + NONE = 0, + PER_WINDOW = 1 << 0, + BUILTIN = 1 << 1, + IS_REVERSED = 1 << 2, + NON_MASKABLE = 1 << 3, + IGNORE_AUTOREPEAT = 1 << 4, +} + +public struct Accelerator { + public string name; + public ActionMode mode_flags; + public Meta.KeyBindingFlags grab_flags; +} + +[DBus (name = "org.gnome.Shell")] +public interface ShellKeyGrabber : GLib.Object { + public abstract signal void accelerator_activated (uint action, GLib.HashTable parameters_dict); + + public abstract uint grab_accelerator (string accelerator, ActionMode mode_flags, Meta.KeyBindingFlags grab_flags) throws GLib.DBusError, GLib.IOError; + public abstract uint[] grab_accelerators (Accelerator[] accelerators) throws GLib.DBusError, GLib.IOError; + public abstract bool ungrab_accelerator (uint action) throws GLib.DBusError, GLib.IOError; + public abstract bool ungrab_accelerators (uint[] actions) throws GLib.DBusError, GLib.IOError; + + private static Settings settings; + private static ShellKeyGrabber? instance; + + private static HashTable saved_action_ids; + + public static void init () { + settings = new Settings ("io.elementary.dock.keybindings"); + saved_action_ids = new HashTable (null, null); + + settings.changed.connect (() => { + ungrab_keybindings (); + setup_grabs (); + }); + + Bus.watch_name (BusType.SESSION, "org.gnome.Shell", BusNameWatcherFlags.NONE, () => on_watch.begin (), () => instance = null); + } + + private static async void on_watch () { + try { + instance = yield Bus.get_proxy (SESSION, "org.gnome.Shell", "/org/gnome/Shell"); + warning ("GOT PROXY"); + setup_grabs (); + } catch (Error e) { + warning ("Failed to connect to bus for keyboard shortcut grabs: %s", e.message); + } + } + + private static void setup_grabs () requires (instance != null) { + for (int i = 1; i <= 9; i++) { + var keybindings = settings.get_strv ("launch-dock-%d".printf (i)); + Accelerator[] accelerators = {}; + for (int j = 0; j < keybindings.length; j++) { + accelerators += Accelerator () { + name = keybindings[j], + mode_flags = ActionMode.NONE, + grab_flags = Meta.KeyBindingFlags.NONE + }; + + try { + foreach (var id in instance.grab_accelerators (accelerators)) { + saved_action_ids[id] = i; + } + } catch (Error e) { + critical ("Couldn't grab accelerators: %s", e.message); + } + } + } + + instance.accelerator_activated.connect (on_accelerator_activated); + } + + private static void on_accelerator_activated (uint action, GLib.HashTable parameters_dict) { + if (!(action in saved_action_ids)) { + return; + } + + Dock.LauncherManager.get_default ().launch (saved_action_ids[action]); + } + + private static void ungrab_keybindings () requires (instance != null) { + var actions = saved_action_ids.get_keys_as_array (); + + try { + instance.ungrab_accelerators (actions); + } catch (Error e) { + critical ("Couldn't ungrab accelerators: %s", e.message); + } + } +} diff --git a/src/meson.build b/src/meson.build index 0ed8fe590..30e3413d8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -8,6 +8,7 @@ sources = [ 'MainWindow.vala', 'PoofPopover.vala', 'DBus' / 'ItemInterface.vala', + 'DBus' / 'ShellKeyGrabber.vala', 'DBus' / 'SwitcherooControl.vala', 'DBus' / 'Unity.vala' ] From 89815c6f7a34f36ba96b84b4eb2142b079586957 Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Thu, 30 May 2024 13:05:06 +0200 Subject: [PATCH 4/7] Remove debugging --- src/DBus/ShellKeyGrabber.vala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DBus/ShellKeyGrabber.vala b/src/DBus/ShellKeyGrabber.vala index fedeb57f8..574f4e297 100644 --- a/src/DBus/ShellKeyGrabber.vala +++ b/src/DBus/ShellKeyGrabber.vala @@ -69,7 +69,6 @@ public interface ShellKeyGrabber : GLib.Object { private static async void on_watch () { try { instance = yield Bus.get_proxy (SESSION, "org.gnome.Shell", "/org/gnome/Shell"); - warning ("GOT PROXY"); setup_grabs (); } catch (Error e) { warning ("Failed to connect to bus for keyboard shortcut grabs: %s", e.message); From f89c6f06cda89ca788f28ee4f5c672b19df0e390 Mon Sep 17 00:00:00 2001 From: Leonhard <106322251+leolost2605@users.noreply.github.com> Date: Thu, 30 May 2024 18:53:02 +0200 Subject: [PATCH 5/7] Update Application.vala --- src/Application.vala | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 468905ba1..7571adf47 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -4,23 +4,13 @@ */ public class Dock.Application : Gtk.Application { - private const string LAUNCH_INDEX = "launch-index"; - - private const OptionEntry[] OPTIONS = { - { LAUNCH_INDEX, 'i', OptionFlags.NONE, OptionArg.INT, null, "Launch the app that's currently at the given index. Should only be used if dock is already running", "INT" }, - }; public Application () { Object ( - application_id: "io.elementary.dock", - flags: ApplicationFlags.HANDLES_COMMAND_LINE + application_id: "io.elementary.dock" ); } - construct { - add_main_option_entries (OPTIONS); - } - protected override void startup () { base.startup (); @@ -37,20 +27,6 @@ public class Dock.Application : Gtk.Application { gtk_settings.gtk_application_prefer_dark_theme = granite_settings.prefers_color_scheme == DARK; } - protected override int command_line (ApplicationCommandLine command_line) { - var options = command_line.get_options_dict (); - - if (LAUNCH_INDEX in options) { - // Cast to int to automatically get the int from the variant and then to uint for our index - // I like how this looks so I left it instead of something more expressive like get_int32 :P - LauncherManager.get_default ().launch ((uint)(int) options.lookup_value (LAUNCH_INDEX, VariantType.INT32)); - } else { - activate (); - } - - return 0; - } - protected override void activate () { if (active_window == null) { var main_window = new MainWindow (); From 75714ca6f2c5f9ac364538072d8dba7beed86bec Mon Sep 17 00:00:00 2001 From: Leonhard <106322251+leolost2605@users.noreply.github.com> Date: Thu, 30 May 2024 18:53:31 +0200 Subject: [PATCH 6/7] Update Application.vala --- src/Application.vala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 7571adf47..207ed5fb8 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -4,11 +4,8 @@ */ public class Dock.Application : Gtk.Application { - public Application () { - Object ( - application_id: "io.elementary.dock" - ); + Object (application_id: "io.elementary.dock"); } protected override void startup () { From 82b5ff7c4b42fff5bcd6c2a7521cd76c49e21d80 Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Thu, 30 May 2024 20:37:28 +0200 Subject: [PATCH 7/7] Add license header --- src/DBus/ShellKeyGrabber.vala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/DBus/ShellKeyGrabber.vala b/src/DBus/ShellKeyGrabber.vala index 574f4e297..52fc228f1 100644 --- a/src/DBus/ShellKeyGrabber.vala +++ b/src/DBus/ShellKeyGrabber.vala @@ -1,3 +1,8 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io) + */ + /** * ActionMode: * @NONE: block action