Skip to content

text-input: Reword the interpretation of serials to be more specific

Here's a long story. The serial is formerly described as:

When the client receives a done event with a serial different than the
number of past commit requests, it must proceed as normal, except it
should not change the current state of the zwp_text_input_v3 object.

Upon first reading it might be obvious to interpret "proceed as normal" as "apply the changes made by the done event" and "not change the current state" as "do not make requests on it until serial matches with expectations again". This would turn the serial into a flow control mechanism to avoid pushing state changes that we know might be stale.

GTK however makes another outlandish interpretation, where "proceed as normal" means "ignore the changes made by the done event" and "not change state of the zwp_text_input_v3 object" is "not change client state". This makes the serial a full synchronization mechanism where IM commands that are deemed out of sync are symply ignored.

This would seem a misinterpretation of the protocol, and I proceeded to change the behavior in GTK. Then some deja vu feeling struck me and I found https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/384#note_344864, this change was already done and discussed in the past. Not just that, GTK behavior is the right interpretation.

However, there's some notable disadvantages, there's 2 easy ways to completely break the synchronization between compositor and client: Having the IM push new state too often (i.e. multiple consecutive .done events), or having the client .commit too often. If any of both peers gets ahead of the other slightly, the end result is ignored input. More specifically, IBus has no provision for this kind of transactional behavior (probably other IMs too), so implementing "emit .done once after a set of changes" is not quite possible.

Arguably, ignoring IM input is also a bad thing. IMs expect all commands to be respected and applied in order and might even rely on that in their own internal state. Since only state changes are flushed on .done events, partially ignoring IM commands will end up with the client IM state out of sync.

The usecase described at that GNOME gitlab comment (edited text changes happening in parallel to IM interaction) trades the handling of an inherently racy corner case with the worst kind of mishandling (ignoring user input) if IM/client don't perfectly sync up.

On the other hand, the flow control approach is more lenient with IMs and clients "getting a step ahead", and more importantly does not punish the user whenever either IM/client happens to do that. Double down on this (already intuitively correct) description, and specify further what it implies.

Edited by Carlos Garnacho

Merge request reports