Skip to content

Raise a running app the launcher is asked to open - #16097

Open
dmkenney wants to merge 2 commits into
omacom:quattrofrom
dmkenney:launcher-activation-token
Open

dmkenney wants to merge 2 commits into
omacom:quattrofrom
dmkenney:launcher-activation-token

Conversation

@dmkenney

@dmkenney dmkenney commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Part of #16078. Needs omacom/omarchy-pkgs#1367 for the token; without it the launcher works as before.

What changed

Hyprland refuses an xdg-activation request whose token carries no input serial since hyprwm/Hyprland#16427 (unreleased, and in omacom/omarchy-pkgs's Hyprland once that carries it). The Apps launcher ran gtk-launch, which replaces the caller's token with a fresh one that has no serial whenever the entry sets StartupNotify=true. So picking an app that's already running (Nautilus, for example) would no longer bring its window forward. Hyprland would only mark it urgent.

  • AppLibrary.launch asks quickshell for a token tied to the click (Quickshell.requestActivationToken(), added in omarchy-pkgs#1367), and launches from the callback with the token as XDG_ACTIVATION_TOKEN. On a quickshell without the call it launches at once with no token.
  • New hidden omarchy-launch-desktop-entry finds the entry's file in the XDG data dirs and runs gio launch on it, which keeps the caller's token. A DBusActivatable=true app is activated with org.freedesktop.Application.Activate and the token instead, because GLib's D-Bus activation only sends a token from its own launch context. IDs that don't map to a file fall back to gtk-launch, as before.
  • Launches still go through uwsm-app, so apps keep their own scope.

How it was verified

  • test/shell.d/launch-desktop-entry-test.sh (new): token passed through gio launch, the user's copy of an entry first, IDs with spaces or ending in .desktop, D-Bus activation with the token, and the gtk-launch fallback.
  • ./test/cli: 125 ok, 0 failed.
  • app-search-test.sh updated for the new launch path (it asserted the old gtk-launch call), plus a check that the token is passed. It and the other launcher tests (dock-test.sh, desktop-entry-launch-test.sh, app-icon-scan-test.sh) pass.
  • Which launchers keep an inherited token, checked with an entry that logs its environment: gtk-launch keeps it only without StartupNotify=true; gio launch and uwsm app always keep it.
  • Nested Hyprland 0.56.2 with Tell T2 Mac owners to save their Wi-Fi firmware before installing #16427 and the stricter serial check, quickshell built with the token call, Nautilus running and foot focused:
    • uwsm-app -- gtk-launch org.gnome.Nautilus.desktop (today's path): invalid serial 0 … rejecting, focus stays on foot.
    • A real click running the new path: quickshell token → omarchy-launch-desktop-entry → D-Bus Activate with the token → focus moves to Nautilus.
    • On stock 0.56.2, today's path raises Nautilus, so this keeps current behavior once Hyprland checks serials.

Not verified: the full Omarchy shell running the new AppLibrary.launch (tested with a panel that runs the same code), and the full ./test/shell suite (it brings up a second bar on a live desktop).

Update: async token

Quickshell review rejected the blocking Quickshell.activationToken(): it waited on a Wayland roundtrip on the UI thread. quickshell-mirror/quickshell#1353 replaces it with Quickshell.requestActivationToken(callback), and AppLibrary.launch now launches from the callback.

The launcher closes its window before launch() runs. With the first version of the quickshell helper that dropped the token (it was tied to the window), so quickshell-mirror/quickshell#1351 now gives each request its own token object. No change was needed here for that.

@greptile-apps

greptile-apps Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The change reaches the desktop-app launch paths across Omarchy’s launcher and dock.

The launch changes have no established blocking behavior bug, but the test organization requirement must be met before merging.

Findings

  1. P2 Launch tests are split ▶

Summary

The launcher now requests an activation token without blocking and passes it to a new desktop-entry helper.

  • App selections carry a click token so running windows can come forward.

The earlier unnumbered finding about stale launch assertions is addressed: those assertions are absent from the current app-search-test.sh.

The previous-review range was not used because its merge base differs from the current PR's merge base. The full PR changes were reviewed.

Reviews (4) · Last reviewed commit: "Wait for the launcher's activation token..." · Reviewed by Greptile

Comment thread shell/services/AppLibrary.qml Resolved
@omarchybot omarchybot added the enhancement New feature or request label Oct 22, 2026
dmkenney added a commit to dmkenney/omarchy-pkgs that referenced this pull request Oct 24, 2026
The old patch waited for the token with a Wayland roundtrip on the UI
thread, which can block for as long as the compositor takes, and a
roundtrip doesn't guarantee the token has arrived. Upstream review
rejected that approach.

The patch is now the upstream commits on top of the pinned commit:
quickshell-mirror/quickshell#1166 (merged: shared activation helper and
tray tokens), and omacom#1351 and omacom#1353 (notification tokens and
Quickshell.requestActivationToken(), both async). Quickshell.
activationToken() is gone; omacom/omarchy#16097 moves to the callback.
dmkenney added a commit to dmkenney/omarchy-pkgs that referenced this pull request Oct 24, 2026
The old patch waited for the token with a Wayland roundtrip on the UI
thread, which can block for as long as the compositor takes, and a
roundtrip doesn't guarantee the token has arrived. Upstream review
rejected that approach.

The patch is now the upstream commits on top of the pinned commit:
quickshell-mirror/quickshell#1166 (merged: shared activation helper and
tray tokens), and omacom#1351 and omacom#1353 (notification tokens and
Quickshell.requestActivationToken(), both async).
Quickshell.activationToken() is gone; omacom/omarchy#16097 moves to the
callback.
dmkenney added a commit to dmkenney/omarchy-pkgs that referenced this pull request Oct 24, 2026
The old patch waited for the token with a Wayland roundtrip on the UI
thread, which can block for as long as the compositor takes, and a
roundtrip doesn't guarantee the token has arrived. Upstream review
rejected that approach.

The patch is now the upstream commits on top of the pinned commit:
quickshell-mirror/quickshell#1166 (merged: shared activation helper and
tray tokens), and omacom#1351 and omacom#1353 (notification tokens and
Quickshell.requestActivationToken(), both async). omacom#1351 also gives each
token request its own callback, so overlapping requests get their own
tokens and a request survives its window closing.
Quickshell.activationToken() is gone; omacom/omarchy#16097 moves to the
callback.
Hyprland refuses an xdg-activation request whose token carries no input
serial since hyprwm/Hyprland#16427. The launcher ran apps through
gtk-launch, which replaces the token with one of its own that carries
none whenever the entry asks for startup notification, so picking an
app that is already running no longer raised its window.

Ask quickshell for a token tied to the click and launch through
omarchy-launch-desktop-entry, which passes it on: gio launch keeps the
caller's XDG_ACTIVATION_TOKEN, and a D-Bus activatable app is activated
over D-Bus with the token, since GLib's D-Bus activation only sends a
token of its own. gtk-launch stays as the fallback for ids that don't
map to a file.
Quickshell.activationToken() blocked the UI thread until the compositor
answered, so quickshell#1353 replaced it with requestActivationToken(),
which passes the token to a callback. Launch from that callback.
@dmkenney
dmkenney force-pushed the launcher-activation-token branch from d4f3d2a to bbd0a6f Compare November 2, 2026 18:03
@dmkenney

dmkenney commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on quattro. #16334 removed the app-search-test.sh assertions that Greptile flagged, so I dropped the commit that updated them. launch-desktop-entry-test.sh and app-search-test.sh pass.


set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Launch tests are split

This new test file breaks the repository's instruction to extend the area's existing tests rather than add another *-test.sh. Move these helper checks into test/shell.d/desktop-entry-launch-test.sh, which already covers desktop-entry launches. This repository requirement must be met before merging.

File Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@Pakvothe

Copy link
Copy Markdown

Still happens on Hyprland 0.57.1 (Try Omarchy, aarch64): asking for an app that's already open on another workspace (Nautilus, Chromium) doesn't switch to it.

One path this PR doesn't cover: plugin panels that open windows with Quickshell.execDetached. Superwhisper's panel runs superwhisper settings, and with the settings window open on workspace 1 and workspace 2 active, Hyprland moves focus to it (activewindow>>com.superwhisper.Superwhisper) but stays on workspace 2. hl.dsp.focus({ window = "address:…" }) on the same window does switch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants