From 5eb4c6a0bbbff3ffe6ccf46264ccd0498f6fb516 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 25 Jul 2021 00:55:57 +0100 Subject: [PATCH] Set _KDE_NET_WM_DESKTOP_FILE x11 window property. This explicitly tells KDE to associate the OpenRA window with the integrated appimage desktop file, allowing it to use the correct resolution icon for the task switcher. --- .../Sdl2PlatformWindow.cs | 42 ++++++++++++++++++- packaging/linux/openra.appimage.in | 34 +++++++++------ 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/OpenRA.Platforms.Default/Sdl2PlatformWindow.cs b/OpenRA.Platforms.Default/Sdl2PlatformWindow.cs index 0972379dc0..11259f1ff3 100644 --- a/OpenRA.Platforms.Default/Sdl2PlatformWindow.cs +++ b/OpenRA.Platforms.Default/Sdl2PlatformWindow.cs @@ -124,6 +124,15 @@ namespace OpenRA.Platforms.Default [DllImport("user32.dll")] static extern bool SetProcessDPIAware(); + [DllImport("libX11")] + static extern IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists); + + [DllImport("libX11", CharSet=CharSet.Ansi)] + static extern int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, IntPtr mode, string data, int elements); + + [DllImport("libX11")] + static extern IntPtr XFlush(IntPtr display); + public Sdl2PlatformWindow(Size requestEffectiveWindowSize, WindowMode windowMode, float scaleModifier, int batchSize, int videoDisplay, GLProfile requestProfile, bool enableLegacyGL) { @@ -218,10 +227,10 @@ namespace OpenRA.Platforms.Default window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED_DISPLAY(videoDisplay), SDL.SDL_WINDOWPOS_CENTERED_DISPLAY(videoDisplay), windowSize.Width, windowSize.Height, windowFlags); - // Work around an issue in macOS's GL backend where the window remains permanently black - // (if dark mode is enabled) unless we drain the event queue before initializing GL if (Platform.CurrentPlatform == PlatformType.OSX) { + // Work around an issue in macOS's GL backend where the window remains permanently black + // (if dark mode is enabled) unless we drain the event queue before initializing GL while (SDL.SDL_PollEvent(out var e) != 0) { // We can safely ignore all mouse/keyboard events and window size changes @@ -241,6 +250,35 @@ namespace OpenRA.Platforms.Default } } } + else if (Platform.CurrentPlatform == PlatformType.Linux) + { + // The KDE task switcher limits itself to the 128px icon unless we + // set an X11 _KDE_NET_WM_DESKTOP_FILE property on the window + var currentDesktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP"); + var desktopFilename = Environment.GetEnvironmentVariable("OPENRA_DESKTOP_FILENAME"); + if (desktopFilename != null && currentDesktop == "KDE") + { + try + { + var info = default(SDL.SDL_SysWMinfo); + SDL.SDL_VERSION(out info.version); + SDL.SDL_GetWindowWMInfo(Window, ref info); + + var d = info.info.x11.display; + var w = info.info.x11.window; + var property = XInternAtom(d, "_KDE_NET_WM_DESKTOP_FILE", false); + var type = XInternAtom(d, "UTF8_STRING", false); + + XChangeProperty(d, w, property, type, 8, IntPtr.Zero, desktopFilename, desktopFilename.Length + 1); + XFlush(d); + } + catch + { + Log.Write("debug", "Failed to set _KDE_NET_WM_DESKTOP_FILE"); + Console.WriteLine("Failed to set _KDE_NET_WM_DESKTOP_FILE"); + } + } + } // Enable high resolution rendering for Retina displays if (Platform.CurrentPlatform == PlatformType.OSX) diff --git a/packaging/linux/openra.appimage.in b/packaging/linux/openra.appimage.in index 727545f5c2..45cac44b4f 100755 --- a/packaging/linux/openra.appimage.in +++ b/packaging/linux/openra.appimage.in @@ -8,19 +8,27 @@ cd "${HERE}/../lib/openra" || exit 1 if [ -n "${APPIMAGE}" ]; then LAUNCHER=${APPIMAGE} - # appimaged doesn't update the mime or icon caches when registering AppImages. - # Run update-desktop-database and gtk-update-icon-cache ourselves if we detect - # that the desktop file has been installed but the handler is not cached - if command -v update-desktop-database > /dev/null; then - APPIMAGEID=$(printf "file://%s" "${APPIMAGE}" | md5sum | cut -d' ' -f1) - LAUNCHER_NAME="appimagekit_${APPIMAGEID}-openra-{MODID}.desktop" - LAUNCHER_PATH="${HOME}/.local/share/applications/${LAUNCHER_NAME}" - MIMECACHE_PATH="${HOME}/.local/share/applications/mimeinfo.cache" - SCHEME="x-scheme-handler/openra-{MODID}-{TAG}" - if [ -f "${LAUNCHER_PATH}" ] && ! grep -qs "${SCHEME}=" "${MIMECACHE_PATH}"; then - update-desktop-database "${HOME}/.local/share/applications" - if command -v gtk-update-icon-cache > /dev/null; then - gtk-update-icon-cache ~/.local/share/icons/hicolor/ -t + APPIMAGEID=$(printf "file://%s" "${APPIMAGE}" | md5sum | cut -d' ' -f1) + LAUNCHER_NAME="appimagekit_${APPIMAGEID}-openra-{MODID}.desktop" + LAUNCHER_PATH="${HOME}/.local/share/applications/${LAUNCHER_NAME}" + export SDL_VIDEO_X11_WMCLASS="openra-{MODID}-{TAG}" + + if [ -f "${LAUNCHER_PATH}" ]; then + # The KDE task switcher limits itself to the 128px icon unless we + # set an X11 _KDE_NET_WM_DESKTOP_FILE property on the window + export OPENRA_DESKTOP_FILENAME="${LAUNCHER_NAME}" + + # appimaged doesn't update the mime or icon caches when registering AppImages. + # Run update-desktop-database and gtk-update-icon-cache ourselves if we detect + # that the desktop file has been installed but the handler is not cached + if command -v update-desktop-database > /dev/null; then + MIMECACHE_PATH="${HOME}/.local/share/applications/mimeinfo.cache" + SCHEME="x-scheme-handler/openra-{MODID}-{TAG}" + if ! grep -qs "${SCHEME}=" "${MIMECACHE_PATH}"; then + update-desktop-database "${HOME}/.local/share/applications" + if command -v gtk-update-icon-cache > /dev/null; then + gtk-update-icon-cache ~/.local/share/icons/hicolor/ -t + fi fi fi fi