Skip to content

Commit 234c28c

Browse files
committed
WIP: desktop: enable app icons in dock, alt-tab, etc.
Signed-off-by: Kajus Naujokaitis <kajus.naujokaitis@unikie.com>
1 parent 92fa532 commit 234c28c

File tree

18 files changed

+285
-218
lines changed

18 files changed

+285
-218
lines changed

lib/default.nix

Lines changed: 95 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,51 +56,127 @@ in
5656

5757
types = prev.types // {
5858
networking = lib.types.submodule {
59+
# keep-sorted start skip_lines=1 block=yes newline_separated=yes
5960
options = {
60-
name = lib.mkOption {
61-
type = lib.types.nullOr lib.types.str;
62-
description = "Host name as string.";
61+
cid = lib.mkOption {
62+
type = lib.types.nullOr lib.types.int;
6363
default = null;
64+
description = ''
65+
Vsock CID (Context IDentifier) as integer:
66+
- VMADDR_CID_HYPERVISOR (0) is reserved for services built into the hypervisor
67+
- VMADDR_CID_LOCAL (1) is the well-known address for local communication (loopback)
68+
- VMADDR_CID_HOST (2) is the well-known address of the host
69+
'';
6470
};
65-
mac = lib.mkOption {
71+
72+
interfaceName = lib.mkOption {
6673
type = lib.types.nullOr lib.types.str;
67-
description = "MAC address as string.";
6874
default = null;
75+
description = "Name of the network interface.";
6976
};
77+
7078
ipv4 = lib.mkOption {
7179
type = lib.types.nullOr lib.types.str;
7280
description = "IPv4 address as string.";
7381
default = null;
7482
};
75-
ipv6 = lib.mkOption {
76-
type = lib.types.nullOr lib.types.str;
77-
description = "IPv6 address as string.";
78-
default = null;
79-
};
83+
8084
ipv4SubnetPrefixLength = lib.mkOption {
8185
type = lib.types.nullOr lib.types.int;
8286
default = null;
8387
description = "The IPv4 subnet prefix length (e.g. 24 for 255.255.255.0)";
8488
example = 24;
8589
};
86-
interfaceName = lib.mkOption {
90+
91+
ipv6 = lib.mkOption {
8792
type = lib.types.nullOr lib.types.str;
93+
description = "IPv6 address as string.";
8894
default = null;
89-
description = "Name of the network interface.";
9095
};
91-
cid = lib.mkOption {
92-
type = lib.types.nullOr lib.types.int;
96+
97+
mac = lib.mkOption {
98+
type = lib.types.nullOr lib.types.str;
99+
description = "MAC address as string.";
93100
default = null;
101+
};
102+
103+
name = lib.mkOption {
104+
type = lib.types.nullOr lib.types.str;
105+
description = "Host name as string.";
106+
default = null;
107+
};
108+
109+
};
110+
# keep-sorted end
111+
};
112+
113+
ghafApplication = lib.types.submodule {
114+
# keep-sorted start skip_lines=1 block=yes
115+
options = {
116+
categories = lib.mkOption {
117+
description = "The `Categories` of the desktop entry; see https://specifications.freedesktop.org/menu-spec/1.0/category-registry.html for possible values";
118+
type = lib.types.listOf lib.types.str;
119+
default = [ ];
120+
};
121+
description = lib.mkOption {
122+
type = lib.types.str;
123+
description = "The `Comment` of the desktop entry";
124+
};
125+
desktopName = lib.mkOption {
126+
type = lib.types.str;
127+
description = "The `Name` of the desktop entry";
128+
default = "";
129+
};
130+
exec = lib.mkOption {
131+
type = lib.types.nullOr lib.types.str;
94132
description = ''
95-
Vsock CID (Context IDentifier) as integer:
96-
- VMADDR_CID_HYPERVISOR (0) is reserved for services built into the hypervisor
97-
- VMADDR_CID_LOCAL (1) is the well-known address for local communication (loopback)
98-
- VMADDR_CID_HOST (2) is the well-known address of the host
133+
The `Exec` of the desktop entry.
134+
If `vm` is set, this command will be executed in the target VM.
99135
'';
136+
default = null;
137+
};
138+
extraModules = lib.mkOption {
139+
type = lib.types.listOf lib.types.attrs;
140+
description = "Additional modules required for the application";
141+
default = [ ];
142+
};
143+
genericName = lib.mkOption {
144+
type = lib.types.nullOr lib.types.str;
145+
description = "The `GenericName` of the desktop entry";
146+
default = null;
147+
};
148+
givcArgs = lib.mkOption {
149+
description = "GIVC arguments for the application";
150+
type = lib.types.listOf lib.types.str;
151+
default = [ ];
152+
};
153+
icon = lib.mkOption {
154+
type = lib.types.nullOr lib.types.str;
155+
description = "The `Icon` of the desktop entry";
156+
default = null;
157+
};
158+
name = lib.mkOption {
159+
type = lib.types.str;
160+
description = "The name of the desktop file (excluding the .desktop or .directory file extensions)";
161+
};
162+
packages = lib.mkOption {
163+
type = lib.types.listOf lib.types.package;
164+
description = "Packages required for this application";
165+
default = [ ];
166+
};
167+
startupWMClass = lib.mkOption {
168+
type = lib.types.nullOr lib.types.str;
169+
description = "The `StartupWMClass` of the desktop entry";
170+
default = null;
171+
};
172+
vm = lib.mkOption {
173+
description = "VM name in case this launches an isolated application.";
174+
type = lib.types.nullOr lib.types.str;
175+
default = null;
100176
};
101177
};
178+
# keep-sorted end
102179
};
103-
104180
};
105181

106182
# Launcher utilities

modules/desktop/graphics/cosmic/default.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ in
291291
adwaita-icon-theme
292292
ghaf-wallpapers
293293
grim # promptless screenshot for test automation
294-
(import ../launchers-pkg.nix { inherit pkgs config; })
294+
(import ../launchers-pkg.nix { inherit pkgs config lib; })
295295
]
296296
++ [ (lib.hiPrio ghaf-cosmic-config) ];
297297
sessionVariables = {

modules/desktop/graphics/launchers-pkg.nix

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
# SPDX-FileCopyrightText: 2022-2026 TII (SSRC) and the Ghaf contributors
22
# SPDX-License-Identifier: Apache-2.0
3-
{ pkgs, config, ... }:
3+
{
4+
pkgs,
5+
config,
6+
lib,
7+
...
8+
}:
49
let
510
toDesktop =
611
launcherElem:
712
let
813
prefix = if launcherElem.vm != null then "[${launcherElem.vm}] " else "";
9-
icon = if launcherElem.icon != null then launcherElem.icon else launcherElem.name;
14+
icon =
15+
if launcherElem.icon != null then
16+
launcherElem.icon
17+
else
18+
(lib.strings.toLower (lib.replaceStrings [ " " ] [ "-" ] launcherElem.desktopName));
19+
20+
startupWMClass = launcherElem.startupWMClass or launcherElem.name;
1021

1122
extraCheckPhase =
1223
if builtins.isPath icon then
@@ -19,11 +30,13 @@ let
1930
in
2031
(pkgs.makeDesktopItem {
2132
inherit (launcherElem) name;
22-
genericName = launcherElem.name;
23-
desktopName = launcherElem.name;
33+
inherit (launcherElem) desktopName;
34+
inherit (launcherElem) genericName;
35+
inherit (launcherElem) categories;
36+
inherit (launcherElem) exec;
2437
inherit icon;
38+
inherit startupWMClass;
2539
comment = "${prefix}${launcherElem.description}";
26-
exec = launcherElem.execPath;
2740
}).overrideAttrs
2841
(prevAttrs: {
2942
checkPhase = prevAttrs.checkPhase + extraCheckPhase;

modules/desktop/graphics/launchers.nix

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,14 @@
55
let
66
inherit (lib)
77
mkOption
8-
types
98
;
109
in
1110
{
1211
options.ghaf.graphics = {
1312
launchers = mkOption {
1413
description = "Application launchers to show in the system drawer or launcher.";
14+
type = lib.types.listOf lib.types.ghafApplication;
1515
default = [ ];
16-
type = types.listOf (
17-
types.submodule {
18-
options = {
19-
name = mkOption {
20-
description = "Name of the application";
21-
type = types.str;
22-
};
23-
description = mkOption {
24-
description = "Description of the application";
25-
type = types.str;
26-
default = "Secured Ghaf Application";
27-
};
28-
vm = mkOption {
29-
description = "VM name in case this launches an isolated application.";
30-
type = types.nullOr types.str;
31-
default = null;
32-
};
33-
execPath = mkOption {
34-
description = "Path to the executable to be launched";
35-
type = types.path;
36-
};
37-
icon = mkOption {
38-
description = ''
39-
Optional icon for the launcher. If unspecified, active icon theme will
40-
be searched to find an icon matching the launcher name. Can be set to an
41-
icon name from the current theme (Papirus) or a full path to an icon file.
42-
'';
43-
type = types.nullOr (types.path // types.str);
44-
default = null;
45-
};
46-
};
47-
}
48-
);
4916
};
5017
};
5118
}

modules/microvm/appvm.nix

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ let
2525
vmName = "${vm.name}-vm";
2626
# A list of applications for the GIVC service
2727
givcApplications = map (app: {
28-
name = app.givcName;
29-
command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/${app.command}";
28+
name = lib.strings.toLower (lib.replaceStrings [ " " ] [ "-" ] app.desktopName);
29+
command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/${app.exec}";
3030
args = app.givcArgs;
3131
}) vm.applications;
3232
# Packages and extra modules from all applications defined in the appvm
@@ -289,56 +289,7 @@ in
289289
description = ''
290290
Applications to include in the AppVM
291291
'';
292-
type = types.listOf (
293-
types.submodule (
294-
{ config, lib, ... }:
295-
{
296-
options = {
297-
name = mkOption {
298-
type = types.str;
299-
description = "The name of the application";
300-
};
301-
description = mkOption {
302-
type = types.str;
303-
description = "A brief description of the application";
304-
};
305-
packages = mkOption {
306-
type = types.listOf types.package;
307-
description = "A list of packages required for the application";
308-
default = [ ];
309-
};
310-
icon = mkOption {
311-
type = types.str;
312-
description = "Application icon";
313-
default = null;
314-
};
315-
command = mkOption {
316-
type = types.str;
317-
description = "The command to run the application";
318-
default = null;
319-
};
320-
extraModules = mkOption {
321-
description = "Additional modules required for the application";
322-
type = types.listOf types.attrs;
323-
default = [ ];
324-
};
325-
givcName = mkOption {
326-
description = "GIVC name for the application";
327-
type = types.str;
328-
};
329-
givcArgs = mkOption {
330-
description = "A list of GIVC arguments for the application";
331-
type = types.listOf types.str;
332-
default = [ ];
333-
};
334-
};
335-
config = {
336-
# Create a default GIVC name for the application
337-
givcName = lib.mkDefault (lib.strings.toLower (lib.replaceStrings [ " " ] [ "-" ] config.name));
338-
};
339-
}
340-
)
341-
);
292+
type = lib.types.listOf lib.types.ghafApplication;
342293
default = [ ];
343294
};
344295
packages = mkOption {

modules/microvm/sysvms/guivm.nix

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,17 @@ let
3131
# Launchers for all virtualized applications that run in AppVMs
3232
virtualLaunchers = map (app: rec {
3333
inherit (app) name;
34+
inherit (app) desktopName;
35+
inherit (app) genericName;
36+
inherit (app) categories;
37+
inherit (app) startupWMClass;
3438
inherit (app) description;
35-
#inherit (app) givcName;
36-
vm = app.vmName;
37-
execPath = "${pkgs.givc-cli}/bin/givc-cli ${config.ghaf.givc.cliArgs} start app --vm ${vm} ${app.givcName}";
3839
inherit (app) icon;
40+
vm = app.vmName;
41+
exec = "${pkgs.givc-cli}/bin/givc-cli ${config.ghaf.givc.cliArgs} start app --vm ${vm} ${
42+
lib.strings.toLower (lib.replaceStrings [ " " ] [ "-" ] app.desktopName)
43+
}";
3944
}) virtualApps;
40-
41-
# Launchers for all desktop, non-virtualized applications that run in the GUIVM
42-
guivmLaunchers = map (app: {
43-
inherit (app) name;
44-
inherit (app) description;
45-
execPath = app.command;
46-
inherit (app) icon;
47-
}) cfg.applications;
4845
in
4946
{
5047
imports = [
@@ -122,7 +119,7 @@ let
122119
enable = true; # Enable graphical boot on gui-vm
123120
renderer = "gpu"; # Use GPU for graphical boot in gui-vm
124121
};
125-
launchers = guivmLaunchers ++ lib.optionals config.ghaf.givc.enable virtualLaunchers;
122+
launchers = cfg.applications ++ lib.optionals config.ghaf.givc.enable virtualLaunchers;
126123
cosmic = {
127124
securityContext.rules = map (vm: {
128125
identifier = vm.name;
@@ -353,30 +350,7 @@ in
353350
description = ''
354351
Applications to include in the GUIVM
355352
'';
356-
type = lib.types.listOf (
357-
lib.types.submodule {
358-
options = {
359-
name = lib.mkOption {
360-
type = lib.types.str;
361-
description = "The name of the application";
362-
};
363-
description = lib.mkOption {
364-
type = lib.types.str;
365-
description = "A brief description of the application";
366-
};
367-
icon = lib.mkOption {
368-
type = lib.types.str;
369-
description = "Application icon";
370-
default = null;
371-
};
372-
command = lib.mkOption {
373-
type = lib.types.str;
374-
description = "The command to run the application";
375-
default = null;
376-
};
377-
};
378-
}
379-
);
353+
type = lib.types.listOf lib.types.ghafApplication;
380354
default = [ ];
381355
};
382356
};

0 commit comments

Comments
 (0)