Skip to content

Commit ff8a550

Browse files
committed
Add settings-daemon application launcher support
1 parent 2d3d951 commit ff8a550

11 files changed

Lines changed: 349 additions & 351 deletions

po/POTFILES

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ src/Layout/Widgets/AdvancedSettingsPanel.vala
2020
src/Layout/Widgets/Display.vala
2121
src/Plug.vala
2222
src/Shortcuts/Backend/ConflictsManager.vala
23-
src/Shortcuts/Backend/CustomShortcutSettings.vala
23+
src/Shortcuts/Backend/CustomShortcuts.vala
2424
src/Shortcuts/Backend/Settings.vala
25-
src/Shortcuts/Backend/ShortcutsList.vala
2625
src/Shortcuts/Backend/Shortcut.vala
27-
src/Shortcuts/Shortcuts.vala
28-
src/Shortcuts/Widgets/ConflictDialog.vala
26+
src/Shortcuts/Backend/ShortcutsList.vala
27+
src/Shortcuts/Widgets/AppChooser.vala
28+
src/Shortcuts/Widgets/AppChooserRow.vala
2929
src/Shortcuts/Widgets/CustomShortcutListBox.vala
30+
src/Shortcuts/Widgets/CustomShortcutRow.vala
3031
src/Shortcuts/Widgets/ShortcutListBox.vala
32+
src/Shortcuts/Shortcuts.vala

src/Shortcuts/Backend/ConflictsManager.vala

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* SPDX-License-Identifier: GPL-2.0-or-later
3-
* SPDX-FileCopyrightText: 2017-2023 elementary, Inc. (https://elementary.io)
3+
* SPDX-FileCopyrightText: 2017-2025 elementary, Inc. (https://elementary.io)
44
*/
55

66
class Keyboard.Shortcuts.ConflictsManager : GLib.Object {
@@ -40,6 +40,19 @@
4040
private static bool custom_shortcut_conflicts (Shortcut shortcut, out string name, out string group) {
4141
name = "";
4242
group = SectionID.CUSTOM.to_string ();
43-
return CustomShortcutSettings.shortcut_conflicts (shortcut, out name, null);
43+
44+
var application_shortcuts = new GLib.Settings (CustomShortcuts.SETTINGS_SCHEMA);
45+
var shortcuts = (CustomShortcuts.ParsedShortcut[]) application_shortcuts.get_value (CustomShortcuts.APPLICATION_SHORTCUTS);
46+
for (int i = 0; i < shortcuts.length; i++) {
47+
for (int j = 0; j < shortcuts[i].keybindings.length; j++) {
48+
var action_shortcut = new Shortcut.parse (shortcuts[i].keybindings[j]);
49+
if (shortcut.is_equal (action_shortcut)) {
50+
name = shortcuts[i].target;
51+
return true;
52+
}
53+
}
54+
}
55+
56+
return false;
4457
}
4558
}

src/Shortcuts/Backend/CustomShortcutSettings.vala

Lines changed: 0 additions & 158 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-2.0-or-later
3+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
4+
*/
5+
6+
namespace Keyboard.Shortcuts.CustomShortcuts {
7+
public enum ActionType {
8+
DESKTOP_FILE,
9+
COMMAND_LINE
10+
}
11+
12+
public struct ParsedShortcut {
13+
ActionType type;
14+
string target;
15+
GLib.HashTable<string, Variant> parameters;
16+
string[] keybindings;
17+
}
18+
19+
public const string SETTINGS_SCHEMA = "io.elementary.settings-daemon.applications";
20+
public const string APPLICATION_SHORTCUTS = "application-shortcuts";
21+
}

src/Shortcuts/Shortcuts.vala

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ namespace Keyboard.Shortcuts {
6262
private SwitcherRow custom_shortcuts_row;
6363

6464
construct {
65-
CustomShortcutSettings.init ();
66-
6765
unowned var list = Shortcuts.ShortcutsList.get_default ();
6866

6967
section_switcher = new Gtk.ListBox ();
@@ -113,12 +111,7 @@ namespace Keyboard.Shortcuts {
113111
for (int id = 0; id < SectionID.CUSTOM; id++) {
114112
shortcut_views += new ShortcutListBox ((SectionID) id);
115113
}
116-
117-
if (CustomShortcutSettings.available) {
118-
var custom_tree = new CustomShortcutListBox ();
119-
120-
shortcut_views += custom_tree;
121-
}
114+
shortcut_views += new CustomShortcutListBox ();
122115

123116
foreach (unowned Gtk.Widget view in shortcut_views) {
124117
stack.add_child (view);
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/* SPDX-License-Identifier: GPL-3.0-or-later
2+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
3+
*/
4+
5+
public class Keyboard.AppChooser : Granite.Dialog {
6+
public signal void app_chosen (string filename, GLib.HashTable<string, Variant> parameters);
7+
public signal void custom_command_chosen (string command, GLib.HashTable<string, Variant> parameters);
8+
9+
private Gtk.ListBox list;
10+
private Gtk.SearchEntry search_entry;
11+
private Gtk.Entry custom_entry;
12+
13+
construct {
14+
search_entry = new Gtk.SearchEntry () {
15+
placeholder_text = _("Search Applications")
16+
};
17+
18+
list = new Gtk.ListBox () {
19+
hexpand = true,
20+
vexpand = true
21+
};
22+
list.add_css_class (Granite.STYLE_CLASS_RICH_LIST);
23+
list.set_sort_func (sort_function);
24+
list.set_filter_func (filter_function);
25+
26+
var scrolled = new Gtk.ScrolledWindow () {
27+
child = list
28+
};
29+
30+
var frame = new Gtk.Frame (null) {
31+
child = scrolled
32+
};
33+
34+
custom_entry = new Gtk.Entry () {
35+
placeholder_text = _("Type in a custom command"),
36+
primary_icon_activatable = false,
37+
primary_icon_name = "utilities-terminal-symbolic"
38+
};
39+
40+
var box = new Gtk.Box (VERTICAL, 6);
41+
box.append (search_entry);
42+
box.append (frame);
43+
box.append (custom_entry);
44+
45+
modal = true;
46+
default_height = 500;
47+
default_width = 400;
48+
get_content_area ().append (box);
49+
add_button (_("Cancel"), Gtk.ResponseType.CANCEL);
50+
51+
// TRANSLATORS: This string is used by screen reader
52+
update_property (Gtk.AccessibleProperty.LABEL, _("Select startup app"), -1);
53+
54+
search_entry.grab_focus ();
55+
search_entry.search_changed.connect (() => {
56+
list.invalidate_filter ();
57+
});
58+
59+
response.connect (hide);
60+
61+
list.row_activated.connect (on_app_selected);
62+
custom_entry.activate.connect (on_custom_command_entered);
63+
}
64+
65+
public void init_list (GLib.List<GLib.DesktopAppInfo> app_infos) {
66+
foreach (var app_info in app_infos) {
67+
var icon = app_info.get_icon () ?? new ThemedIcon ("application-default-icon");
68+
var name = app_info.get_name ();
69+
var filename = File.new_for_path (app_info.get_filename ()).get_basename ();
70+
71+
list.prepend (new AppChooserRow ({icon, name, app_info.get_description (), null, filename}));
72+
73+
var actions = app_info.list_actions ();
74+
for (var i = 0; i < actions.length; i++) {
75+
var action = actions[i];
76+
list.prepend (new AppChooserRow ({icon, name, app_info.get_action_name (action), action, filename}));
77+
}
78+
}
79+
}
80+
81+
private int sort_function (Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) {
82+
unowned AppChooserRow row_1 = (AppChooserRow) row1.get_child ();
83+
unowned AppChooserRow row_2 = (AppChooserRow) row2.get_child ();
84+
85+
var name_1 = row_1.info.name;
86+
var name_2 = row_2.info.name;
87+
88+
return name_1.collate (name_2);
89+
}
90+
91+
private bool filter_function (Gtk.ListBoxRow list_box_row) {
92+
var app_row = (AppChooserRow) list_box_row.get_child ();
93+
return search_entry.text.down () in app_row.info.name.down ()
94+
|| search_entry.text.down () in app_row.info.name.down ();
95+
}
96+
97+
private void on_app_selected (Gtk.ListBoxRow list_box_row) {
98+
var app_row = (AppChooserRow) list_box_row.get_child ();
99+
100+
var parameters = new GLib.HashTable<string, Variant> (null, null);
101+
if (app_row.info.action != null) {
102+
parameters["action"] = app_row.info.action;
103+
}
104+
105+
app_chosen (app_row.info.filename, parameters);
106+
hide ();
107+
}
108+
109+
private void on_custom_command_entered () {
110+
custom_command_chosen (
111+
custom_entry.text,
112+
new GLib.HashTable<string, Variant> (null, null)
113+
);
114+
hide ();
115+
}
116+
}

0 commit comments

Comments
 (0)