Skip to content

Commit 95c387e

Browse files
committed
Implement background app monitoring
1 parent 8cb6d15 commit 95c387e

File tree

10 files changed

+410
-1
lines changed

10 files changed

+410
-1
lines changed

data/background.svg

Lines changed: 176 additions & 0 deletions
Loading

data/dock.gresource.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<gresources>
33
<gresource prefix="/io/elementary/dock">
44
<file compressed="true">Application.css</file>
5+
<file compressed="true">background.svg</file>
56
<file compressed="true">poof.svg</file>
67
</gresource>
78
</gresources>

src/AppSystem/AppSystem.vala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@ public class Dock.AppSystem : Object, UnityClient {
1717

1818
public signal void app_added (App app);
1919

20+
public BackgroundMonitor background_monitor { get; construct; }
21+
2022
private GLib.HashTable<unowned string, App> id_to_app;
2123

2224
private AppSystem () { }
2325

2426
construct {
27+
background_monitor = new BackgroundMonitor ();
2528
id_to_app = new HashTable<unowned string, App> (str_hash, str_equal);
2629
}
2730

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0
3+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
4+
*
5+
* Authored by: Leonhard Kargl <[email protected]>
6+
*/
7+
8+
public class Dock.BackgroundApp : Object {
9+
public DesktopAppInfo app_info { get; construct; }
10+
public string? instance { get; construct; }
11+
public string? message { get; construct; }
12+
13+
public BackgroundApp (DesktopAppInfo app_info, string? instance, string? message) {
14+
Object (app_info: app_info, instance: instance, message: message);
15+
}
16+
17+
public void kill () {
18+
if (instance == null) {
19+
warning ("No instance to kill");
20+
return;
21+
}
22+
23+
try {
24+
var app_id = app_info.get_id ().replace (".desktop", "");
25+
Process.spawn_command_line_async ("flatpak kill %s".printf (app_id));
26+
} catch (Error e) {
27+
warning ("Failed to kill instance: %s", e.message);
28+
}
29+
}
30+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0
3+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
4+
*
5+
* Authored by: Leonhard Kargl <[email protected]>
6+
*/
7+
8+
public class Dock.BackgroundAppRow : Gtk.ListBoxRow {
9+
public BackgroundApp app { get; construct; }
10+
11+
public BackgroundAppRow (BackgroundApp app) {
12+
Object (app: app);
13+
}
14+
15+
construct {
16+
var icon = new Gtk.Image.from_gicon (app.app_info.get_icon ()) {
17+
icon_size = LARGE
18+
};
19+
20+
var name = new Gtk.Label (app.app_info.get_display_name ()) {
21+
xalign = 0,
22+
hexpand = true
23+
};
24+
25+
var message = new Gtk.Label (app.message) {
26+
xalign = 0,
27+
hexpand = true
28+
};
29+
message.add_css_class (Granite.STYLE_CLASS_DIM_LABEL);
30+
31+
var button = new Gtk.Button.from_icon_name ("window-close-symbolic") {
32+
valign = CENTER,
33+
halign = CENTER
34+
};
35+
button.add_css_class ("circular");
36+
37+
var spinner = new Gtk.Spinner () {
38+
spinning = true
39+
};
40+
41+
var button_stack = new Gtk.Stack () {
42+
transition_type = CROSSFADE
43+
};
44+
button_stack.add_named (button, "button");
45+
button_stack.add_named (spinner, "spinner");
46+
47+
var grid = new Gtk.Grid () {
48+
column_spacing = 9,
49+
row_spacing = 3,
50+
margin_top = 3,
51+
margin_bottom = 3,
52+
margin_start = 3,
53+
margin_end = 3
54+
};
55+
grid.attach (icon, 0, 0, 1, 2);
56+
57+
if (app.message != null) {
58+
grid.attach (name, 1, 0, 1, 1);
59+
grid.attach (message, 1, 1, 1, 1);
60+
} else {
61+
grid.attach (name, 1, 0, 1, 2);
62+
}
63+
64+
grid.attach (button_stack, 2, 0, 1, 2);
65+
66+
focusable = false;
67+
child = grid;
68+
69+
button.clicked.connect (() => {
70+
button_stack.set_visible_child_name ("spinner");
71+
app.kill ();
72+
73+
Timeout.add_seconds (5, () => {
74+
// Assume killing failed
75+
button_stack.set_visible_child_name ("button");
76+
return Source.REMOVE;
77+
});
78+
});
79+
}
80+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0
3+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
4+
*
5+
* Authored by: Leonhard Kargl <[email protected]>
6+
*/
7+
8+
public class Dock.BackgroundItem : BaseItem {
9+
private BackgroundMonitor monitor;
10+
11+
private Gtk.Popover popover;
12+
13+
construct {
14+
monitor = new BackgroundMonitor ();
15+
16+
var list_box = new Gtk.ListBox () {
17+
selection_mode = NONE,
18+
margin_bottom = 3,
19+
margin_top = 3,
20+
};
21+
list_box.bind_model (monitor.background_apps, create_widget_func);
22+
list_box.set_placeholder (new Gtk.Label (_("No apps are running in the background")));
23+
24+
popover = new Gtk.Popover () {
25+
position = TOP,
26+
child = list_box
27+
};
28+
popover.set_parent (this);
29+
30+
var image = new Gtk.Image.from_resource ("/io/elementary/dock/background.svg");
31+
bind_property ("icon-size", image, "pixel-size", SYNC_CREATE);
32+
33+
overlay.child = image;
34+
35+
gesture_click.released.connect (popover.popup);
36+
}
37+
38+
private Gtk.Widget create_widget_func (Object obj) {
39+
var app = (BackgroundApp) obj;
40+
return new BackgroundAppRow (app);
41+
}
42+
}

0 commit comments

Comments
 (0)