diff --git a/bottles/backend/managers/installer.py b/bottles/backend/managers/installer.py
index 0fb1e65f278..49289639171 100644
--- a/bottles/backend/managers/installer.py
+++ b/bottles/backend/managers/installer.py
@@ -479,7 +479,7 @@ def install(
# create Desktop entry
bottles_icons_path = os.path.join(ManagerUtils.get_bottle_path(config), "icons")
icon_path = os.path.join(bottles_icons_path, executable.get("icon"))
- ManagerUtils.create_desktop_entry(_config, _program, False, icon_path)
+ ManagerUtils.create_desktop_entry(_config, _program, False, icon_path, True)
if is_final:
step_fn()
diff --git a/bottles/backend/utils/imagemagick.py b/bottles/backend/utils/imagemagick.py
index c83e560158d..d1acf054575 100644
--- a/bottles/backend/utils/imagemagick.py
+++ b/bottles/backend/utils/imagemagick.py
@@ -85,4 +85,4 @@ def convert(
cmd += " -flatten"
cmd += f" '{dest}'"
- subprocess.Popen(["bash", "-c", cmd])
+ subprocess.run(["bash", "-c", cmd])
diff --git a/bottles/backend/utils/manager.py b/bottles/backend/utils/manager.py
index af92788aa76..e332057428c 100644
--- a/bottles/backend/utils/manager.py
+++ b/bottles/backend/utils/manager.py
@@ -24,6 +24,8 @@
import icoextract # type: ignore [import-untyped]
+from bottles.backend.params import APP_ID
+
from bottles.backend.globals import Paths
from bottles.backend.logger import Logger
from bottles.backend.models.config import BottleConfig
@@ -32,6 +34,11 @@
from bottles.backend.utils.generic import get_mime
from bottles.backend.utils.imagemagick import ImageMagickUtils
+import uuid
+from gi.repository import GLib, Gio, Gtk, Xdp, XdpGtk4
+
+portal = Xdp.Portal()
+
logging = Logger()
@@ -224,6 +231,7 @@ def create_desktop_entry(
skip_icon: bool = False,
custom_icon: str = "",
use_xdp: bool = False,
+ window: Gtk.Window = None,
) -> bool:
if not os.path.exists(Paths.applications) and not use_xdp:
return False
@@ -279,41 +287,49 @@ def create_desktop_entry(
f.write(f"Exec={cmd_legacy} -b '{config.get('Name')}'\n")
return True
- '''
- WIP: the following code is not working yet, it raises an error:
- GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod
- import uuid
- from gi.repository import Gio, Xdp
- portal = Xdp.Portal()
+ def prepare_install_cb (self, result):
+ ret = portal.dynamic_launcher_prepare_install_finish(result)
+ id = f"{config.get('Name')}.{program.get('name')}"
+ sum_type = GLib.ChecksumType.SHA1
+ exec = "bottles-cli run -p {} -b '{}' -- %u".format(
+ shlex.quote(program.get('name')), config.get('Name')
+ )
+ portal.dynamic_launcher_install(
+ ret["token"],
+ "{}.App_{}.desktop".format(
+ APP_ID, GLib.compute_checksum_for_string(sum_type, id, -1)
+ ),
+ """[Desktop Entry]
+ Exec={}
+ Type=Application
+ Terminal=false
+ Categories=Application;
+ Comment=Launch {} using Bottles.
+ StartupWMClass={}""".format(
+ exec, program.get("name"), program.get("name")
+ )
+ #TODO: Desktop Actions Configure missing
+ #[Desktop Action Configure]
+ #Name=Configure in Bottles
+ #Exec={}
+ )
+ #TODO: Require xdp>=1.20.1
if icon == "com.usebottles.bottles-program":
- _icon = Gio.BytesIcon.new(icon.encode("utf-8"))
+ icon += ".svg"
+ _icon = Gio.File.new_for_uri(
+ f"resource:/com/usebottles/bottles/icons/scalable/apps/{icon}"
+ )
else:
- _icon = Gio.FileIcon.new(Gio.File.new_for_path(icon))
- icon_v = _icon.serialize()
- token = portal.dynamic_launcher_request_install_token(program.get("name"), icon_v)
- portal.dynamic_launcher_install(
- token,
- f"com.usebottles.bottles.{config.get('Name')}.{program.get('name')}.{str(uuid.uuid4())}.desktop",
- """
- [Desktop Entry]
- Exec={}
- Type=Application
- Terminal=false
- Categories=Application;
- Comment=Launch {} using Bottles.
- Actions=Configure;
- [Desktop Action Configure]
- Name=Configure in Bottles
- Exec={}
- """.format(
- f"{cmd_cli} run -p {shlex.quote(program.get('name'))} -b '{config.get('Path')}'",
- program.get("name"),
- f"{cmd_legacy} -b '{config.get('Name')}'"
- ).encode("utf-8")
- )
- '''
- return False
+ _icon = Gio.File.new_for_path(icon)
+ icon_v = Gio.BytesIcon.new(_icon.load_bytes()[0]).serialize()
+ portal.dynamic_launcher_prepare_install(XdpGtk4.parent_new_gtk(window),
+ program.get("name"), icon_v,
+ Xdp.LauncherType.APPLICATION,
+ None, True, False, None,
+ prepare_install_cb)
+ #TODO: Rework to delay showing the toast
+ return True
@staticmethod
def browse_wineprefix(wineprefix: dict):
diff --git a/bottles/frontend/widgets/program.py b/bottles/frontend/widgets/program.py
index 2b0e43b382a..789d4b15eb7 100644
--- a/bottles/frontend/widgets/program.py
+++ b/bottles/frontend/widgets/program.py
@@ -304,6 +304,8 @@ def update(result, _error=False):
"executable": self.program["executable"],
"path": self.program["path"],
},
+ use_xdp=True,
+ window=self.window,
)
def add_to_library(self, _widget):
diff --git a/data/data.gresource.xml.in b/data/data.gresource.xml.in
index e690e114bad..45badb913e8 100644
--- a/data/data.gresource.xml.in
+++ b/data/data.gresource.xml.in
@@ -3,6 +3,9 @@
@APP_ID@.metainfo.xml
+
+ icons/hicolor/scalable/apps/com.usebottles.bottles-program.svg
+
icons/hicolor/symbolic/apps/bottles-steam-symbolic.svg
icons/hicolor/symbolic/actions/external-link-symbolic.svg