Skip to content

SetContent drops the text/plain offer for file:// strings, breaking paste into text fields #28

Description

@ReyMoss

Reproduction steps

  1. Create a Vicinae snippet whose content is a local file URI, for example file:///run/user/1000/, and give it a keyword trigger.
  2. Type that trigger in any text field. I used Zed and a browser address bar.
  3. The trigger is deleted and nothing is inserted in its place.

The same result without Vicinae, by driving the D-Bus method it uses:

gdbus call --session --dest org.gnome.Shell \
  --object-path /org/gnome/Shell/Extensions/Clipboard \
  --method org.gnome.Shell.Extensions.Clipboard.SetContent 'file:///run/user/1000/'

wl-paste --list-types       # text/uri-list
wl-paste --type text/plain  # Clipboard content is not available as requested type

Current vs. Expected behavior

Current: the clipboard carries a single text/uri-list offer, so an application that pastes text asks for text/plain, receives nothing, and inserts nothing.

Expected: text targets can still paste the string, the way they do when the same string is placed on the clipboard by wl-copy.

FileHandler.set() in core/clipboard/handlers/file-handler.js calls St.Clipboard.set_content with text/uri-list only, for both CLIPBOARD and PRIMARY. It is selected by matchesContent() via isFileUri() in utils/clipboard-utils.js, which returns true when every line of the content starts with file://. Since set_content replaces rather than adds, no text offer survives. The handler was introduced for #15, where file URIs offered as plain text prevented Electron and Chromium targets from recognising a file.

clipboard set via resulting offers
wl-copy 'file:///run/user/1000/' text/plain, text/plain;charset=utf-8, UTF8_STRING, STRING, TEXT
SetContent 'file:///run/user/1000/' text/uri-list
SetContent 'https://example.com' text/plain;charset=utf-8
SetContent 'x file:///run/user/1000/' text/plain;charset=utf-8
SetContent '/run/user/1000/' text/plain;charset=utf-8

Vicinae reaches this path because it expands snippets through the clipboard: it copies the expanded text, injects Ctrl+V, then restores the previous clipboard, and usesClipboard is hardcoded to true on Linux.

Vicinae server log for one expansion
vicinae: Snippet expansion: keyword="zen" app="dev.zed.Zed.desktop" terminal=false
vicinae: SNIPPET TRIGGERED: zen
vicinae: Deferring expansion until modifiers are released
vicinae: SNIPPET EMITTING (mods released): zen
vicinae: Received new clipboard selection with 1 offers (password= false )
vicinae: "text/uri-list" (size="23 bytes")
vicinae: Received new clipboard selection with 1 offers (password= false )
vicinae: "text/uri-list" (size="22 bytes")
vicinae: Received new clipboard selection with 1 offers (password= false )
vicinae: "text/plain" (size="18 bytes")
vicinae: SNIPPET UNDO: zen

The 22 byte payload is the snippet text file:///run/user/1000/, the 23 byte one includes the trailing space added by the word boundary option, and the 18 byte text/plain entry is the previous clipboard being restored.

Workaround in use

Storing the snippet without the scheme, /run/user/1000/ instead of file:///run/user/1000/, which no longer matches isFileUri and pastes as text. Address bars resolve absolute paths anyway.

Extension version and system specs

Extension 1.6.2
Vicinae 0.26.3
NixOS 26.11, kernel 7.1.8
GNOME Shell 50.4, Wayland

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