Skip to content

Commit

Permalink
Add context menu (#182)
Browse files Browse the repository at this point in the history
Co-authored-by: Danielle Foré <[email protected]>
  • Loading branch information
leolost2605 and danirabbit authored Nov 10, 2023
1 parent b5c18f6 commit 80335a7
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 19 deletions.
74 changes: 60 additions & 14 deletions src/Launcher.vala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public class Dock.Launcher : Gtk.Button {

private static Gtk.CssProvider css_provider;

private Gtk.PopoverMenu popover;

public Launcher (GLib.DesktopAppInfo app_info) {
Object (app_info: app_info);
}
Expand All @@ -28,6 +30,32 @@ public class Dock.Launcher : Gtk.Button {
windows = new GLib.List<AppWindow> ();
get_style_context ().add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);

var action_section = new Menu ();
foreach (var action in app_info.list_actions ()) {
action_section.append (
app_info.get_action_name (action),
MainWindow.ACTION_PREFIX + MainWindow.LAUNCHER_ACTION_TEMPLATE.printf (app_info.get_id (), action)
);
}

var pinned_section = new Menu ();
pinned_section.append (
_("Keep in Dock"),
MainWindow.ACTION_PREFIX + MainWindow.LAUNCHER_PINNED_ACTION_TEMPLATE.printf (app_info.get_id ())
);

var model = new Menu ();
if (action_section.get_n_items () > 0) {
model.append_section (null, action_section);
}
model.append_section (null, pinned_section);

popover = new Gtk.PopoverMenu.from_model (model) {
autohide = true,
position = TOP
};
popover.set_parent (this);

var image = new Gtk.Image () {
gicon = app_info.get_icon ()
};
Expand All @@ -36,33 +64,51 @@ public class Dock.Launcher : Gtk.Button {
child = image;
tooltip_text = app_info.get_display_name ();

clicked.connect (() => {
try {
add_css_class ("bounce");
notify["pinned"].connect (() => ((MainWindow) get_root ()).sync_pinned ());

var context = Gdk.Display.get_default ().get_app_launch_context ();
context.set_timestamp (Gdk.CURRENT_TIME);
var gesture_click = new Gtk.GestureClick () {
button = Gdk.BUTTON_SECONDARY
};
add_controller (gesture_click);
gesture_click.released.connect (popover.popup);

clicked.connect (() => launch ());
}

~Launcher () {
popover.unparent ();
popover.dispose ();
}

public void launch (string? action = null) {
try {
add_css_class ("bounce");

var context = Gdk.Display.get_default ().get_app_launch_context ();
context.set_timestamp (Gdk.CURRENT_TIME);

if (action != null) {
app_info.launch_action (action, context);
} else {
app_info.launch (null, context);
} catch (Error e) {
critical (e.message);
}
Timeout.add (400, () => {
remove_css_class ("bounce");
} catch (Error e) {
critical (e.message);
}

return Source.REMOVE;
});
Timeout.add (400, () => {
remove_css_class ("bounce");

return Source.REMOVE;
});
}

public void update_windows (owned GLib.List<AppWindow>? new_windows) {
if (new_windows == null) {
windows = new GLib.List<AppWindow> ();
return;
} else {
windows = (owned) new_windows;
}

windows = (owned) new_windows;
}

public AppWindow? find_window (uint64 window_uid) {
Expand Down
64 changes: 59 additions & 5 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
*/

public class Dock.MainWindow : Gtk.ApplicationWindow {
// First %s is the app id second %s the action name
public const string LAUNCHER_ACTION_TEMPLATE = "%s.%s";
// %s is the app id
public const string LAUNCHER_PINNED_ACTION_TEMPLATE = "%s-pinned";
public const string ACTION_GROUP_PREFIX = "win";
public const string ACTION_PREFIX = ACTION_GROUP_PREFIX + ".";

private static Gtk.CssProvider css_provider;

private Gtk.Box box;
Expand Down Expand Up @@ -67,6 +74,22 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
unowned var app_id = app_info.get_id ();
app_to_launcher.insert (app_id, launcher);
box.append (launcher);

var pinned_action = new SimpleAction.stateful (
LAUNCHER_PINNED_ACTION_TEMPLATE.printf (app_id),
null,
new Variant.boolean (launcher.pinned)
);
launcher.notify["pinned"].connect (() => pinned_action.set_state (launcher.pinned));
pinned_action.change_state.connect ((new_state) => launcher.pinned = (bool) new_state);
add_action (pinned_action);

foreach (var action in app_info.list_actions ()) {
var simple_action = new SimpleAction (LAUNCHER_ACTION_TEMPLATE.printf (app_id, action), null);
simple_action.activate.connect (() => launcher.launch (action));
add_action (simple_action);
}

return app_to_launcher[app_id];
}

Expand Down Expand Up @@ -110,14 +133,45 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
app_to_launcher.foreach_remove ((app_id, launcher) => {
var window_list = launcher_window_list.take (launcher);
launcher.update_windows ((owned) window_list);
if (launcher.windows.is_empty ()) {
if (!launcher.pinned) {
launcher.unparent ();
return true;
}
if (launcher.windows.is_empty () && !launcher.pinned) {
remove_launcher (launcher, false);
return true;
}

return false;
});
}

public void remove_launcher (Launcher launcher, bool from_map = true) {
foreach (var action in list_actions ()) {
if (action.has_prefix (launcher.app_info.get_id ())) {
remove_action (action);
}
}
box.remove (launcher);

if (from_map) {
app_to_launcher.remove (launcher.app_info.get_id ());
}
}

public void sync_pinned () {
string[] new_pinned_ids = {};

unowned Launcher child = (Launcher) box.get_first_child ();
while (child != null) {
unowned var current_child = child;
child = (Launcher) child.get_next_sibling ();

if (current_child.pinned) {
new_pinned_ids += current_child.app_info.get_id ();
} else if (!current_child.pinned && current_child.windows.is_empty ()) {
remove_launcher (current_child);
}
}


var settings = new Settings ("io.elementary.dock");
settings.set_strv ("launchers", new_pinned_ids);
}
}

0 comments on commit 80335a7

Please sign in to comment.