TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Why Is It So Hard to Detect Keyup Events on Linux?

148 pointsby robertelderover 6 years ago

14 comments

cryptonectorover 6 years ago
I mean, that there&#x27;s no key up event in tty context goes back to the beginning of time, and is not Linux&#x27;s fault, and not even Unix&#x27;s (nor VMS&#x27;s) fault, or anyone&#x27;s fault, because this all works the way it does because of how terminals worked, and they worked the way they did because it was <i>simple</i>.<p>If, in the late 70s, key up events in tty context had been important, then terminal vendors would have developed an escape sequence system for expressing those. But it wasn&#x27;t, so they didn&#x27;t.<p>So, yes, it&#x27;s absolutely impossible to get key up events in tty context, and at this point it will almost certainly stay that way forever, as it&#x27;s too late to retrofit terminal emulators, drivers, and applications to understand whatever protocol for communicating key up events. (The right way to do this would be to develop an escape sequence protocol that the tty&#x2F;pty drivers could decode and turn events into out-of-band events to be delivered via ioctl()s, that way applications that don&#x27;t care about key up events don&#x27;t see them and don&#x27;t need to be modified. But who is going to do all that work?)
评论 #19015515 未加载
评论 #19012845 未加载
评论 #19014576 未加载
评论 #19028016 未加载
评论 #19012989 未加载
评论 #19012929 未加载
doogliusover 6 years ago
The OS is abstracting away details about where the characters come from, which is a keyboard in this case. The characters could also come from other sources, such as a file, or a speech-to-text program getting input from a microphone. Key-up events make no sense for these sources. Essentially, the author wants to go down a layer of abstraction to use his keyboard not as a character input device but as a grid of buttons. By default, this will require special permissions on most linux distros (and rightly so, as it allows for keylogging), but this is a matter of changing one&#x27;s udev configuration; root is not inherently required.<p>In any case, the stated goal &quot;to remotely navigate a robot over an SSH connection using the &#x27;w&#x27;, &#x27;a&#x27;, &#x27;s&#x27;, &#x27;d&#x27; keys&quot; is misguided to begin with; what happens when your connection drops and the robot can&#x27;t be stopped?<p>Addendum: has the author thought about the case where the user is using a keyboard layout where the WASD keys are not together, or where the user is using a non-latin-alphabet keyboard? As someone who uses a dvorak-based layout, I am annoyed at how often developers screw the key&#x2F;character distinction up and assume everyone uses qwerty.
egwynnover 6 years ago
The terminal is the wrong tool for this job. I believe the author realizes this in their exploration of the topic, but I think it still bears saying explicitly. This task is difficult not because of some big design mess-up, but because this use-case is well outside the design constraints of the technology he turned to first.<p>EDIT: I’d also like to mention that “Linux” has nothing to do with this. One would face the same issues using a Windows SSH client connecting to a Solaris SSH server.
评论 #19012802 未加载
评论 #19013983 未加载
vesinisaover 6 years ago
That raw keyboard events are not delivered through SSH connection is entirely expected. At its core, it is a text-only communication protocol. At the discretion of the client terminal, there could be an ANSI escape to enter mode where raw key events are delivered, akin to unbuffered input. But that is nevertheless beyond the scope of what SSH offers.
评论 #19012701 未加载
nerdponxover 6 years ago
This weirdly seems like the &quot;right&quot; implementation to me. Somehow I feel like a TTY generally doesn&#x27;t need or deserve to know when keys are pressed and released.<p>That said, is there a more end-to-end summary out there of how keyboard input is handled in GNU&#x2F;Linux? I have the vague understanding that USB HID scancodes are translated into keycodes, which are sent along to X applications or a TTY, but where and how each step happens is still a bit mysterious to me.
评论 #19012791 未加载
adontzover 6 years ago
ReadConsoleInput <a href="https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;console&#x2F;readconsoleinput" rel="nofollow">https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;console&#x2F;readconsole...</a><p>INPUT_RECORD <a href="https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;console&#x2F;input-record-str" rel="nofollow">https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;console&#x2F;input-recor...</a><p>KEY_EVENT_RECORD <a href="https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;console&#x2F;key-event-record-str" rel="nofollow">https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;console&#x2F;key-event-r...</a><p><pre><code> bKeyDown If the key is pressed, this member is TRUE. Otherwise, this member is FALSE (the key is released). </code></pre> Also, please note that INPUT_RECORD contains union of key, mouse, window buffer size, menu and focus event records. I do not want to say interface is more well thought per se, but it is definitely more rich.
评论 #19014633 未加载
gnachmanover 6 years ago
This is functionality that the terminal emulator reasonably should provide to enable games or other interactive applications. I believe that would solve the author&#x27;s complaints. Some work has been done along these lines in both Kitty and iTerm2. Not everyone likes the idea because it breaks the basic abstraction of a terminal. I kinda like it, though, and I&#x27;m optimistic that the situation will improve in the coming years.
jchwover 6 years ago
The title really should be &quot;On a TTY&quot; and not &quot;On Linux&quot; - the reality is, it&#x27;s not that hard. The TTY is a TTY - it&#x27;s designed for typing, not general input. You could always forward your input events through another channel, even over SSH if you wanted.
jesuslopover 6 years ago
IIRC &#x2F;dev&#x2F;input&#x2F;event* gives you that
solarkraftover 6 years ago
Meta:<p>I&#x27;ll again have to criticize this submission&#x27;s title. It shouldn&#x27;t be &quot; Why Is It So Hard to Detect Keyup Event on Linux?&quot; (it&#x27;s not a problem with the kernel), it should be something along the lines of &quot;Why can&#x27;t I detect key up events via SSH?&quot;.<p>And the answer to that is simple: That&#x27;s not what it&#x27;s designed for.<p>Or, even better: Instead of concentrating on the complaints part of the article provide on the part in which you&#x27;re providing value to your readers: &quot;Detecting keyboard events without a display server&quot; or, if you want to get in on the long headlines trend: &quot;Detecting key up events in a TTY environments is hard. Here are some ways&quot;.
评论 #19012986 未加载
评论 #19012972 未加载
AnthonBergover 6 years ago
Would it work if the sender immediately started sending a fast stream of repeating characters over? Then the keyup on the receiver is when the stream stops.
zwetanover 6 years ago
Very interesting, in a different context I had to tackle a pretty similar problem with Redtamarin [0]<p>Traditionally under the CLI you will manage key input wih a readline() command or something similar to kbhit() and depending on your needs you&#x27;ll use getchar() then track if either a CR or LF is entered for the &quot;end of command&quot;, also EOF.<p>This is blocking, so nothing else can happen, and depending on how you do it, you can only read single byte chars and not mutlibyte chars (like CJK input)<p>something like<p><pre><code> while( run ) { i=kbhit(); if( i != 0 ) { key = String.fromCharCode( getchar() ); if( (key == &quot;\n&quot;) || (key == &quot;\r&quot;) ) { run = false; } else { buffer += key; } i = 0; } } </code></pre> another way to do it<p><pre><code> while( run ) { b = fgetc( stdin ); if( b == EOF ) { if( kbuffer.length == 0 ) { return null; } run = false; } else if( b == LF ) { run = false; } else { kbuffer.writeByte( b ); } } </code></pre> which has 2 greats advantages, being able to read multiple bytes input (thanks to fgetc() which read the raw byte) and detect EOF (CTRL+D under POSIX, CTRL+Z under WIN32), but still blocking forever, using fgetc() the detection of EOF is done automatically for you (while getchar() getc() etc. do not detect that EOF)<p>now because Redtamarin is based on AVM2 and AS3, there is one part of the API which try to reimplement the Flash API with such things like KeyboardEvent that should be able to be non-blocking but still for a CLI environment<p>That KeyboardEvent should detect keyUp or keyDown but yeah it is hard to detect and if you try to do that for multipel platforms liek Windows &#x2F; macOS &#x2F; Linux it gets nigthmarish<p>In a little experiment [1] I found out you can do &quot;stupid things&quot; that actually work, like spawning a child worker (AVM2 uses pthread), blocking on the user input (like above) and then send back a message to your main worker and so receive a &quot;key event&quot;, all that allow to listen for input asynchronously<p>But then, what about making the difference between keyUp and keyDown ? I decided to ignore the keyUp because in fact it does not really matters on the CLI or I least I don&#x27;t see any use to it, for a GUI yes I can see the use cases, but for a CLI? not so much<p>Purely on the CLI (no X Server) you don&#x27;t really listen for key events you read the stdin stream, the only special events are signals like SIGINT SIGHUP etc. or special kind of signals like EOF.<p>The other things you can alterate is the buffering of that stdin and the raw mode&#x2F;cooked mode and echo off&#x2F;on.<p>So for a use case like navigating something using the &#x27;w&#x27;, &#x27;a&#x27;, &#x27;s&#x27;, &#x27;d&#x27; keys you just need to go async to listen for chars input (which key is pressed) and probably a mix of timeout on the last key pressed and a &quot;diff&quot; between the &quot;prev key&quot; and &quot;last key&quot;.<p>If last key pressed is &#x27;w&#x27; then go up, if you keep receiving a &#x27;w&#x27; key you keep going up, if prev key was &#x27;w&#x27; and the last key is different you change direction.<p>And to detect when to stop to go up if last key pressed was &#x27;w&#x27; you just keep the time when this key was pressed, if 1 second elapsed and no more key events are received you stop going up, ergo you don&#x27;t need to detect keyUp, but maybe I&#x27;m missing something.<p><pre><code> [0]: https:&#x2F;&#x2F;github.com&#x2F;Corsaair&#x2F;redtamarin [1]: https:&#x2F;&#x2F;twitter.com&#x2F;redtamarin&#x2F;status&#x2F;900794336031510530</code></pre>
zackmorrisover 6 years ago
This is quite possibly one of the best critiques of YAGNI that I&#x27;ve ever read.<p>I grew up in the waterfall (as opposed to agile) era of the 80s and 90s. Back then, it was top priority to catch mistakes as early in development as possible. This is the top article I could find on the concept, which seems to stir a lot of debate:<p><a href="https:&#x2F;&#x2F;developers.slashdot.org&#x2F;story&#x2F;03&#x2F;10&#x2F;21&#x2F;0141215&#x2F;software-defects---do-late-bugs-really-cost-more" rel="nofollow">https:&#x2F;&#x2F;developers.slashdot.org&#x2F;story&#x2F;03&#x2F;10&#x2F;21&#x2F;0141215&#x2F;softw...</a><p>The gist of it is that if a bug costs $1 to fix during development, it costs $10 to fix during testing and $100 to fix once it&#x27;s in production. Maybe someone can find the original quote.<p>Had I been working on terminals in the 70s, I would have been the annoying person in the back of the room who raised their hand and said &quot;what about key ups?&quot; There would have been a lot of muttering, much debate about how to store keymap bit arrays and what might happen if they get out of sync, every edge case would be explored, and in the end my opinion would be noted somewhere and character streams would have moved forward as the &quot;simpler&quot; implementation.<p>But it&#x27;s not simpler, because perfectly valid use cases were excluded. Basically, their decision meant that we couldn&#x27;t have video games in the terminal. Kind of a big deal, if you ask me.<p>After so many decades of this, it&#x27;s hard for me to drink the Kool-Aid on new frameworks, even if they&#x27;re ones we use every day like C++ (operator overloading was maybe a bad idea in hindsight), git (can&#x27;t store folders without .gitkeep), Angular (two way binding - oops), React (front end PHP), even HTML&#x2F;CSS&#x2F;Javascript (difficulty encoding our own tags as components&#x2F;nondetermistic inheritance across browsers&#x2F;mutability). These frameworks are great, but it takes a certain level of suspension of disbelief to buy into them.<p>Give me 5 minutes with any technology and I&#x27;ll find the conceptual flaws and bugs that impose major hurdles on its conceptual simplicity, utility and reusability. Basically everything I touch breaks. It&#x27;s like a knack that makes me a good programmer, but also a Debbie Downer.<p><a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MZF6EK7x4Dk" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MZF6EK7x4Dk</a><p>P.S. The workaround for the keyup thing is probably to set the key repeat threshold and repeat delays to 0 and check for repeated keydown events each main loop, setting the keymap entry to true if the key is still down (false otherwise). It&#x27;s not perfect because it can&#x27;t easily detect multiple keys down or modifier keys, but that was one of the ways we did it in classic Mac OS anyway.
评论 #19014661 未加载
评论 #19015010 未加载
评论 #19013736 未加载
评论 #19015118 未加载
shmerlover 6 years ago
What about Wayland?
评论 #19012871 未加载