Home Flight manual By tags Ramblings Colophon RSS

System-wide clipboard history with fcitx5

Series introduction

Maybe a new fcitx

IBus, standing (vaguely) for "Intelligent Input Bus", is an input framework that allows users to, for example, switch between different keyboard layouts, which any non-English native speakers reading this blog would certainly be familiar with.

It is notably used by default by GNOME-based desktop environments, making it the de facto standard for many Linux users; however, it has been somewhat finicky for me (and others) when working with Wayland1—which is where fcitx52 comes in.

But fcitx5 is a lot other than "Wayland's IBus": just as vaguely, it stands for "Flexible Context-aware Input Tool with eXtension support", and in this series, I mean to delve deeply into the most practical and ubiquitous of its built-in modules.

Table of contents

A staple of the frantic user's tool belt, the clipboard history needs no introduction.

I remember the day one of my colleagues excitedly demonstrated their newly-acquired copy-paste buffer history plug-in that would work well inside the very specific "file editing" view of their IDE. I remember it well, because it was last year—a whopping half a century or so after vi introduced them.

Ah, and Vim today offers a lofty forty-five registers, complete with bindings to append, replace, print from as plain text, print from as if you were typing it, et cet.; see :help registers.

But I digress.

What Vim doesn't quite do with its many registers is avail them to other applications. For that, you've got your syste—

Ah, I'm being told that neither Windows nor macOS actually offers any more than one measly "clipboard", despite X11 having had, since the early 1990s at the latest, a complete, detailed specification for no less than three such buffers, two of which are exceptionally convenient and still completely supported and working across the board (BSD and Linux)—even many Wayland compositors implement that compatibility to the X11 specification.

But I digress some more.

If you're neither in a sensible text editor, nor on a sensible OS, and that despite your recurring-payment-contingent system gradually unveiling its dearthy core, its familiar-enough face has you keep coming back... I bid you good luck3; the rest of us shall tonight feast on a tidy serving of fcitx5 goodness.

Clipboard history with fcitx5

A built-in add-on to fcitx5, the clipboard module keeps track of the "stuff" you put in your "clipboard". Obviously, right? Well, with two little notes:

  1. The three X11 "clipboards" I alluded to earlier are collectively referred to as selections. They're the primary, the secondary, and the clipboard. Typically, you write to and paste from the clipboard (well, not really4) with Ctrl+C and Ctrl+V, respectively; any piece of text you select (double-click, or click and hold
  1. The "stuff" only is the plain text part of the data that you copied. Yes, there are indeed several parts in there. Typed data. Lazily streamed on demand. Oh yeah, the X11 selections function—they're a lot more than "some shared data dumps"—they're not even that at all4, to begin with!

So, that module grabs the textual content of what goes into your clipboard selection, and keep it in its memory, though not only that last one! At any time, you can recall the most recent few (how many is configurable), and insert them anywhere you can type—more on that later.

To recall your clipboard history, the default key binding is Ctrl+; (the semicolon). You may then fully configure how to go about making your selection: paginate results, navigate through entries or pages, confirm with either Enter or Space, cancel with Escape, pick a numbered entry right away with 1 through <n> and clear its memory with Backspace or Delete.

Due discretion manipulating passwords

As I mean to go over in a future article, the clipboard isn't just (or at all) a "transient data buffer". If nothing else, the data it exposes is typed—I mean by that that there is some MIME type associated with it.

One such "type", would be x-kde-passwordManagerHint, the de-facto standard (however limited in use) when describing passwords across sensible platforms.

To be precise, x-kde-passwordManagerHint is technically not quite adhering to the MIME specification: it should rather likely be application/x-kde-passwordManagerHint.

Moreover, global, top-level MIME types are typically also registered at the IANA, to its Media Types Registry, which this isn't; but then again no "password" type is.

Capable password managers adequately make use of such types when providing data through your selections (read: "clipboard"). For illustration, here's the reference of how KeePassXC goes about this implementation:

void Clipboard::setText(const QString& text, bool clear)
{
    // ...

    auto* mime = new QMimeData;
    mime->setText(text);
#if defined(Q_OS_MACOS)
    mime->setData("application/x-nspasteboard-concealed-type", text.toUtf8());
#elif defined(Q_OS_UNIX)
    mime->setData("x-kde-passwordManagerHint", QByteArrayLiteral("secret"));
#elif defined(Q_OS_WIN)
    mime->setData("ExcludeClipboardContentFromMonitorProcessing", QByteArrayLiteral("1"));
    mime->setData("CanIncludeInClipboardHistory", {4, '\0'});
    mime->setData("CanUploadToCloudClipboard ", {4, '\0'});
#endif

    // ...
}

Then, courteous "clipboard" inspectors may give you the privacy you deserve in handling that data. By default, fcitx5's clipboard add-on, when prompted to display recent entries for reuse, will indicate them with •••••••• <Password> instead of disclosing their contents. The actual underlying passwords will still be put in5 when you so choose, they're merely obscured for greater assurances that nobody may lay their eyes on them.

The •••••••• <Password> entry that fcitx5 may display always uses 8 "bullet" characters (), regardless of the actual length of the corresponding password. There's absolutely no information surfacing about the content of the password then; only its nature is revealed.

I wanted to ascertain something and ended up also looking up fcitx5's implementation regarding that password handling mechanism, so I might as well leave some interesting excepts here for explanation:

constexpr char PASSWORD_MIME_TYPE[] = "x-kde-passwordManagerHint";
find it also here on GitHub

static const std::string passwordHint = PASSWORD_MIME_TYPE;
if (mimeTypes_.contains(passwordHint)) {
    receiveDataForMime(passwordHint, [this, callbackWrapper](const std::vector<char> &data) {
        if (std::string_view(data.data(), data.size()) == "secret" && ignorePassword_) {
            FCITX_CLIPBOARD_DEBUG() << "Wayland clipboard contains password, ignore.";
            return;
        }
        isPassword_ = true;
        receiveRealData(callbackWrapper);
    });
} else {
    receiveRealData(callbackWrapper);
}
find it also here on GitHub

I should note that this behaviour only is the default one, but that fcitx5 may be configured in several ways, either to ignore these records altogether, denote them with the aforementioned bullets, or let them be shown plainly.

On the topic of discretion with regards to data shown on screen, competent compositors also provide a way to block out some windows from your screen sharing activities. See niri's documentation for illustration.

Anywhere you type

On the topic of passwords, another benefit of using fcitx is that it still is an input method, rather than a tool that pastes content. From the perspective of the applications that receive your input, you're indeed just typing text in.

Take the example of these utterly misguided—and hopefully antiquated—practice6, whereby some password inputs would disallow being pasted into:

<input type="password" onpaste="return false;" placeholder="Passwords, please!">
you shouldn't be able to paste anything in this <input>

No pasting allowed. But if you're running fcitx5, you may just open up your trusty global clipboard machine and pour your precious secrets into my confidential ear—though if you'd be so kind as to rather mail me them, as I don't operate a keylogger here...

Though pretty neat, this may come "at the cost" to what a more general-purpose "clipboard history manager" may give you: fcitx5 only handles textual data through its clipboard add-on. In reality of course, no feature was sacrificed for this one: what we have here is is only the corollary to fcitx5 still being, at its core, an Input Method provider—a pretty good one.

  1. Although "applications being finicky" under Wayland will come at no surprise to anyone, I will note that it mostly has to do with running a lot of X11 applications actually through a compatibility layer, and NVIDIA notoriously having been an execrable collaborator in helping the Linux kernel developers integrate their hardware into the ecosystem.

  2. fcitx5 is a fairly recent project (started around 2019) led by the same original author, a complete rewrite of its predecessor, infusing new life into fcitx notably in including first-class Wayland support, a vastly more modern codebase, greater performance (reportedly), and some unified theming and configuration tools.

  3. I truly mean this in good faith, and you're obviously much welcome to stay and join us—I only jest here, I have no qualms against users of any platform. Plus, in all honestly, I have absolutely no doubt that the very same capabilities are available on these as well.

  4. Not really. Not directly. In fact, nothing ever "writes to it"—the original authors didn't design them for machines with 32GB or RAM to waste away on such frivolities. There's a lot more to unpack here, but that'll have to be the object of another blog post altogether. ↩2

  5. I'd use "input" as the past participle of the verb "to input", just like I'd use "(broad)cast" over "(broad)casted", but the few authoritative dictionaries I consult, and the one linguist whose influence is greatest on my English nowadays, are definitely aligned on the idea that linguistics is descriptive rather than prescriptive—I went with "put in" to ruffle no feathers.

  6. Its main achievement is in ensuring you're using passwords you remember, and that very principle is indeed becoming antiquated quite fast. It's not that keeping your password nowhere but in your head isn't safe—that'd be safe alright, even you are subject to losing access—it's that this practice encourages reusing passwords, or perhaps familiar patterns in designing them: the very fact there's a design to your passwords is the vulnerability.
    Although, come to think of it, diceware passphrases are indeed quite a good idea, and not too much of a chore to either remember or type. Maybe the obsolescence is obsolete. What goes around comes around!

Referenced tools