[HN Gopher] Why Is It So Hard to Detect Keyup Event on Linux?
___________________________________________________________________
Why Is It So Hard to Detect Keyup Event on Linux?
Author : EntICOnc
Score : 141 points
Date : 2021-05-16 07:59 UTC (1 days ago)
(HTM) web link (blog.robertelder.org)
(TXT) w3m dump (blog.robertelder.org)
| leoc wrote:
| Seeing this near the top of HN is a bit like seeing a "Why Does
| Italian Have All These Screwy Verb Endings?" post near the top of
| a web forum for professional students of linguistics ...
| munchbunny wrote:
| What's obvious to you might not be obvious to everyone. I've
| only heard reference to the issue previously but never looked
| at a detailed discussion, mostly out of not caring because I've
| never had to do something that depended on detecting keyup
| events in Linux in a non-browser context.
| ajkjk wrote:
| Really? There is almost no information in this article that I
| have ever heard before, and I imagine that I'm a pretty typical
| reader of this forum. You might have have a very mis-calibrated
| model of HN readers.
| teknopaul wrote:
| This is silly, you can't detect key up or keyb down in a tty, you
| detect what the terminal emulator gives you: chars and Esc
| sequences.
|
| It's as sane as asking why you can detect joystick movements or
| the kettle boiling.
|
| It bothers me how little people understand about the terminal and
| "the command line", despite using it everyday.
|
| If people read man bash from top to bottom they would probably
| get a feel for what is going on. Learn how changing the title of
| your tty works and there is not much left to _not_ understand.
| memoblobi wrote:
| Because they are serial character devices?
| alkonaut wrote:
| Detecting keyup only in a window env seems like a perfectly good
| place to be. The problem there might be that there is no such
| thing as a "desktop linux" so writing a nice cross platform
| desktop app for any Linux regardless of window manager and
| desktop env I assume is a bit of a black art.
| josefx wrote:
| The X11 example only has a basic event loop with a check if the
| if the key up event was repeated. Everything else is setting up
| the window and tearing it down on close. That should work in
| any window manager.
|
| Most of the examples are either global listeners or outside of
| a window environment.
| lfmunoz4 wrote:
| Can't someone just modify the keyboard linux driver to detect key
| press events?
| akmittal wrote:
| All the applications getting keyup events seems like big security
| issue.
|
| Is this same case with Wayland
| yw3410 wrote:
| Is what the same as Wayland? Maybe you've misunderstood the
| article?
|
| The process is running as root and reading directly from /proc;
| the article acknowledges that it's essentially a keylogger.
| chaorace wrote:
| I _am_ now curious, though. How does Wayland handle key
| events? I have to imagine it only lets the active window
| listen in on key events, right? Maybe there 's an API for
| subsribing to specific key combinations?
| ashafer wrote:
| iirc it's pretty much completely up to the compositor. The
| spec is worded to allow "focus" to enter a surface and
| deliver events to it, but it never specifies under what
| conditions the compositor should do so.
|
| So the compositor chooses what surface to deliver events to
| based on its own desires (like letting pointer focus enter
| background apps) and the users input. I think there is a
| protocol (used by Xwayland?) to allow a client to get
| events from any window if the compositor/user allows it
| Cloudef wrote:
| That's how it is. It's up to compositor to decide what
| events to send to what clients. Usually this means
| compositor only forwards input events to the focused
| surface.
| chrisseaton wrote:
| > Maybe there's an API for subsribing to specific key
| combinations?
|
| Why would you ever let a non-focused application subscribe
| to any key combinations?
| pdkl95 wrote:
| I am currently writing a utility to spy on Super
| Hexagon's KeyPress/KeyRelease XEvents with the goal of
| recording very precise timestamps for each event. Since
| the walls in the game arrive at a constant rate, I want
| to graph my keypress/keyrelease events modulo the time
| between walls.
|
| My success rate for finishing Hyper Hexagonest[1] is
| falling; being able to inspect recent attempts might
| reveal where my timing is drifting.
|
| (it's only ~25%-ish finished, unfortunately)
|
| [1] https://www.youtube.com/watch?v=JJ96olZr8DE
| reificator wrote:
| > _Why would you ever let a non-focused application
| subscribe to any key combinations?_
|
| * Media playback controls
|
| * Hotkeys to take screnshots, or record videos
|
| * Quake style terminals
|
| * Ingame chat and game invites
|
| * Color pickers
|
| * Screen controls like F.lux
|
| * Window management hotkeys
|
| * Push-to-Talk in group voice calls
|
| And that's just what I personally use on my own machine.
|
| It's a massive security issue that any installed software
| can listen to any input activity or view/affect other
| windows, and that does need to be reigned in. But to
| claim that there's no legitimate utility to global
| hotkeys is absurd. We need robust permissions, not a
| completely crippled experience.
| topaz0 wrote:
| In my experience most of these use cases are handled on
| linux by the window manager calling a script that sends a
| message to the relevant application, e.g. over dbus.
| michaelmrose wrote:
| Some applications prefer to provide a ui for the user to
| configure a hotkey. This is naturally discoverable within
| the scope of the other settings in its preferences
| screen.
|
| Providing a cli interface for automation or binding a
| hotkey is imo more powerful and useful but its not
| discoverable. Doubly so for a controlling it over dbus.
|
| The logical thing is that since there is a substantial
| use case and a desire to limit applications access to
| global info is that a permission system ought to have
| been built into Wayland such that applications could
| request not only global access to the keyboard but
| permission to get a notification when a particular key
| press happened.
|
| Since this feature was a staple of desktop operating
| systems for decades it ought to have been part of the
| plan from the start.
| zxzax wrote:
| People have been asking for similar grab-type things
| since early on in Wayland, and there have been many
| proposals, but nobody has actually stepped forward to
| build such a permission system that would work everywhere
| and would not create additional security problems or
| would not severely overcomplicate things. It's not a
| simple thing to do, by any means. If you think you know
| how, I would urge you to get started designing it and
| contributing it to some of the major Wayland
| implementations.
| michaelmrose wrote:
| I don't really want to be in the business of growing
| wheat or baking bread if what I actually want is a
| sandwich but I will happily explain why ___ sandwich
| shack is doing it wrong because Monday morning
| quarterbacking is more fun.
| zxzax wrote:
| I get that, but everyone else also seems to have that
| attitude, so you see why it doesn't really get done when
| nobody has any wheat or bread :)
| reificator wrote:
| Sure, and that works fine. Just let my application tell
| the window manager:
|
| * What key events I care about. (I.E. what the keybind
| should be named in the settings UI)
|
| * What script or message to pass back to me when that
| event is activated.
|
| * What the default keycombo should be, if any.
| icedchai wrote:
| It doesn't even need to be installed. Back in the 90's,
| some Unix workstations shipped with X11 security disabled
| by default. Your keyboard could be sniffed just by
| plugging into the network. Fun times.
| tjalfi wrote:
| PureText[0] is a Windows application I use regularly. It
| adds a keyboard shortcut for pasting as plain text.
|
| [0] https://stevemiller.net/puretext/
| pjc50 wrote:
| https://docs.microsoft.com/en-
| us/windows/win32/api/winuser/n... : for global hotkeys.
| [deleted]
| chrisseaton wrote:
| That doesn't seem like something that an application
| should be getting involved with. An application should
| only be able to manage its own windows and key presses to
| its own window.
| R0b0t1 wrote:
| Problematic. Means you are relying on the DE for all UI
| development. With Windows and X11 the DE is
| reconfigurable to some extent by applications.
|
| There is also more to this, showing the Wayland security
| model is incoherent. If debugging is enabled on your
| system I can simply debug your root terminal and start
| injecting commands into memory.
| zxzax wrote:
| Wayland obviously cannot solve all security issues and
| privilege escalations in the underlying OS -- the
| solution to that problem would be to just disable
| debugging within that security context.
|
| In Wayland the situation is also not so much different
| from Windows, you would just reconfigure and extend the
| DE itself. You are already relying on them to provide
| most of the UI to an extent.
| R0b0t1 wrote:
| In regards to your first point, I am saying that Wayland
| does not do what it sets out to do and the proper way of
| doing it is a much larger problem than what Wayland can
| address. It is possibly better to avoid breaking
| everyone's stuff if you're just going to need to shortly
| do it again to fix the things Wayland does not and can
| not fix.
|
| For your latter point, Wayland is much different. In
| Windows there are ways to inject behavior into other
| programs or the UI elements. This exists so you can
| change the UI. Wayland's idea of security is very much
| against that, at least in the way it can be done on
| Windows/X11.
| zxzax wrote:
| I don't know what you mean you'll need to break it again,
| this one particular hole is already plugged in Wayland.
| That won't cause additional breakage, and you'll still
| want to be plugging those additional holes like ptrace
| anyway.
|
| Input injection is being worked on in a different
| library, that brings a standard API that's supposed to
| work the same across Wayland, X11, and with sandboxed
| contexts: https://gitlab.freedesktop.org/libinput/libei
| reificator wrote:
| So if I'm in my text editor and decide I want to change
| the currently playing song, I need to switch
| windows/contexts, press a hotkey or GUI button, and
| switch back?
|
| The current model where everything running can listen to
| everything you do is not acceptable, but that doesn't
| mean there's no usecases that strongly benefit from
| global hotkeys.
| chrisseaton wrote:
| > So if I'm in my text editor and decide I want to change
| the currently playing song, I need to switch
| windows/contexts, press a hotkey or GUI button, and
| switch back?
|
| Looks to me like something the DE should manage for you,
| not the application.
|
| But everyone seems to disagree with me!
| michaelmrose wrote:
| Probably because nobody on earth wants what would be the
| convenient design to dictate how they use something.
| TeMPOraL wrote:
| But how do you teach your DE to do new things for you?
| And what is your DE in the first place?
|
| The answer to both these questions is: _an application_.
| Think of applications hooking into global shortcuts as
| plugins for your DE.
| reificator wrote:
| > _Looks to me like something the DE should manage for
| you, not the application._
|
| > _But everyone seems to disagree with me!_
|
| The original post you responded to was suggesting that
| your DE, or at least something outside of your
| application, provide an API to register specific global
| hotkeys that you can listen for. In response, you said:
|
| > _Why would you ever let a non-focused application
| subscribe to any key combinations?_
|
| So to me when reading this thread, it looks like you're
| the one disagreeing with this idea. This is the first
| post of yours I've seen where you suggest this, and the
| thread begins with you shooting down the entire concept
| as ridiculous.
|
| Unless you're suggesting that the DE comes with a
| preconfigured set of global hotkeys and cannot be altered
| or extended, nor handled differently by different
| applications. In which case yes, I strongly disagree with
| that.
|
| There's a reasonable middleground between a free-for-all
| and nothing but what the DE already thought of, and
| that's a well-defined API boundary alongside per-
| application, per-feature permissions. Bonus points if the
| DE handles all key-combination assignment in a consistent
| UI and applications can only register a suggested
| keycombo, a context for when the hotkey should be
| activated, and a function to respond to the event.
| chrisseaton wrote:
| > Unless you're suggesting that the DE comes with a
| preconfigured set of global hotkeys and cannot be altered
| or extended
|
| Yes that's what I'm suggesting. Works fine for almost all
| use-cases like on macOS.
|
| I guess it's just not a popular opinion lol!
| reificator wrote:
| I did edit the post you responsed to a few times in the
| last few minutes, so heads up there.
|
| > > _Unless you 're suggesting that the DE comes with a
| preconfigured set of global hotkeys and cannot be altered
| or extended_
|
| > _Yes that 's what I'm suggesting._
|
| Okay, let's use the example of music playback. If your DE
| handles music playback controls, how does it tell the
| music player when to stop and start, or skip to next
| track?
|
| Does it hardcode a list of music players, each of which
| provides its own bespoke API, and the DE calls into the
| application?
|
| Or does it provide a way for any music player to call
| into the DE, and listen for those play/pause/skip events?
|
| And if it does that, then why are the list of events
| hardcoded? Why not allow the music player to say "I also
| play podcasts, and I want to provide a hotkey to speed
| up/slow down the playback speed, or provide a separate
| hotkey to skip ahead 30 seconds that's distinct from
| skipping the entire episode."? Why not allow Discord to
| provide a push-to-talk hotkey so that people on a group
| call can actually hear each other without dogs barking
| and keys clacking and people coughing?
|
| ---
|
| Look at the VSCode Extension API for instance:
|
| * Extensions are at least partially isolated from the
| main process and each other. I don't know how far this
| goes or how secure, but for our purposes they could be as
| isolated as you want.
|
| * They can register a command which when activated,
| performs some action from within the extension.
|
| * Those commands show up in the command list at the top
| of the screen when you hit "Control + Shift + P" (which
| is itself a command subject to all the same rules) and
| users can select whichever command they want to run.
|
| * Those commands can also be assigned to a hotkey.
|
| * Extensions can suggest a default binding for this
| hotkey, but users can go into the VSCode settings page
| and assign whatever keycombo they desire.
|
| * Users can remove keybindings for commands that have
| them by default.
|
| * Users can assign keybindings to commands that don't
| have them by default.
|
| * All keybind editing is performed through the same UI,
| which is owned by VSCode and not the extension.
|
| * VSCode itself is the thing listening to those key
| events, and it calls into the extension to activate it.
|
| * There is a concept of context for when these keybinds
| apply, such as when a markdown document is active in the
| editor. Extensions provide these contexts by default and
| users can override them as they choose.
|
| * Extensions themselves don't even start up until an
| activation event is met. These can be opening a file of a
| certain language, running a command, etc...
|
| What about this model is objectionable in your mind? Who
| benefits from the lockdown you propose where no new ideas
| can be tried until the DE authority deigns to allow it?
| zxzax wrote:
| All of your concerns regarding music players are actually
| already addressed by the MPRIS spec:
| https://specifications.freedesktop.org/mpris-spec/latest/
|
| This problem has been solved in the DEs for quite some
| time now, global hotkeys is probably the very last thing
| you want to reach for, when all other options are
| exhausted.
|
| And when that happens, I don't know about other DEs, but
| the way you're describing with extensions is mostly how
| GNOME Wayland already works. If you want to intercept a
| key, you ship an extension for that, and display a UI to
| rebind the keys, or you can place additional entries in
| the system's keyboard settings panel. What you can't do
| is have random unprivileged processes intercept keys
| without the user's permission.
| eropple wrote:
| I've had custom global hotkeys for stuff in MacOS for
| over a decade.
| chrisseaton wrote:
| But that's not how things like playback controls are
| implemented - they have non-extensible separate APIs for
| that. That's the point.
| eropple wrote:
| You've also been given a raft of other functions that
| depend on them in this thread.
|
| I'm not sure what your hangup here actually is.
| zxzax wrote:
| IME, most of those functions tend to get implemented in
| the DE when it turns out they're actually useful, or some
| other mechanism can be used to activate them. So no
| reason to get hung up on that particular method to do it
| either.
| TeMPOraL wrote:
| Depends on an application. Plenty of applications have a
| legitimate reason to hook into global keyboard handlers,
| or otherwise instrument other applications or the system
| itself. Removing that capability would be crippling to
| the utility of a computer.
|
| It sort of works in the mobile space (+/- accessibility
| services, which are the way to get that functionality if
| you need it), but that's only because mobile devices are
| consumption-oriented; there's only so much you can do
| with them, and they eschew utility in order to streamline
| you into being monetized by third-party services.
| simion314 wrote:
| Not all applications need to be a classic "windowed
| application".
|
| I know this is a rare use case, but the DE and the app
| need to work togheter to allow global shortcuts. I for
| example have a keyboard with many useless media keys ,
| that I configured to run some specific scripts and some I
| could very easy set them up as Global shortcuts for some
| KDE apps. Not sure if other DEs would offer to setup
| global shortcuts for you.
|
| Probably something most users will use is screen
| recordings and screen readers , this applications need to
| have global shortcuts(and access to the screen and window
| elements)
| yjftsjthsd-h wrote:
| In order to implement
| https://www.semicomplete.com/projects/keynav/ (or
| anything else that listens for a specific key combo to
| activate)
| chrisseaton wrote:
| Isn't that kind of thing the responsibility of the
| desktop environment service? Not an application?
| yjftsjthsd-h wrote:
| I suppose the proper answer is that that very much
| depends on your philosophy of desktop environments; I
| happen to prefer modular desktops built out of separate
| programs from separate authors which may or may not even
| know about each other. This has the advantage of making
| it trivial to retrofit new features without needing to
| ask your DE upstream. Or to be more pithy: Okay, fine;
| what desktop environments implement keynav? With X11, I
| can make the answer be "(probably) all of them".
| riskable wrote:
| As long as the desktop environment provides a mechanism
| for applications to register their global shortcuts then
| all is well. However, without such a feature the
| application has to just listen for all keystrokes and
| check if it matches something the user's configured.
|
| Example: I've bound several scenes in OBS to keyboard
| shortcuts so that I can switch scenes no matter what
| application I'm in. I'm pretty sure OBS does this by
| listening to all keyboard events on the root window. It's
| not very efficient, but it works.
|
| Now imagine having to support a global shortcut daemon
| per DE that exists. I suppose _someone_ would write an
| abstraction but really, it 's something that
| FreeDesktop.org should provide (if it already doesn't).
| jeroenhd wrote:
| WorkRave can't function well without it. Currently, it's
| working through a compatibility layer I think, but if
| that breaks, the application can't be made to work on
| Wayland AFAIK.
|
| Alternative shortcut managers might also run into trouble
| (say, clipboard managers with customizable shortcuts)
| although those could work with a simple permission prompt
| for each new shortcut. Very annoying and obtrusive to the
| user, but the security principles remain.
|
| There are also tools that extend some window managers
| with i3-like shortcuts and configurations; the config
| files are parsed on the fly and they need to work in the
| background.
|
| Then there's tools like AutoHotkey that can be great
| tools for productivity through scripting and custom
| shortcuts. A lot of AH's functionality can be replicated
| using the standard hotkey API, but not everything.
|
| There's also diagnostic tools (see Windows Steps
| Recorder) that record all keystrokes and generate a step
| by step report about what happened with screenshots as a
| guide.
|
| IMO global key capture should still be possible with the
| right capabilities set because there are valid use cases
| for it. Requiring additional permissions is fine IMO, but
| completely removing the option to do this is a pain.
| joaonmatos wrote:
| Global Hotkeys for something like Quake terminal, or
| voice chat push-to-talk. Obviously I don't see why you
| would encumber the core protocol for it, but a
| subscription model for it as a wlroots or FreeDesktop
| portal could be interesting.
| pengaru wrote:
| Userspace doesn't implement debouncing in linux, that's driver
| territory; linux isn't an rtos. It's unclear why this is even
| mentioned at all.
|
| And you don't need root if your program's user is in the input
| group on most distros. You're opening a device node in
| /dev/input/XXX, the standard UNIX permissions model applies...
| zozbot234 wrote:
| > And you don't need root if your program's user is in the
| input group on most distros.
|
| It's complicated. Being in the input group is part of it, but
| to actually get the access you need to interface with the
| freedesktop-derived multiseat stack, which is as clunky as
| everything else that comes from the fd.o folks.
| klodolph wrote:
| Yes, I think the article's description of getch() as being
| inadequate due to a lack of debouncing is a bit weird. I would
| think that debouncing would be done even earlier, in the
| keyboard itself, since the debouncing you need is necessarily
| specific to the actual hardware. While USB HID keyboards are
| state-based (they transmit a packet listing which keys are
| pressed), the PS/2 protocol is event-based, and transmits
| "make" and "break" messages for key-press and key-release
| events, respectively.
|
| (That said, I wouldn't be surprised if debouncing were done in
| the driver. I just think it's the wrong place for it.)
| pengaru wrote:
| I suspect the author may have some experience implementing
| ad-hoc buttons via GPIO polling from userspace, and maybe
| used getch() in doing so.
| klodolph wrote:
| The thing about getch() is that there's not really one
| standard getch(). There's a Windows version of getch()
| which is compatible with, notably, Borland's version for
| DOS (I think), and then various people have reimplemented
| getch() for other systems.
| pengaru wrote:
| They might have meant to write getc() or getchar()...
| klodolph wrote:
| That would make no sense at all. I think the comparison
| to getch() is the natural one here.
| pengaru wrote:
| I suppose, from the linux perspective going through
| curses for this use case, in the same sentence mentioning
| "debouncing" seems awkward, but it does at least provide
| a polling api. Honestly I have no idea what they're
| talking about there.
| dec0dedab0de wrote:
| This might be a dumb question, but why would I want to detect a
| Keyup event in the first place?
| silon42 wrote:
| To properly implement something like Ctrl+Tab for switching
| between tabs (assuming application has such a concept).
| dragontamer wrote:
| Lets say you're porting a fighting game, such as Blazblue, to
| Linux.
|
| Carl Clover (Blazblue character) attacks on keydown, while
| Carl's doll attacks on key-up. Expert players change the
| rhythms of their key-down / key-up to make combos possible.
|
| In general, these kinds of fighting game characters are called
| 'Negative Edge' characters. There's a large number of them in
| many different fighting games. I know its present in Street
| Fighter, Marvel vs Capcom, Mortal Kombat, and Injustice. Even
| SSB:U (Shield-release / perfect shields) is a negative-edge
| event, showing just how common negative-edges have become in
| modern games.
|
| I personally am only really good at Blazblue: and thus, I know
| that Carl Clover, and to a lesser extent Taokaka and Lichi are
| negative-edge characters. Its an entire "character design"
| philosophy, to make certain characters feel much different from
| others. But its all over the place.
|
| ----------
|
| I HATE playing negative edge characters. If I realize a
| character has negative-edges, I run the heck away from them.
| Nonetheless, I accept that fighting games are fun because
| there's "always a character" that matches someone's
| personality.
|
| If someone else has fun playing negative edge characters, I
| want to welcome them into the community, and therefore want to
| support negative-edge gameplay into a game. Its not about "me",
| its about "the community of players".
| theon144 wrote:
| The problem isn't Linux, but the terminal environment...
| dragontamer wrote:
| Then lets say a hypothetical terminal video game that acts
| on negative-edges.
|
| My point: negative-edge gameplay is common in fighting
| games (and maybe other video games). Its reasonable to
| expect that a video game designer would use that technique.
|
| I've played terminal action games before. Lets say you're
| programming one and have some useful function mapped to the
| negative edge. How do you implement that in the terminal?
|
| --------
|
| Megaman's charge shot (and most "charge shot" video games,
| including Samus / Metroid, Rocket Knight Adventures, etc.
| etc.)
|
| Maybe those platformers are more common? Either way, the
| negative-edge is all over video games, its a good control
| scheme.
| zokier wrote:
| As you have discovered, terminal is not really an good
| environment for games. Its really just that simple. If
| you pick terminal as your platform, you are intentionally
| picking a limited platform, and working within those
| limits is then kinda the point. Having poor input
| handling is part of those limits. If you just want to
| make a good game, then just use Wayland (or X11) instead
| or some wrapper of those.
| dragontamer wrote:
| The Linux terminal is not a good environment for that.
|
| The Windows terminal supports key-up events... as long as
| I can remember anyway. I think a number of Windows
| programmers who are looking at Linux's command-line API
| wonder why its so hard to get something that's common in
| Windows.
| zekica wrote:
| You can interface with input devices directly if you want
| that. The output can still be in an VT10x terminal, or it
| can be directly in a framebuffer if you want software
| rendered graphics. Or better yet! X11 or Wayland.
| recursive wrote:
| Or even simpler. Let's say you're porting a side scrolling
| old school Mario-type game. When you release the "move right"
| key, the guy stops moving right.
| dragontamer wrote:
| Lol. KISS bites me again.
| klyrs wrote:
| Simplicity is boring. Thanks for writing that comment. I
| learned something new about games I've only played
| casually (by which I mean, button-mashing)
| dragontamer wrote:
| For Blazblue specifically, I'm not a Carl player
| (ugggh... negative edges). But just remember: whenever
| the doll is attacking, it reacted to the player LETTING
| GO of a button (key-up).
|
| All of Carl's moves himself are on key-down.
|
| So think of what your fingers must do to consistently
| pull off combos like: https://youtu.be/D8gPPB9YD6s?t=65
|
| You get the benefit of playing two-characters vs the
| opponent's one character, but it means having to think
| about both characters (as well as having a wonky control
| scheme for the 2nd character). Furthermore, Carl is
| designed to play with the doll, so you only deal the same
| damage as everyone else if you successfully pull off
| these combos.
|
| But having two-characters means you can setup
| unblockables more easily (doll hits high, Carl hits low),
| or weird pressure strings / frame traps that are
| unavailable to most typical characters. Which is where
| Carl's unique advantage really comes in. So its not a
| "damage" thing, its more about the mind-games you play
| with the opponent when its 2vs1.
|
| Terminology: A, B, C, and D are the four attack buttons
| in the game. Numbers represent which direction you push
| (2A means A-button while holding "Down". 2 is down on the
| numpad. 8 is up, 6 is right, 4 is left). Every fighting
| game community has invented their own terminology. But
| knowing this should give you enough information to watch
| that combo-tutorial adequately.
|
| A, B, C map to Carl, D maps to the doll. Holding D means
| that the doll starts to move left-right (4 or 6 with your
| left hand), letting go of D means that the doll attacks
| (negative edging). A, B, and C on Carl play as a typical
| fighting game character.
|
| Carl is... not easy... to play.
| theon144 wrote:
| RTFA
|
| >In my case, the goal was to remotely navigate a robot over an
| SSH connection using the 'w', 'a', 's', 'd' keys. Real-time
| tasks like this require extremely high responsiveness to key
| events for palatable performance.
|
| Yeah, I don't think a SSH connection is the right tool either,
| but there's the answer (and basically the entire article
| follows from that).
| fl0wenol wrote:
| In retrospect, thinking about the end problem, he really
| should have written a custom front-end that used SSH (or TLS)
| and a custom protocol to remotely send input and receive
| telemetry, as most term emus don't support this kind of
| behavior. It could still be a TUI, but it'd be local and use
| evdev. What'd be nice is then you could actually use a
| joystick if you had one ^_^
| pcwalton wrote:
| > So, what do you do when you want to send 'key release' events
| over SSH when the target machine doesn't have an X server? Well,
| you have to build your own client/server application where a
| client/server listens locally on the machine with the keyboard,
| and then forwards these events to the remote machine where you're
| running the applications that needs to respond to these events.
| That sounds like a lot of work because you have to set up all the
| sockets and custom messaging protocols, but there's no way around
| it because the key release events simply aren't forwarded over
| your terminal-based SSH session when there is no X server
| forwarding configured.
|
| This isn't that much work if you write it as a trivial Web app
| using WebSockets. Then you can leverage the browser's OS
| abstraction layer instead of having to write your own.
| [deleted]
| pjc50 wrote:
| > A tty doesn't know about the concept of key press or key
| release events. It only knows about 'data stream in' and 'data
| stream out'.
|
| This is basically the long and the short of it; it's a very old
| API, and retrofitting key-up detection reliably is a serious
| problem.
| drran wrote:
| To fix this low level problem, someone will need to modify
| xterm, or libvte, or any other terminal, to send escape
| sequences for key release events, when such mode is requested
| by an application.
| patrec wrote:
| Already done. Kitty and other modern terminals have an
| extended keyboard interface which allows to detect keypress,
| keyrelase and arbitrary key combinations (unlike legacy
| vt100-style terminal emulators, where e.g. Tab and Ctrl-I are
| indistinguishable). For backwards compatibility you need to
| switch to this mode by sending an escape sequence.
|
| https://sw.kovidgoyal.net/kitty/keyboard-protocol.html
| eikenberry wrote:
| > and other modern terminals
|
| Do you know of any source documenting which terminal
| emulators support this feature other than kitty?
| CoastalCoder wrote:
| Perhaps this is nitpicking, but I don't think the issue here is
| "data stream" vs. not-"data stream".
|
| Perhaps a better distinction is "data stream of characters" vs.
| "data stream that can express key events (and perhaps other
| stuff as well)".
| swiley wrote:
| This is correct, plan9 continues using a data stream but puts
| events in the data stream rather than characters.
|
| Even on Linux the low level kernel API for getting keypress
| events works this way.
| icedchai wrote:
| It's really a lower level protocol issue. The serial
| terminals upon which the "tty" model is based had no event
| stream outside of characters being sent or received. There
| are events provided by the serial port itself and delivered
| out-of-band though (example: modem DCD line drops, SIGHUP is
| generated.)
| GuB-42 wrote:
| Small nitpick, if you use WASD for control, it may be better to
| use the keycodes and not the characters. People with non-QWERTY
| layouts probably want to use whatever keys they have on this
| location (ex: ZQSD for AZERTY layout).
| marcodiego wrote:
| I don't think the article is fair. I'm not used to such lower
| level on linux, but it is certainly doable without root. SDL has
| been doing it for ages. Doing it from the terminal is another
| thing entirely since it was never designed for such kinds of
| events.
| thebeardisred wrote:
| I'm right there with you, but as someone who is used to the
| "lower levels" of Linux (to use your phrasing) this seems like
| the exploration of someone beginning to understand they were on
| the question side of an "X / Y problem"
| (https://xyproblem.info/).
|
| Put differently, they're making the transition from Linux as a
| commodity used to build the thing they're dreaming of to Linux
| as a critical design component.
|
| For example, he calls out in the beginning: > They are
| interested in performing some real-time based task that is
| controlled using keyboard presses. In my case, the goal was to
| remotely navigate a robot over an SSH connection using the 'w',
| 'a', 's', 'd' keys.
|
| As the author discovers, that's fundamentally not how SSH
| works. This sort of behavior could be achieved using other
| mechanisms, but it's not even really an issue of the tty/pty.
| They're just trying to map a functional model from a different
| operating system to Linux.
|
| As to the discussion of keyboard handling moves into Python
| code I would have again, gone a different path.
|
| When the author took a turn into Python my first thought was
| this is trivial for evdev to handle
| (https://en.m.wikipedia.org/wiki/Evdev / https://python-
| evdev.readthedocs.io/en/latest/).
|
| Next thing I know they touch on the kernel mechanisms managed
| by evdev.... And pivot across to X11 (which would seem to make
| sense until one realizes that the transition to Wayland from
| X11 is far further along than a layperson might imagine).
|
| In the end a good write up which shows a lot of "raw power" on
| the part of the author. With some additional tutilage,
| exploration, or guidance they to really take their
| understanding to the next level.
|
| For the folks who are in the weeds (like me) it is a good
| guided tour. Seeing into the "beginners mind" (and taking it to
| heart) can provide perspective as to how to make software more
| intuitive.
|
| (Typed and butchered from my phone).
| [deleted]
| riskable wrote:
| I could be wrong but I'm _pretty sure_ SDL just reads the
| keydown /keyup events it gets from the X server (that's why you
| don't need to choose a keyboard device when you use it). So
| without X running SDL wouldn't be able to grab keyboard events.
|
| It can grab joystick/gamepad events though since it reads those
| directly. In that case you have to enumerate then specify which
| gamepad/joystick device to use so it can open the correct /dev/
| path.
| BoppreH wrote:
| It can certainly be done by interfacing with the X server, but
| it limits you to systems with a running X server (e.g. no
| headless raspberry PI's, no Wayland).
|
| I have a planned change to use this a default, and fall back to
| /dev/input on non-X systems. It's not quite there yet,
| especially the capability of suppressing key events.
| BoppreH wrote:
| I'm the author of the `keyboard`[1] library mentioned in the
| article.
|
| - It reads all events because it's meant to interface with your
| keyboard directly, for global hotkeys, macros, disabling or
| remaping keys, etc. Interacting with windows and per-application
| hotkeys are explicitly not a goal of the library at the moment.
|
| - It reads /dev/input because the library was developed to work
| in as many environments as possible, including headless
| installations like raspberry pi's that may not have a graphical
| environment or even a monitor. There's an open change to _try_ to
| communicate with the X server first and fallback to /dev/input,
| but event suppression is not working reliably with this yet.
|
| - It could read /dev/input by just being in the `input` group,
| but then `dumpkeys` doesn't work and you are stuck typing numeric
| scan codes instead of key names.
|
| Due to a series of unfortunate personal circumstances I've been
| unable to give the proper maintenance the library requires, but
| the issues and thank yous have never stopped, and I'm slowly
| getting back to it again.
|
| ---
|
| Little known trick: if you run the library as a standalone module
| (`python -m keyboard`), it prints a JSON object for each detected
| event. You can save them to a file and pipe them back (`python -m
| keyboard < events.txt`) to replay them like a macro.
|
| Little known trick 2: I also created `mouse`[2], the companion
| library for my second favorite peripheral. It's the same thing,
| but for mouse events.
|
| [1]: https://github.com/boppreh/keyboard
|
| [2]: https://github.com/boppreh/mouse
| vanous wrote:
| Thank you very much for the library. Recently I have been
| learning touch typing and detecting system wise characters
| typed per day plus speed and acuracy is on my todo list. I
| already selected the keyboard module for this after some
| initial research.
| jorl17 wrote:
| Hi! I've used your library in various projects and am very
| grateful for it!
|
| I figured it'd be worth a shot to ask you this here, since I
| just caught you: have you considered adding some support for
| "rehooking"/"restarting" the library, so that callees can
| restart your library whenever they detect that their
| environment has changed (e.g. input devices have been
| (dis)connected, etc)?
|
| I've contributed with some info to this issue
| https://github.com/boppreh/keyboard/issues/264 as to how we're
| dealing with this in some of our projects. Funnily enough, I
| didn't know about `python -m keyboard`, and had I known about
| it, it would definitely have saved me some time!
|
| Once again, thank you very much for your hard work!
| BoppreH wrote:
| Thanks!
|
| I've been thinking about how to handle environment changes
| for a while, and it's pretty hard to reliably detect and
| respond to them in all supported systems.
|
| But I really like the idea of a manual "re-init" method as
| temporary measure. This should be trivial in Windows, and
| doable in Linux after some refactoring.
|
| Thanks for the idea, I'll take a look tomorrow.
| RickHull wrote:
| For those interested, I wrote a similar library for Ruby:
| https://github.com/rickhull/device_input
| ajross wrote:
| tl;dr: It's not about Linux, it's the terminal.
|
| Linux exposes your keyboards as /dev/inputN devices and (with the
| exception of oddball devices or drivers without the hardware
| capability to detect them) every single one of them presents
| clean down/up pairs on every press, every time. If you want to
| read the device state, read it from the kernel.
|
| The problem is that the author doesn't want to detect the device
| state. The author wants to write a program to run at the command
| line. And the command line is an environment descended from a
| long line of tty environments going back to the original
| teletypes of the 1960's. And those devices were never designed to
| expose a "keyboard" as a "device". They were a source of
| "characters" only.
|
| Now, over time countless people writing countless terminal
| emulators have tried to address this shortcoming, in countless
| not-quite compatible ways. And that's been about as successful as
| you'd expect. You can do it, but...
|
| But again, it's not about device support. Your command line
| program isn't and has never been connected to a "keyboard" device
| via any useful abstraction. The same feature that allows you to
| pipe input into it instead of typing at it makes this problem
| hard.
| agumonkey wrote:
| What is the correct architecture or design to make TUI on a
| terminal then ? Honest question
| TeMPOraL wrote:
| I think the other problem mentioned in the article is that
| _it has to work over SSH_. TUI on a local machine has no
| problem hooking into input devices; display-side, the
| difference between GUI and TUI is just what API calls you use
| to render stuff. But if you want to drive things remotely,
| you 're constrained by the remoting protocol - which, in TFAs
| case, is SSH without X forwarding.
| agumonkey wrote:
| Good point. This reminds me of Wayland Vs xorg.
| ajross wrote:
| Yeah, but it's the same problem. "Over ssh" means "on a
| terminal". Terminals have input streams, they don't have
| "keyboards".
| agumonkey wrote:
| It seems to me that terms mostly had semi batch IO
| mindset. The basic unit is a chat, not a signal over time
| like `<sensor> down for half a second` which only make
| sense for high frequency or real time user interactions.
| leoc wrote:
| The original ttys were literally Teletypes
| https://www.bell-labs.com/usr/dmr/www/picture.html
| designed to send text directly to another Teletype over a
| phone line. As such they sent and received sequences of
| characters, not key events, yes. OFC these are also
| basically the same ASCII text streams that Unix pipes
| between shell commands and the file system.
| agumonkey wrote:
| I get the legacy aspect both in internals of the time and
| usage. But I'm curious how to upgrade the old way to
| support finer grained interactions.
| riskable wrote:
| Not necessarily! SSH is terminal-agnostic: It doesn't
| care what or even _if_ you 're running a terminal or a
| shell on either end.
|
| It's perfectly reasonable to setup a pipe that sends
| _binary data_ through SSH: cat
| somefile.bin | ssh someuser@somehost "cat - >
| /tmp/somefile.bin
|
| That example assumes the shell of the user on the other
| side can execute the `cat` command but what if you didn't
| use a shell at all? What if you just had
| `/usr/bin/myprogram` as your shell? That can work too!
| You just need to set things up correctly (the SSH tunnel
| and make sure your program knows what to do when various
| escape sequences/signals get sent through the pipe by the
| SSH client--so the session can end cleanly, mostly).
| Going this low-level _probably_ isn 't necessary
| though...
|
| For the author's original example you could write
| `read_raw_input.py` and then pipe it through ssh to your
| controlling program on the other side say,
| `receive_input.py`:
| /usr/bin/read_raw_input.py | ssh someuser@somehost
| "receive_input.py"
|
| ...as long as the two Python scripts were setup to write
| and read from stdout/stdin everything should work fine,
| be reasonably low-latency, and won't require much setup
| other than SSH keys.
|
| On the other hand, if I were do to this I'd write my
| Python code so that it communicates with the other end
| directly rather than rely on the SSH daemon but that's
| just me (even if it was using SSH/paramiko internally).
| kelnos wrote:
| Sure, and that'd be fine for a special-purpose app that
| you use for yourself, but imagine being a regular user
| and installing this app, and the author wants you to
| install something on both the client and server side, and
| to run ssh in this unusual way. And you have to ensure
| that you have the proper permissions for raw access to
| the keyboard on the client side.
|
| If it's something that truly requires that sort of
| experience to work properly, ok, but if it's just a sort
| of "I want a fancy text UI that requires key-up events",
| this process is a bit much to ask of your users.
| mortehu wrote:
| There could easily have been escape sequences for released
| keys, just like there are for non-character keys like the
| arrow keys. You'll have to change your terminal emulator to
| support this too, though. This would work fine with SSH.
| ajross wrote:
| Honest answer: one that doesn't involve the need to capture
| individual keypresses. It just doesn't work on a Unix tty.
| Use a web app or other smart client (c.f. the IBM 3270, which
| had this problem largely solved in 1971 by putting the key
| navigation intelligence into the terminal).
| agumonkey wrote:
| I was about to say that, distributing real time input
| processing near the terminal makes sense. Also I wonder how
| video games handle that separation.
| Athas wrote:
| You don't go through the TTY model, but read directly from
| devices (if the kernel allows it). But people will hate you
| for it, since it doesn't fit with the abstraction layers that
| are commonly used, one of which is that only _characters_
| matter, not keypresses. Consider how such a TUI that directly
| interacts with keyboard devices (because it wants to detect
| keyup events) would work over SSH. It cannot. Abstraction
| layers limit certain functionality, but they also allow
| workflows to exist that otherwise could not (or would be much
| more complicated). You have to judge in every instance
| whether the correct balance has been made, but I don 't think
| this aspect of the Unix terminal design is awful.
| silon42 wrote:
| We need a text-mode equivalent of X11 (and then ssh
| forwarding for it).
| leoc wrote:
| I mean, on Unix it's ncurses, right? If no-one's ever added
| key-event support to ncurses then that's a(n additional) sign
| that it likely isn't possible and that TUIs just have to make
| do without the capability.
| zokier wrote:
| Correct architecture for terminal applications is command
| line; line oriented input, line oriented output. Not handling
| individual key events.
| karatinversion wrote:
| Not always, mind; having to press enter after every
| character press in vim would be a major drag!
| zokier wrote:
| ed/ex works perfectly fine with only line input and
| output. Afaik TECO stared out like that too.
|
| Gvim works for visual editing
| icedchai wrote:
| You can read individual characters just fine from a command
| line app. That's what tty "raw" mode does.
| PaulDavisThe1st wrote:
| Even back in the 1980s, when I was asked to reimplement the
| heirarchical DEC VMS "help" command for SunOS (in a
| terminal window), it was necessary to handle individual
| characters rather than use line-oriented input. The VMS
| "help" command had been written for VT100/VT200 terminals
| and their cousins, and was designed to take action on a
| single key press, rather than waiting for a return/enter
| action to "send" the command.
| arghwhat wrote:
| You're not supposed to write very advanced TUIs (advanced
| being subjective here). It's not what the interfaces were
| designed for.
|
| The interfaces for advanced UIs is Wayland and X. TUIs are
| meant for compatibility, not fancy ability.
| kelnos wrote:
| Right. And on top of that, one of the useful benefits of a
| TUI is that you can use them while ssh'd into a remote
| server. If your fancy TUI is expecting to get raw access to
| the keyboard, it's not going to work in a ssh session.
| _jal wrote:
| Who says? Actual question.
|
| > TUIs are meant for compatibility
|
| Nonsense. Our machines don't even get GUIs installed.
| toast0 wrote:
| Like other's have said. If your user interface relies on key-
| up, it's not really possible in general. A given linux
| machine may only have a serial console, and afaik, you're not
| getting key up from any serial terminals; certainly not any
| common terminals. It's just not part of the design, and short
| of a time machine, it's unlikely to become part of the design
| because DEC isn't around to update the spec for vtXXX
| terminals or their implementations.
| silicon2401 wrote:
| this comment was an excellent read. is there any kind of book
| that covers the historical development of computer tech in this
| way, that isn't just a full-blown technical reference?
| ajross wrote:
| Not at that level of completeness, no. Most people who puzzle
| this out start with writing escape characters in shell to
| dazzle up their bash prompts and then escalate from there to
| figuring out the rest of the protocol.
| amelius wrote:
| > Linux exposes your keyboards as /dev/inputN devices
|
| Yeah, but those are only readable by root.
| zozbot234 wrote:
| The modern Linux stack allows non-root users to access these
| if they're "bound" to the right 'seat' and 'session' in the
| freedesktop-derived multiseat infrastructure. AIUI, this is
| how non-root X works as well. It's incredibly clunky stuff
| because no one has ever made the effort to refactor it nicely
| (the typical problem with all fd.o stuff), but this is
| _supposed_ to be possible.
| fulafel wrote:
| To add, you can read the kb events even in a command line
| program. Using GUI APIs works fine in terminal programs if the
| GUI is running. Works even remotely in a GUI that support
| network transparency, like X does. Eg like this:
|
| https://stackoverflow.com/a/4037579
___________________________________________________________________
(page generated 2021-05-17 23:02 UTC)