From 6a4868f8537451adbb8643c6cd07ad7ad66c414c Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Fri, 22 Nov 2024 18:25:51 +0100 Subject: [PATCH 1/4] Introduce an AppSystem --- src/App.vala | 23 +++-- src/AppSystem.vala | 157 ++++++++++++++++++++++++++++++++++ src/Application.vala | 2 +- src/DBus/ItemInterface.vala | 6 +- src/LauncherManager.vala | 165 +++--------------------------------- src/meson.build | 1 + 6 files changed, 191 insertions(+), 163 deletions(-) create mode 100644 src/AppSystem.vala diff --git a/src/App.vala b/src/App.vala index 27cb4da2..74deb7f6 100644 --- a/src/App.vala +++ b/src/App.vala @@ -21,6 +21,8 @@ public class Dock.App : Object { } } + public signal void removed (); + public bool pinned { get; construct set; } public GLib.DesktopAppInfo app_info { get; construct; } @@ -97,8 +99,6 @@ public class Dock.App : Object { } menu_model.append_section (null, pinned_section); - var launcher_manager = LauncherManager.get_default (); - pinned_action = new SimpleAction.stateful (PINNED_ACTION, null, new Variant.boolean (pinned)); pinned_action.change_state.connect ((new_state) => pinned = (bool) new_state); action_group.add_action (pinned_action); @@ -118,6 +118,7 @@ public class Dock.App : Object { notify["pinned"].connect (() => { pinned_action.set_state (pinned); + check_remove (); LauncherManager.get_default ().sync_pinned (); }); } @@ -137,9 +138,9 @@ public class Dock.App : Object { } else if (windows.size == 0) { app_info.launch (null, context); } else if (windows.size == 1) { - LauncherManager.get_default ().desktop_integration.focus_window.begin (windows.first ().uid); - } else if (LauncherManager.get_default ().desktop_integration != null) { - LauncherManager.get_default ().desktop_integration.show_windows_for.begin (app_info.get_id ()); + AppSystem.get_default ().desktop_integration.focus_window.begin (windows.first ().uid); + } else if (AppSystem.get_default ().desktop_integration != null) { + AppSystem.get_default ().desktop_integration.show_windows_for.begin (app_info.get_id ()); } } catch (Error e) { critical (e.message); @@ -177,6 +178,12 @@ public class Dock.App : Object { return false; } + private void check_remove () { + if (!pinned && !running) { + removed (); + } + } + public void update_windows (Gee.List? new_windows) { if (new_windows == null) { windows = new Gee.LinkedList (); @@ -190,6 +197,8 @@ public class Dock.App : Object { if (launching && running) { launching = false; } + + check_remove (); } public AppWindow? find_window (uint64 window_uid) { @@ -255,7 +264,7 @@ public class Dock.App : Object { return; } - LauncherManager.get_default ().desktop_integration.focus_window.begin (current_windows[current_index].uid); + AppSystem.get_default ().desktop_integration.focus_window.begin (current_windows[current_index].uid); // Throttle the scroll for performance and better visibility of the windows Timeout.add (250, () => { @@ -270,7 +279,7 @@ public class Dock.App : Object { if (timer_id != 0) { Source.remove (timer_id); } else { - yield LauncherManager.get_default ().sync_windows (); // Get the current stacking order + yield AppSystem.get_default ().sync_windows (); // Get the current stacking order current_index = windows.size > 1 && windows.first ().has_focus ? 1 : 0; current_windows = {}; foreach (AppWindow window in windows) { diff --git a/src/AppSystem.vala b/src/AppSystem.vala new file mode 100644 index 00000000..fa8967b6 --- /dev/null +++ b/src/AppSystem.vala @@ -0,0 +1,157 @@ + +public class Dock.AppSystem : Object, UnityClient { + private static Settings settings; + private static GLib.Once instance; + + static construct { + settings = new Settings ("io.elementary.dock"); + } + + public static unowned AppSystem get_default () { + return instance.once (() => { return new AppSystem (); }); + } + + public signal void app_added (App app); + + public DesktopIntegration? desktop_integration { get; private set; } + + private GLib.HashTable id_to_app; + + private AppSystem () { } + + construct { + id_to_app = new HashTable (str_hash, str_equal); + } + + public async void load () { + foreach (string app_id in settings.get_strv ("launchers")) { + var app_info = new GLib.DesktopAppInfo (app_id); + add_app (app_info, true); + } + + try { + desktop_integration = yield GLib.Bus.get_proxy ( + SESSION, + "org.pantheon.gala", + "/org/pantheon/gala/DesktopInterface" + ); + + yield sync_windows (); + + desktop_integration.windows_changed.connect (sync_windows); + } catch (Error e) { + critical ("Failed to get desktop integration: %s", e.message); + } + } + + private App add_app (DesktopAppInfo app_info, bool pinned) { + var app = new App (app_info, pinned); + id_to_app[app_info.get_id ()] = app; + app.removed.connect ((_app) => id_to_app.remove (_app.app_info.get_id ())); + app_added (app); + return app; + } + + public async void sync_windows () requires (desktop_integration != null) { + DesktopIntegration.Window[] windows; + try { + windows = yield desktop_integration.get_windows (); + } catch (Error e) { + critical (e.message); + return; + } + + var app_window_list = new Gee.HashMap> (); + foreach (unowned var window in windows) { + unowned var app_id = window.properties["app-id"].get_string (); + App? app = id_to_app[app_id]; + if (app == null) { + var app_info = new GLib.DesktopAppInfo (app_id); + if (app_info == null) { + continue; + } + + app = add_app (app_info, false); + } + + AppWindow? app_window = app.find_window (window.uid); + if (app_window == null) { + app_window = new AppWindow (window.uid); + } + + app_window.update_properties (window.properties); + + var window_list = app_window_list.get (app); + if (window_list == null) { + var new_window_list = new Gee.LinkedList (); + new_window_list.add (app_window); + app_window_list.set (app, new_window_list); + } else { + window_list.add (app_window); + } + } + + foreach (var app in id_to_app.get_values ()) { + Gee.List? window_list = null; + app_window_list.unset (app, out window_list); + app.update_windows (window_list); + } + } + + public void add_app_for_id (string app_id) { + if (app_id in id_to_app) { + id_to_app[app_id].pinned = true; + return; + } + + var app_info = new DesktopAppInfo (app_id); + + if (app_info == null) { + warning ("App not found: %s", app_id); + return; + } + + add_app (app_info, true); + } + + public void remove_app_by_id (string app_id) { + if (app_id in id_to_app) { + id_to_app[app_id].pinned = false; + } + } + + public string[] list_launchers () { + return settings.get_strv ("launchers"); + } + + private void update_launcher_entry (string sender_name, GLib.Variant parameters, bool is_retry = false) { + if (!is_retry) { + // Wait to let further update requests come in to catch the case where one application + // sends out multiple LauncherEntry-updates with different application-uris, e.g. Nautilus + Idle.add (() => { + update_launcher_entry (sender_name, parameters, true); + return false; + }); + + return; + } + + string app_uri; + VariantIter prop_iter; + parameters.get ("(sa{sv})", out app_uri, out prop_iter); + + var app_id = app_uri.replace ("application://", ""); + if (id_to_app[app_id] != null) { + id_to_app[app_id].perform_unity_update (prop_iter); + } else { + critical ("unable to update missing launcher: %s", app_id); + } + } + + private void remove_launcher_entry (string sender_name) { + var app_id = sender_name + ".desktop"; + if (id_to_app[app_id] != null) { + id_to_app[app_id].remove_launcher_entry (); + } + } +} diff --git a/src/Application.vala b/src/Application.vala index 80171fa5..ef913fb3 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -31,7 +31,7 @@ public class Dock.Application : Gtk.Application { add_window (main_window); unowned var unity_client = Unity.get_default (); - unity_client.add_client (LauncherManager.get_default ()); + unity_client.add_client (AppSystem.get_default ()); } active_window.present (); diff --git a/src/DBus/ItemInterface.vala b/src/DBus/ItemInterface.vala index fefed2ed..6e5f431c 100644 --- a/src/DBus/ItemInterface.vala +++ b/src/DBus/ItemInterface.vala @@ -6,14 +6,14 @@ [DBus (name = "io.elementary.dock.items")] public class Dock.ItemInterface : Object { public void add_launcher (string app_id) throws DBusError, IOError { - LauncherManager.get_default ().add_launcher_for_id (app_id); + AppSystem.get_default ().add_app_for_id (app_id); } public void remove_launcher (string app_id) throws DBusError, IOError { - LauncherManager.get_default ().remove_launcher_by_id (app_id); + AppSystem.get_default ().remove_app_by_id (app_id); } public string[] list_launchers () throws DBusError, IOError { - return LauncherManager.get_default ().list_launchers (); + return AppSystem.get_default ().list_launchers (); } } diff --git a/src/LauncherManager.vala b/src/LauncherManager.vala index 48303243..7ce24c7c 100644 --- a/src/LauncherManager.vala +++ b/src/LauncherManager.vala @@ -3,7 +3,7 @@ * SPDX-FileCopyrightText: 2023 elementary, Inc. (https://elementary.io) */ - public class Dock.LauncherManager : Gtk.Fixed, UnityClient { + public class Dock.LauncherManager : Gtk.Fixed { private static Settings settings; private static GLib.Once instance; @@ -12,11 +12,9 @@ } public Launcher? added_launcher { get; set; default = null; } - public Dock.DesktopIntegration? desktop_integration { get; private set; } private Adw.TimedAnimation resize_animation; private List launchers; //Only used to keep track of launcher indices - private GLib.HashTable id_to_app; static construct { settings = new Settings ("io.elementary.dock"); @@ -24,7 +22,6 @@ construct { launchers = new List (); - id_to_app = new GLib.HashTable (str_hash, str_equal); overflow = VISIBLE; @@ -75,14 +72,14 @@ return; } - if (app_info.get_id () in id_to_app) { - id_to_app[app_info.get_id ()].pinned = true; - drop_target_file.reject (); - return; - } + // if (app_info.get_id () in id_to_app) { + // id_to_app[app_info.get_id ()].pinned = true; + // drop_target_file.reject (); + // return; + // } var position = (int) Math.round (drop_x / get_launcher_size ()); - added_launcher = add_launcher (new DesktopAppInfo.from_filename (file.get_path ()), true, true, position); + // added_launcher = add_launcher (new DesktopAppInfo.from_filename (file.get_path ()), true, true, position); added_launcher.moving = true; }); @@ -97,30 +94,9 @@ } }); - Idle.add (() => { - foreach (string app_id in settings.get_strv ("launchers")) { - var app_info = new GLib.DesktopAppInfo (app_id); - add_launcher (app_info, true, false); - } - reposition_launchers (); - - GLib.Bus.get_proxy.begin ( - GLib.BusType.SESSION, - "org.pantheon.gala", - "/org/pantheon/gala/DesktopInterface", - GLib.DBusProxyFlags.NONE, - null, - (obj, res) => { - try { - desktop_integration = GLib.Bus.get_proxy.end (res); - desktop_integration.windows_changed.connect (sync_windows); - - sync_windows.begin (); - } catch (GLib.Error e) { - critical (e.message); - } - }); - }); + AppSystem.get_default ().app_added.connect ((app) => add_launcher (app, true)); + + map.connect (AppSystem.get_default ().load); } private void reposition_launchers () { @@ -145,12 +121,11 @@ return settings.get_int ("icon-size") + Launcher.PADDING * 2; } - private Launcher add_launcher (GLib.DesktopAppInfo app_info, bool pinned = false, bool reposition = true, int index = -1) { - var app = new App (app_info, pinned); + private Launcher add_launcher (App app, bool reposition = true, int index = -1) { var launcher = new Launcher (app); - unowned var app_id = app_info.get_id (); - id_to_app.insert (app_id, app); + app.removed.connect (() => remove_launcher (launcher, true)); + if (index >= 0) { launchers.insert (launcher, index); } else { @@ -177,7 +152,6 @@ public void remove_launcher (Launcher launcher, bool animate = true) { launchers.remove (launcher); - id_to_app.remove (launcher.app.app_info.get_id ()); if (animate) { launcher.set_revealed (false); @@ -202,85 +176,6 @@ launcher.cleanup (); } - private void update_launcher_entry (string sender_name, GLib.Variant parameters, bool is_retry = false) { - if (!is_retry) { - // Wait to let further update requests come in to catch the case where one application - // sends out multiple LauncherEntry-updates with different application-uris, e.g. Nautilus - Idle.add (() => { - update_launcher_entry (sender_name, parameters, true); - return false; - }); - - return; - } - - string app_uri; - VariantIter prop_iter; - parameters.get ("(sa{sv})", out app_uri, out prop_iter); - - var app_id = app_uri.replace ("application://", ""); - if (id_to_app[app_id] != null) { - id_to_app[app_id].perform_unity_update (prop_iter); - } else { - critical ("unable to update missing launcher: %s", app_id); - } - } - - private void remove_launcher_entry (string sender_name) { - var app_id = sender_name + ".desktop"; - if (id_to_app[app_id] != null) { - id_to_app[app_id].remove_launcher_entry (); - } - } - - public async void sync_windows () requires (desktop_integration != null) { - DesktopIntegration.Window[] windows; - try { - windows = yield desktop_integration.get_windows (); - } catch (Error e) { - critical (e.message); - return; - } - - var app_window_list = new Gee.HashMap> (); - foreach (unowned var window in windows) { - unowned var app_id = window.properties["app-id"].get_string (); - App? app = id_to_app[app_id]; - if (app == null) { - var app_info = new GLib.DesktopAppInfo (app_id); - if (app_info == null) { - continue; - } - - app = add_launcher (app_info).app; - } - - AppWindow? app_window = app.find_window (window.uid); - if (app_window == null) { - app_window = new AppWindow (window.uid); - } - - app_window.update_properties (window.properties); - - var window_list = app_window_list.get (app); - if (window_list == null) { - var new_window_list = new Gee.LinkedList (); - new_window_list.add (app_window); - app_window_list.set (app, new_window_list); - } else { - window_list.add (app_window); - } - } - - foreach (var app in id_to_app.get_values ()) { - Gee.List? window_list = null; - app_window_list.unset (app, out window_list); - app.update_windows (window_list); - } - - sync_pinned (); - } - public void move_launcher_after (Launcher source, int target_index) { int source_index = launchers.index (source); @@ -305,21 +200,13 @@ public void sync_pinned () { string[] new_pinned_ids = {}; - Launcher[] launchers_to_remove = {}; foreach (var launcher in launchers) { if (launcher.app.pinned) { new_pinned_ids += launcher.app.app_info.get_id (); - } else if (!launcher.app.pinned && launcher.app.windows.is_empty) { - launchers_to_remove += launcher; } } - foreach (var launcher in launchers_to_remove) { - remove_launcher (launcher); - } - - var settings = new Settings ("io.elementary.dock"); settings.set_strv ("launchers", new_pinned_ids); } @@ -331,30 +218,4 @@ var context = Gdk.Display.get_default ().get_app_launch_context (); launchers.nth (index - 1).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; - return; - } - - var app_info = new DesktopAppInfo (app_id); - - if (app_info == null) { - warning ("App not found: %s", app_id); - return; - } - - add_launcher (app_info).app.pinned = true; - } - - public void remove_launcher_by_id (string app_id) { - if (app_id in id_to_app) { - id_to_app[app_id].pinned = false; - } - } - - public string[] list_launchers () { - return settings.get_strv ("launchers"); - } } diff --git a/src/meson.build b/src/meson.build index 30e3413d..6d3d076f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,6 @@ sources = [ 'App.vala', + 'AppSystem.vala', 'Application.vala', 'AppWindow.vala', 'DesktopIntegration.vala', From 6a77ae14379b4ac7a21fc4171da6cc7bf6aa1e47 Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Sat, 23 Nov 2024 12:45:03 +0100 Subject: [PATCH 2/4] Cleanup --- src/AppSystem.vala | 4 ++++ src/LauncherManager.vala | 43 ++++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/AppSystem.vala b/src/AppSystem.vala index fa8967b6..dca9f856 100644 --- a/src/AppSystem.vala +++ b/src/AppSystem.vala @@ -23,6 +23,10 @@ public class Dock.AppSystem : Object, UnityClient { id_to_app = new HashTable (str_hash, str_equal); } + public App? get_app (string id) { + return id_to_app[id]; + } + public async void load () { foreach (string app_id in settings.get_strv ("launchers")) { var app_info = new GLib.DesktopAppInfo (app_id); diff --git a/src/LauncherManager.vala b/src/LauncherManager.vala index 7ce24c7c..2a5576e8 100644 --- a/src/LauncherManager.vala +++ b/src/LauncherManager.vala @@ -72,14 +72,17 @@ return; } - // if (app_info.get_id () in id_to_app) { - // id_to_app[app_info.get_id ()].pinned = true; - // drop_target_file.reject (); - // return; - // } + var app_system = AppSystem.get_default (); + + var app = app_system.get_app (app_info.get_id ()); + if (app != null) { + app.pinned = true; + drop_target_file.reject (); + return; + } var position = (int) Math.round (drop_x / get_launcher_size ()); - // added_launcher = add_launcher (new DesktopAppInfo.from_filename (file.get_path ()), true, true, position); + // added_launcher = add_launcher (new DesktopAppInfo.from_filename (file.get_path ()), true, position); added_launcher.moving = true; }); @@ -94,7 +97,7 @@ } }); - AppSystem.get_default ().app_added.connect ((app) => add_launcher (app, true)); + AppSystem.get_default ().app_added.connect ((app) => add_launcher (app)); map.connect (AppSystem.get_default ().load); } @@ -121,7 +124,7 @@ return settings.get_int ("icon-size") + Launcher.PADDING * 2; } - private Launcher add_launcher (App app, bool reposition = true, int index = -1) { + private Launcher add_launcher (App app, int index = -1) { var launcher = new Launcher (app); app.removed.connect (() => remove_launcher (launcher, true)); @@ -132,20 +135,18 @@ launchers.append (launcher); } - if (reposition) { - resize_animation.easing = EASE_OUT_BACK; - resize_animation.duration = Granite.TRANSITION_DURATION_OPEN; - resize_animation.value_from = get_width (); - resize_animation.value_to = launchers.length () * get_launcher_size (); - resize_animation.play (); + resize_animation.easing = EASE_OUT_BACK; + resize_animation.duration = Granite.TRANSITION_DURATION_OPEN; + resize_animation.value_from = get_width (); + resize_animation.value_to = launchers.length () * get_launcher_size (); + resize_animation.play (); - ulong reveal_cb = 0; - reveal_cb = resize_animation.done.connect (() => { - reposition_launchers (); - launcher.set_revealed (true); - resize_animation.disconnect (reveal_cb); - }); - } + ulong reveal_cb = 0; + reveal_cb = resize_animation.done.connect (() => { + reposition_launchers (); + launcher.set_revealed (true); + resize_animation.disconnect (reveal_cb); + }); return launcher; } From 7d32f82427844f50b715e8e2f6f72931e631d5b0 Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Wed, 11 Dec 2024 15:22:17 +0100 Subject: [PATCH 3/4] Dnd remove via app pinned --- src/Launcher.vala | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Launcher.vala b/src/Launcher.vala index c2798948..27468990 100644 --- a/src/Launcher.vala +++ b/src/Launcher.vala @@ -71,6 +71,8 @@ public class Dock.Launcher : Gtk.Box { private int drag_offset_x = 0; private int drag_offset_y = 0; + private bool flagged_for_removal = false; + public Launcher (App app) { Object (app: app); } @@ -208,7 +210,11 @@ public class Dock.Launcher : Gtk.Box { drag_source.prepare.connect (on_drag_prepare); drag_source.drag_begin.connect (on_drag_begin); drag_source.drag_cancel.connect (on_drag_cancel); - drag_source.drag_end.connect (() => moving = false); + drag_source.drag_end.connect (() => { + if (!flagged_for_removal) { + moving = false; + } + }); var drop_target = new Gtk.DropTarget (typeof (Launcher), MOVE) { preload = true @@ -435,7 +441,8 @@ public class Dock.Launcher : Gtk.Box { popover.popup (); popover.start_animation (); - LauncherManager.get_default ().remove_launcher (this, false); + app.pinned = false; + flagged_for_removal = true; return true; } else { From 9f68a622258b71d1a48fe67f8cbcbc65a2f3a8f8 Mon Sep 17 00:00:00 2001 From: Leonhard Kargl Date: Wed, 11 Dec 2024 15:33:24 +0100 Subject: [PATCH 4/4] Implement DND support --- src/AppSystem.vala | 4 +++ src/Launcher.vala | 2 ++ src/LauncherManager.vala | 53 ++++++++++++++++++++++------------------ 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/AppSystem.vala b/src/AppSystem.vala index dca9f856..d1895fa3 100644 --- a/src/AppSystem.vala +++ b/src/AppSystem.vala @@ -1,3 +1,7 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io) + */ public class Dock.AppSystem : Object, UnityClient { private static Settings settings; diff --git a/src/Launcher.vala b/src/Launcher.vala index 27468990..3adda528 100644 --- a/src/Launcher.vala +++ b/src/Launcher.vala @@ -15,6 +15,7 @@ public class Dock.Launcher : Gtk.Box { } } + public signal void removed (); public signal void revealed_done (); // Matches icon size and padding in Launcher.css @@ -151,6 +152,7 @@ public class Dock.Launcher : Gtk.Box { }); app.launched.connect (animate_launch); + app.removed.connect (() => removed ()); var bounce_animation_target = new Adw.CallbackAnimationTarget ((val) => { var height = overlay.get_height (); diff --git a/src/LauncherManager.vala b/src/LauncherManager.vala index 2a5576e8..6b521cea 100644 --- a/src/LauncherManager.vala +++ b/src/LauncherManager.vala @@ -81,23 +81,32 @@ return; } - var position = (int) Math.round (drop_x / get_launcher_size ()); - // added_launcher = add_launcher (new DesktopAppInfo.from_filename (file.get_path ()), true, position); - added_launcher.moving = true; + app_system.add_app_for_id (app_info.get_id ()); }); drop_target_file.leave.connect (() => { if (added_launcher != null) { //Without idle it crashes when the cursor is above the launcher Idle.add (() => { - remove_launcher (added_launcher); + added_launcher.app.pinned = false; added_launcher = null; return Source.REMOVE; }); } }); - AppSystem.get_default ().app_added.connect ((app) => add_launcher (app)); + AppSystem.get_default ().app_added.connect ((app) => { + var launcher = new Launcher (app); + + int position = -1; + if (drop_target_file.get_value () != null && added_launcher == null) { // The launcher is being added via dnd from wingpanel + position = (int) Math.round (drop_x / get_launcher_size ()); + added_launcher = launcher; + launcher.moving = true; + } + + add_launcher (launcher, position); + }); map.connect (AppSystem.get_default ().load); } @@ -120,21 +129,19 @@ } } - public static int get_launcher_size () { - return settings.get_int ("icon-size") + Launcher.PADDING * 2; - } - - private Launcher add_launcher (App app, int index = -1) { - var launcher = new Launcher (app); - - app.removed.connect (() => remove_launcher (launcher, true)); + private void add_launcher (Launcher launcher, int index = -1) { + launcher.removed.connect (remove_launcher); if (index >= 0) { + // If the index is > 0 the resize is done by the reposition so we return early launchers.insert (launcher, index); - } else { - launchers.append (launcher); + reposition_launchers (); + launcher.set_revealed (true); + return; } + launchers.append (launcher); + resize_animation.easing = EASE_OUT_BACK; resize_animation.duration = Granite.TRANSITION_DURATION_OPEN; resize_animation.value_from = get_width (); @@ -147,19 +154,13 @@ launcher.set_revealed (true); resize_animation.disconnect (reveal_cb); }); - - return launcher; } - public void remove_launcher (Launcher launcher, bool animate = true) { + private void remove_launcher (Launcher launcher) { launchers.remove (launcher); - if (animate) { - launcher.set_revealed (false); - launcher.revealed_done.connect (remove_finish); - } else { - remove_finish (launcher); - } + launcher.set_revealed (false); + launcher.revealed_done.connect (remove_finish); } private void remove_finish (Launcher launcher) { @@ -219,4 +220,8 @@ var context = Gdk.Display.get_default ().get_app_launch_context (); launchers.nth (index - 1).data.app.launch (context); } + + public static int get_launcher_size () { + return settings.get_int ("icon-size") + Launcher.PADDING * 2; + } }