Skip to content

[Linux] XDG Portal UI differences across desktop environments #64

@Bo0sted

Description

@Bo0sted

Bug Report: XDG Portal UI Differences Between Linux Systems

Summary

The XDG Desktop Portal Screenshot interface behaves differently across Linux systems. On the developer's machine, the portal provides a rectangle selection tool for region capture. On the tester's machine (Arch + KDE Plasma + Wayland), a different portal UI appears that looks "weird" compared to the expected interface.

This report documents the portal implementation details, system configuration, and DBus calls to help understand why different portal backends produce different user experiences.


Environment

System Information

  • OS: EndeavourOS (Arch-based)
  • Kernel: Linux 6.18.6-zen1-1-zen
  • Architecture: x86_64
  • Session Type: Wayland
  • Desktop Environment: KDE Plasma
  • KDE Frameworks: 5.116.0
  • Qt Version: 5.15.18

XDG Portal Packages

libportal 0.9.1-2
libportal-gtk4 0.9.1-2
xdg-desktop-portal 1.20.3-2
xdg-desktop-portal-gtk 1.15.3-1
xdg-desktop-portal-kde 6.5.5-1

Active Portal Backends

From busctl --user list:

org.freedesktop.impl.portal.desktop.gtk    PID 8174  xdg-desktop-portal-gtk
org.freedesktop.impl.portal.desktop.kde    PID 8321  xdg-desktop-portal-kde
org.freedesktop.portal.Desktop             PID 7756  xdg-desktop-portal (main)

Key Finding: Both GTK and KDE portal backends are running simultaneously. The main portal daemon (org.freedesktop.portal.Desktop) decides which backend to use based on the desktop environment and portal configuration.

Portal Configuration

  • User config: None (~/.config/xdg-desktop-portal/portals.conf does not exist)
  • System config: None (/etc/xdg-desktop-portal/portals.conf does not exist)

Implication: Without explicit configuration, the portal uses automatic backend selection based on $XDG_CURRENT_DESKTOP (KDE in this case).


Test Results

Test: Region Capture with XDG Portal

Trigger: Pressed Scroll Lock hotkey to capture region

Result: ✅ SUCCESS - Portal opened and region was captured

Captured Image: 410x508 pixels
Capture Time: 14.164 seconds (user interaction time)

User Observation: "A weird looking portal opened up"

Debug Logs

Portal Invocation:

2026-02-02 18:56:47.332 - LinuxScreenCaptureService: CaptureRegionAsync - using interactive region selection
2026-02-02 18:56:47.332 - LinuxScreenCaptureService: Detected desktop environment: KDE, Wayland: True
2026-02-02 18:56:47.332 - LinuxScreenCaptureService: Trying XDG Portal for interactive region capture

Portal Response:

[XDG Portal] SIGNAL RECEIVED: Response=0, Count=1
2026-02-02 18:57:01.495 - LinuxScreenCaptureService: Region captured with XDG Portal
2026-02-02 18:57:01.496 - Captured image: 410x508 in 14164ms

Analysis:

  • Portal responded with Response=0 (success)
  • User successfully selected a region (410x508)
  • The portal UI appeared and functioned correctly, but looked different than expected

Technical Details: XDG Portal Implementation

DBus Interface Used

XerahS calls the XDG Desktop Portal Screenshot API via DBus:

Bus Name: org.freedesktop.portal.Desktop
Object Path: /org/freedesktop/portal/desktop
Interface: org.freedesktop.portal.Screenshot
Method: Screenshot(parent_window: s, options: a{sv}) -> o

Portal Options Sent by XerahS

From LinuxScreenCaptureService.cs:1042-1047:

var options = new Dictionary<string, object>
{
    ["modal"] = false,
    ["interactive"] = forceInteractive,  // true for region capture
    ["handle_token"] = $"xerahs_{Guid.NewGuid():N}"
};

For region capture (CaptureRegionAsync):

  • interactive = true (forces user interaction)
  • modal = false (non-modal dialog)
  • handle_token = unique identifier (e.g., xerahs_8920089090b043d2a5d42440e8d0524c)

Portal Backend Selection

The main portal daemon (xdg-desktop-portal) forwards the Screenshot request to a backend implementation based on:

  1. Desktop Environment: $XDG_CURRENT_DESKTOP = KDE
  2. Available Backends:
    • xdg-desktop-portal-kde (KDE native)
    • xdg-desktop-portal-gtk (GNOME/GTK fallback)

Expected Behavior: On KDE, the portal should use xdg-desktop-portal-kde.


Why Portal UIs Differ

Portal Backend Implementations

Each portal backend provides its own UI for the Screenshot interface:

  1. xdg-desktop-portal-kde (KDE Plasma):

    • Uses KDE's native screenshot tool (Spectacle) or custom Qt-based UI
    • Appearance matches KDE Plasma theme
    • May show different selection tools depending on version
  2. xdg-desktop-portal-gtk (GNOME):

    • Uses GTK-based UI
    • Appearance matches GNOME/GTK theme
    • Typically shows a crosshair cursor with rectangle selection
  3. xdg-desktop-portal-wlr (wlroots compositors):

    • Uses grim + slurp for selection
    • Minimal UI with colored rectangle overlay

Possible Causes of "Weird" UI

  1. KDE Portal Version Differences:

    • Tester has xdg-desktop-portal-kde 6.5.5-1
    • Developer may have a different version with different UI
  2. Qt/KDE Theme Differences:

    • Portal UI inherits system theme
    • Different themes produce different appearances
  3. Spectacle Integration:

    • KDE portal may invoke Spectacle differently
    • Spectacle version differences affect UI
  4. GTK Backend Fallback:

    • If KDE backend fails or is misconfigured, GTK backend may be used
    • GTK UI on KDE looks "weird" because it doesn't match the desktop theme

Comparison: Expected vs. Actual

Developer's Machine (Expected)

  • Portal UI: Rectangle selection tool (likely GTK-based or wlroots-based)
  • Appearance: Clean, minimal interface
  • Behavior: User drags to select region

Tester's Machine (Actual)

  • Portal UI: "Weird looking" interface
  • Backend: Likely xdg-desktop-portal-kde 6.5.5-1
  • Appearance: Different from developer's experience
  • Behavior: Functional but visually different

Investigation Needed

To fully understand the differences, we need to know:

  1. Developer's System:

    • Which portal backend is used? (xdg-desktop-portal-gtk, xdg-desktop-portal-wlr, etc.)
    • Desktop environment (GNOME, Sway, Hyprland, etc.)
    • Portal package versions
  2. Portal Backend Logs:

    • Enable portal debug logging: G_MESSAGES_DEBUG=all xdg-desktop-portal
    • Check which backend handles the Screenshot request
    • Verify if KDE backend is actually being used
  3. Spectacle Behavior:

    • Does KDE portal invoke Spectacle directly?
    • What version of Spectacle is installed?
    • Can Spectacle be configured to change the UI?

Recommendations

For Documentation

  1. Document Portal Backend Differences:

    • Explain that XDG Portal UI varies by desktop environment
    • Provide screenshots of different portal backends
    • Set user expectations that UI will match their DE
  2. Troubleshooting Guide:

    • How to check which portal backend is active
    • How to configure preferred portal backend
    • How to debug portal issues

For Development

  1. Portal Backend Detection:

    • Log which portal backend responds to requests
    • Detect portal backend version for debugging
  2. Fallback Options:

    • If portal UI is problematic, offer alternative capture methods
    • Allow users to disable portal and use CLI tools (grim, spectacle, etc.)
  3. Portal Configuration:

    • Provide option to force specific portal backend
    • Allow users to customize portal options (modal, interactive, etc.)

Additional Notes

Why Multiple Portal Backends Run Simultaneously

From the busctl output, both GTK and KDE backends are running:

  • xdg-desktop-portal-gtk (PID 8174)
  • xdg-desktop-portal-kde (PID 8321)

This is normal behavior. The main portal daemon (xdg-desktop-portal) acts as a router and forwards requests to the appropriate backend based on:

  • Desktop environment ($XDG_CURRENT_DESKTOP)
  • Portal configuration files
  • Interface availability

Only one backend handles each request, but multiple backends can be active simultaneously to support mixed environments (e.g., running GTK apps on KDE).

Portal Specification

The XDG Desktop Portal Screenshot interface is defined by the Freedesktop specification:

XerahS correctly implements this specification. The UI differences are expected behavior based on the portal backend implementation.


Conclusion

The "weird" portal UI is not a bug in XerahS, but rather a difference in portal backend implementations across Linux systems. The XDG Desktop Portal specification defines the API, but each backend (KDE, GTK, wlroots) provides its own UI.

Key Takeaway: XerahS correctly uses the XDG Portal API. The visual appearance of the portal is determined by the user's desktop environment and portal backend, which is outside XerahS's control.

Recommendation: Document this behavior and set user expectations that the portal UI will vary based on their Linux distribution and desktop environment.


System Information Summary

Component Version/Value
OS EndeavourOS (Arch)
Kernel 6.18.6-zen1-1-zen
Session Wayland
Desktop KDE Plasma
KDE Frameworks 5.116.0
Qt 5.15.18
xdg-desktop-portal 1.20.3-2
xdg-desktop-portal-kde 6.5.5-1
xdg-desktop-portal-gtk 1.15.3-1
libportal 0.9.1-2
Active Backend xdg-desktop-portal-kde (expected)

Debug Information

Portal DBus Call

Bus: org.freedesktop.portal.Desktop
Path: /org/freedesktop/portal/desktop
Interface: org.freedesktop.portal.Screenshot
Method: Screenshot("", {"interactive": true, "modal": false, "handle_token": "xerahs_..."})

Portal Response

Response: 0 (success)
URI: file:///path/to/screenshot.png
Image Size: 410x508

Capture Flow

  1. User triggers region capture (Scroll Lock hotkey)
  2. XerahS calls LinuxScreenCaptureService.CaptureRegionAsync()
  3. Service detects Wayland + KDE environment
  4. Service calls CaptureWithPortalAsync(forceInteractive: true)
  5. Portal shows UI (KDE-specific implementation)
  6. User selects region (14 seconds)
  7. Portal returns success with screenshot URI
  8. XerahS loads and processes the image
XDGPortal.mp4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions