// Explicit clipboard capture, path #2. Lane GUI. // // docs/06-risks-and-spikes.md R2: a Wayland client cannot passively observe clipboard // changes made by other applications — not a bug, a deliberate security property, and // the mechanism IDM's clipboard capture relies on does not exist here. The ship-regardless // design has three *explicit* paths instead; this is the second one — a global shortcut // via org.freedesktop.portal.GlobalShortcuts that reads the clipboard on demand when the // user presses it. (#1 is the extension's context menu, EXT's; #3 is AddUrlDialog's // clipboard prefill on open, already in place.) // // Best-effort by design, same as the risk doc says to treat all of this: the portal may // not exist on this desktop, the compositor may not implement it even if the portal // service does, or the user may decline the one-time "let Velox bind a global shortcut" // prompt. Every one of those is silent, permanent for this session, and never surfaced as // an error — there is nothing actionable for the user to do about a desktop that doesn't // have this, and the explicit paths (menu, prefill) still work regardless. Never promise // this in the UI before it has actually fired once. #pragma once #include #include class QDBusObjectPath; namespace velox::gui { class GlobalShortcut : public QObject { Q_OBJECT public: explicit GlobalShortcut(QObject *parent = nullptr); /// Fire-and-forget: asks the portal for a session, then to bind one shortcut. There is /// no synchronous "is this supported" answer — connect activated() and find out from /// whether it ever fires. Safe to call once at startup; safe to call on a desktop with /// no portal at all (logs and returns, does nothing further). void requestBinding(); signals: /// The bound shortcut was pressed. No payload on purpose: the receiver reads the /// clipboard itself at this moment (the "on demand" part of the explicit-path design), /// so nothing here ever touches clipboard content that wasn't asked for right now. void activated(); private slots: void onCreateSessionResponse(uint code, const QVariantMap &results); void onBindShortcutsResponse(uint code, const QVariantMap &results); void onPortalActivated(const QDBusObjectPath &sessionHandle, const QString &shortcutId, qulonglong timestamp, const QVariantMap &options); private: void bindShortcuts(); QString sessionHandle_; bool requested_ = false; }; } // namespace velox::gui