If your inclination is to combine streams every time you need to ensure that 
event ordering is maintained, you could end up with a lot of streams being 
combined, and thus a traditional event queue.  Next thing you know, you might 
want to be able to inject application-created events into that queue, just to 
preserve ordering of something else relative to the incoming events.  If the 
system won’t let you add to the main event queue, you might create your own 
queue in your application (or supporting library) just to be able to mix system 
events with your own events.  Then you end up with a lot of event types, and 
switch statements in dispatching code (like Qt has a good number of, for 
example), and the extra queuing creates delays.  So now and then I take to 
pondering, what could be more elegant if that pattern is to be avoided?

One cause of the ordering problem is that separate processes handle incoming 
events from their respective devices, right?  e.g. kbdfs is independent, so you 
can’t be sure that if you are trying to read from multiple devices, that you 
will get the events in the same order that the user manipulates the devices.  
If there were just one process to handle all input devices (call it inputfs), I 
would think it could continue to serve up separate streams on separate files, 
and still enforce ordering as long as the read operation is blocking.  I.e. if 
you opened both the mouse and the keyboard, and a modifier is pressed, you need 
to read the keyboard file to get the changed modifiers before you are allowed 
to read the next mouse event.  Are there some bad deadlock cases with such an 
approach?  (I didn’t try, it’s just an idea.)

But input events should have timestamps anyway, generated as 
close-to-the-hardware as possible.  (e.g. in an interrupt handler?)  That could 
provide an alternative mechanism to reorder events, if there is no other way to 
guarantee that they will be emitted to the files in the correct order.  Then if 
you read events in the wrong order, at least you can detect that it’s in the 
wrong order, and it will be obvious how to fix that bug.

I don’t like the Plan 9 tendency to put space-separated sequences of data 
values in files.  The knowledge of what those fields mean is out-of-line, so 
you rely on your memory when reading it manually, and changing the schema is 
also hard.  csv at least has a header line to label the fields.  This is also 
why things like xml, json, messagepack and all the others were invented (mostly 
ugly) https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats .  
So now you wonder how to add keyboard modifier state to the mouse events, and 
are afraid to add another field, so you come up with hacks like higher-numbered 
mouse buttons or extra bits.  If the fields were labeled in the first place, 
somehow, it would be extensible.  But making every line into a dictionary is 
too verbose.  Well, maybe put the schema into a separate file then, and expect 
libraries to use it to populate their event structs?  If the struct is missing 
some fields that were added recently, then you are just missing the new info, 
but the new fields do not get in the way of populating the old struct.  If the 
struct has new fields that aren’t available in practice, use standard values to 
indicate that they are uninitialized (empty string, -1, NaN, ...).

Next evolutionary step is maybe to choose a binary format that is easily 
tokenized (maybe add a length to each field, so that arbitrary lengths are ok). 
 Maybe use small numbers for the field labels, and put the schema (table 
mapping the small numbers to their meanings) elsewhere.  (Maybe in the first 
record that you read from the file, as in csv.)  Probably some of the old 
standards already do it that way.  I once invented a format like that myself, 
for serializing arbitrary hierarchical data (like a binary XML) and compacting 
the element IDs into small numbers, but I suspect it’s redundant by now.  
Anyway, it’s a form of unaligned bytewise serialization.  So I figured I could 
do better.

Next improvement is to have a standard way to represent a vector in memory 
(including a length field), and make the event file provide those vectors in 
little-endian layout so that each event can be copied into process memory and 
used directly.  Eliminate deserialization and parsing completely.  The “schema” 
would just be another vector containing the field labels.  But then you need 
fixed field lengths, which creates limits (e.g. it could be a vector of 64-bit 
values, with NaN-boxing to distinguish types, leaving you 51 bits for all 
non-double types; if strings are supported as a type in a vector, then the 
labels in the “schema" can’t be longer than 6 ascii characters, or 8 6-bit 
characters, or 10 5-bit characters, or else strings have to be stored 
separately in a hash table or something).  If a mouse event comes in this form 
(a vector of doubles and ints), and you want to find the “x” value, you first 
search for “x” in the schema vector, which gives you the offset.  Every event 
from then on can be expected to have “x” at the same offset.  But a future 
version of inputfs is free to change the schema, without breaking applications. 
 Adding keyboard modifiers to the mouse events would be easy then (if you 
haven’t solved the event timing problem some other way).  To read it by hand on 
the command line, you need a different tool than cat or tail, but it can read 
all such binary-vector files, which ought to have many other uses.  That’s 
something I’m working on in a different context.

If files in /dev are going to change, we ought to make it future-proof this 
time.  Support all possible input devices, even those that haven’t been 
invented yet.  For now though, there’s multi-touch (touchscreens and 
touchpads), jog/shuttle controls and other kinds of encoders, joysticks, 
tablet/stylus, VR controllers, etc. Shoehorning all of that into hacks that fit 
the old schemas for keyboard and mouse would be really limiting (despite the 
excuses that are made about that).  They are different devices for a reason.  
In general, there could be many devices in use at the same time.  To me it 
seems natural to continue with separate streams for each, rather than 
interleaving the events in one file.

> On Oct 1, 2024, at 3:56 AM, o...@eigenstate.org wrote:
> 
> This is a problem that can happen with any keyboard input;
> if I press 'A' and click, this problem can also happen.
> 
> Fixing this would probably need merging both event streams
> into one /dev/input or similar.
> 
> Quoth Alyssa M via 9fans <9fans@9fans.net>:
>> If mouse click events are queued and the keyboard modifier state changes are 
>> not (or are queued separately), they can get out of step. By the time the 
>> program receives a mouse click event, the keyboard may be unshifted again. 
>> This could happen if a program is late processing mouse input.

------------------------------------------
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/T1dee2a7aea3f7fa3-M682112905f99c35a5eea9bce
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription

Reply via email to