Author Topic: Dual-role keys  (Read 51808 times)

0 Members and 1 Guest are viewing this topic.

Offline angelic_sedition

  • Posts: 124
  • Location: Flatland
Re: Dual-role keys
« Reply #50 on: Tue, 11 February 2014, 13:01:36 »


I have tried to implement SpaceFN in Linux using the record extension in X11.

Trouble is, it lets you intercept key presses, it lets you add keys to the event queue, but you cannot remove events from the queue!

So it works only for real modifiers. A modifier like Shift generates 2 events when you press then release it, and these events are ignored. When you detect the key release, you can then add an event to the queue (if no other key has been pressed in between). That's how xcape works.

It does not work for keys that generate a character, because you cannot remove this character from the event queue.

I don't know how to do better than that. Apparently if you want to be able to modify the event queue you will need to modify one of the Linux kernel drivers.

There is an utility called AutoKey that does key remapping, but it is buggy (it often crashes when you keep a key pressed) and apparently it works by dealing with the window manager, so it's not very portable and this approach suffers from other shortcomings.                     

I'm trying to implement it with python and xlib, but I'm not totally sure what I'm doing.

Autokey is more for text expansion. I haven't had any problems with it crashing, but it doesn't seem like a very good way to do it (as oppoed to a python script by itself and not bound to a key), and to the best of my knowledge, the devs aren't interested in implementing this sort of feature: https://code.google.com/p/autokey/issues/detail?id=200
QWERTY(104wpm) -> CarpalxQ(modded) -> Colemak(118wpm) -> Colemak-DH
Mouse less.

Offline Pro XKB

  • Posts: 25
Re: Dual-role keys
« Reply #51 on: Wed, 12 February 2014, 06:39:13 »
Sorry for sending the wrong link for ActionMessage.  This is the one I meant:

http://lists.x.org/archives/xorg/2010-September/051098.html

Offline islisis

  • Posts: 120
  • Location: Tokyo, Japan
Re: Dual-role keys
« Reply #52 on: Mon, 17 February 2014, 09:19:34 »
Various workloads have put Linux experimentation on the backburner :/ If you make any progress angelic I would help in any way possible (I had similar ideas about trying Autokey, I'm not sure how X input translates to future libraries like Wayland though).

Prototyping continues in AHK, on the LHS alone I've got 4 thumb keys and 3 pinky in varying DR capacities. Implementation in software is a necessity now due to interaction with mouse movement (as another DR trigger... erm and TR ^^;).

Semi-related: chorded the crap out of my 6 button mouse.
« Last Edit: Mon, 17 February 2014, 09:37:58 by islisis »

Offline shaaniqbal

  • Posts: 145
Re: Dual-role keys
« Reply #53 on: Mon, 17 February 2014, 15:09:52 »
If anyone's interested, my post here describes a method of using home row keys as triple-role keys:

http://geekhack.org/index.php?topic=52967.msg1178985#msg1178985

Offline angelic_sedition

  • Posts: 124
  • Location: Flatland
Re: Dual-role keys
« Reply #54 on: Tue, 18 February 2014, 21:00:08 »
Various workloads have put Linux experimentation on the backburner :/ If you make any progress angelic I would help in any way possible (I had similar ideas about trying Autokey, I'm not sure how X input translates to future libraries like Wayland though).

Prototyping continues in AHK, on the LHS alone I've got 4 thumb keys and 3 pinky in varying DR capacities. Implementation in software is a necessity now due to interaction with mouse movement (as another DR trigger... erm and TR ^^;).

Semi-related: chorded the crap out of my 6 button mouse.
I'm pretty busy as well myself. If X dies to Wayland, then I won't move anyway until I get the equivalent of things like xdotool, xdo, xmodmap, xsendkey, xchainkeys, etc. (without them I'm crippled). As for progress, I really have a lot of documentation to wade through before I find what I'm looking for. What would be great is if I could find some decent simple way to time the length of a keypress.

I was thinking a really simple way to do it would be to use sxhkd, which allows you to bind a key to a keypress or keyrelease. Sadly, it doesn't allow for you to have bindings for both. I was thinking it would be really easy to just start a timer on keypress and just keep looping and do nothing until keyrelease or until certain time length, after which it would act as a modifier until key release. The corresponding keyup binding would check the timer and send the normal key (i.e. space) if it was less than that time or do nothing if greater than the time. Alas, I don't think this will ever work, and it says something about my lack of progress that this is the best idea I've had so far.

I don't think the python xlib library hasn't been updated in years, so I'm not too confident about going down that road either.
« Last Edit: Tue, 18 February 2014, 21:02:15 by angelic_sedition »
QWERTY(104wpm) -> CarpalxQ(modded) -> Colemak(118wpm) -> Colemak-DH
Mouse less.

Offline islisis

  • Posts: 120
  • Location: Tokyo, Japan
Re: Dual-role keys
« Reply #55 on: Wed, 19 February 2014, 06:57:21 »
OK, I completely understand! It's an important long term project for me so I'm trying to think ahead, starting will likely be a miracle as I'll have lots to research. Keypress timers can work for simple decision logic and I use it for some DR keys (if it sends the modkey by default you don't need a loop just subtract the system time of the two events), but I want to write a more complete framework as interactions with other keypresses have become quite important.

As an aside, if you don't like AutoKey because it is limited to WMs this may not be better but there is also AutoPy (http://www.autopy.org) though doesn't seem to be maintained

Best of luck and keep us posted :)
« Last Edit: Wed, 19 February 2014, 07:25:50 by islisis »

Offline spiceBar

  • Posts: 998
    • ChessTiger.com
Re: Dual-role keys
« Reply #56 on: Wed, 19 February 2014, 06:58:18 »
Various workloads have put Linux experimentation on the backburner :/ If you make any progress angelic I would help in any way possible (I had similar ideas about trying Autokey, I'm not sure how X input translates to future libraries like Wayland though).

Prototyping continues in AHK, on the LHS alone I've got 4 thumb keys and 3 pinky in varying DR capacities. Implementation in software is a necessity now due to interaction with mouse movement (as another DR trigger... erm and TR ^^;).

Semi-related: chorded the crap out of my 6 button mouse.
I'm pretty busy as well myself. If X dies to Wayland, then I won't move anyway until I get the equivalent of things like xdotool, xdo, xmodmap, xsendkey, xchainkeys, etc. (without them I'm crippled). As for progress, I really have a lot of documentation to wade through before I find what I'm looking for. What would be great is if I could find some decent simple way to time the length of a keypress.

I was thinking a really simple way to do it would be to use sxhkd, which allows you to bind a key to a keypress or keyrelease. Sadly, it doesn't allow for you to have bindings for both. I was thinking it would be really easy to just start a timer on keypress and just keep looping and do nothing until keyrelease or until certain time length, after which it would act as a modifier until key release. The corresponding keyup binding would check the timer and send the normal key (i.e. space) if it was less than that time or do nothing if greater than the time. Alas, I don't think this will ever work, and it says something about my lack of progress that this is the best idea I've had so far.

I don't think the python xlib library hasn't been updated in years, so I'm not too confident about going down that road either.

I think the problem is not to receive events and time them. That's easy to do with the XRecord extension.

The problem is to modify the X event queue. You can add events but not remove events.

At least that's what has stopped me.

Offline angelic_sedition

  • Posts: 124
  • Location: Flatland
Re: Dual-role keys
« Reply #57 on: Wed, 19 February 2014, 11:49:23 »
I think the problem is not to receive events and time them. That's easy to do with the XRecord extension.

The problem is to modify the X event queue. You can add events but not remove events.

At least that's what has stopped me.
Ah well I haven't tried anything with xrecord extension. I've had no problem capturing and sending keystrokes with the methods I've tried, but so far they've all worked badly with timing.

OK, I completely understand! It's an important long term project for me so I'm trying to think ahead, starting will likely be a miracle as I'll have lots to research. Keypress timers can work for simple decision logic and I use it for some DR keys (if it sends the modkey by default you don't need a loop just subtract the system time of the two events), but I want to write a more complete framework as interactions with other keypresses have become quite important.

As an aside, if you don't like AutoKey because it is limited to WMs this may not be better but there is also AutoPy (http://www.autopy.org) though doesn't seem to be maintained

Best of luck and keep us posted :)
RIght now, I'm just trying to come up with something simple (and likely undesirably hackish..) that at least is usable. Something simple shouldn't be too hard to do.. as for something more complete.. python might not be the way to go.

As for autokey, I just don't really see the benefit, since you would just use python scripting with it anyway. It seems more of a hinderance. I'm confused about what you mean by limited to WMs though (I've never had it not work on any WMs or DEs) unless you're not talking about window managers? Unless autokey allows easy distinguishing between keydown and up (which it doesn't to the best of my knowledge), I don't really see it as helpful. Thing like xpybind and autopy (as you mentioned) are what I'm looking at right now for a simple solution. Though xpybind looks basically like a more capable xchainkeys.. I'm not sure it would actually be anymore useful to me than what I've already tried.

I'll update if I get anywhere.
« Last Edit: Wed, 19 February 2014, 11:52:45 by angelic_sedition »
QWERTY(104wpm) -> CarpalxQ(modded) -> Colemak(118wpm) -> Colemak-DH
Mouse less.

Offline islisis

  • Posts: 120
  • Location: Tokyo, Japan
Re: Dual-role keys
« Reply #58 on: Wed, 19 February 2014, 21:51:28 »
Sorry for the imprecise language, I mean on a gui level but I'm just not familiar with the details. I also naively assumed there was a key detection parity with key_press/key_release without doing any research. There is the function wait_for_keypress which I assume was introduced in response to this request, but I agree that the implementation is not complete enough to be a good candidate currently. I will see if we can rally up support for key press/release binding.

For me it seemed easier to implement it on top of a pre-existing remapping framework to avoid conflicts and allow better integration with system events, but I haven't don't any proper research.

Offline hoggy

  • * Ergonomics Moderator
  • Posts: 1502
  • Location: Isle of Man
Re: Dual-role keys
« Reply #59 on: Thu, 20 February 2014, 11:45:32 »
It's only just occurred to me that most of us have already encountered dual use keys - the windows key.  Pressing the win key by itself will bring up the start menu, but win-e will open explorer.  The start menu only appears when the win key is released, if no other button was pressed while the win key was down.  It's not a great discovery, I thought it might be a good example to bring up.                                       
GH Ergonomic Guide (in progress)
http://geekhack.org/index.php?topic=54680.0

Offline islisis

  • Posts: 120
  • Location: Tokyo, Japan
Re: Dual-role keys
« Reply #60 on: Fri, 21 February 2014, 23:43:31 »
Good example, it seems to me alt can considered DR in the same way (and a good candidate for customising for that same reason), as are some change language shortcuts such as alt-shift. It will be interesting to see what are keys can be seen as safe enough for consumption :)
« Last Edit: Sun, 23 February 2014, 00:05:55 by islisis »

Offline Chendy

  • Posts: 3
Re: Dual-role keys
« Reply #61 on: Wed, 05 October 2016, 08:16:31 »
Does anybody know a working script for Windows? i just want space and shift. i was using the script below but doesnt work on my windows 8.1 anymore, no idea why

https://github.com/yutaszk/win-sands-ahk

i posted a question to Stack Exchange, but no luck so far

http://superuser.com/questions/1122228/windows-sands-space-and-shift-aka-dual-role-key-spacebar-works-as-spaceba

Offline hasu

  • Thread Starter
  • Posts: 3471
  • Location: Tokyo, Japan
  • @tmk
    • tmk keyboard firmware project
Re: Dual-role keys
« Reply #62 on: Wed, 05 October 2016, 18:48:58 »
Couldn't  you fix the script?
It seems like very simple clean and easy to hack, what's actually your problem?

Offline wilderjds

  • Posts: 3
Re: Dual-role keys
« Reply #63 on: Thu, 17 November 2016, 20:10:33 »
Just my 2 cents on the rollover detection criterion.  I am interested in using the spacebar as an extra ctrl, so there is a lot of problems with fast typing rollover.

 I found that adding timeouts makes things a bit unpredictable, so I don't like them as a solution. What I ended up doing, and it works quite well even in actual real world typing,  at least for me, is the following.

If spacebar is pressed, X is released,  then treat the spacebar press as a space press.

If spacebar is pressed,  X is pressed and spacebar is released,  treat the spacebar events as space events

Otherwise treat the spacebar press (and the following release) as a ctrl.

I guess the key thing is the first of the checks. It makes all the difference in the world for me.
I am implementing it with a patched version of the ahm patched evdev driver.

Offline angelic_sedition

  • Posts: 124
  • Location: Flatland
Re: Dual-role keys
« Reply #64 on: Tue, 06 December 2016, 16:47:05 »
Just my 2 cents on the rollover detection criterion.  I am interested in using the spacebar as an extra ctrl, so there is a lot of problems with fast typing rollover.

 I found that adding timeouts makes things a bit unpredictable, so I don't like them as a solution. What I ended up doing, and it works quite well even in actual real world typing,  at least for me, is the following.

If spacebar is pressed, X is released,  then treat the spacebar press as a space press.

If spacebar is pressed,  X is pressed and spacebar is released,  treat the spacebar events as space events

Otherwise treat the spacebar press (and the following release) as a ctrl.

I guess the key thing is the first of the checks. It makes all the difference in the world for me.
I am implementing it with a patched version of the ahm patched evdev driver.

Could you elaborate on why you don't like timeouts? To me it seems the best way to implement dual-role would be with a customizable delay before the key starts acting as a modifier combined with a customizable minimal overlap time. Also, the decision should be made on key release (not press) or when the delay time is reached.

For the first case you describe, is X pressed before space? I'm not sure I like the idea of depending on release order as much. I thought ahm already did this, but I guess I was wrong. Do you have your version available somewhere, so I could try it?

As a side note, I encountered someone who uses space as control with xcape. This person was able to get used to it and change how they type to work around the problem (no rolling with space bar). Ideally I'd like to have dual-roled home row keys, so this approach isn't feasible for me, but I found it interesting nonetheless.
QWERTY(104wpm) -> CarpalxQ(modded) -> Colemak(118wpm) -> Colemak-DH
Mouse less.

Offline angelic_sedition

  • Posts: 124
  • Location: Flatland
Re: Dual-role keys
« Reply #65 on: Thu, 08 December 2016, 00:14:58 »
Related to my posts from years ago, I never got anywhere mostly due to lack of time, experience, documentation, and simple examples of what I wanted to do in python. As far as I understand X (and I don't understand it all that well), you can only grab/capture all keys if you have a mapped window (and only when that window is active; this is how normal programs work). As for globally capturing keys, only one program can globally capture a specific key combination (this is how hotkey daemons work). This seems to leave only a few possibilities for creating an "intelligent" dual-role program:

1. Capture the modifier in question plus all letter keys
- Potential for conflict with keys bound by a hotkey daemon or window manager (potentially impossible or inconvenient to dual-role for certain modifiers)

2. Capture all unmodified letter/number/etc. keys
- Since all typing (without modifiers) is going through the dual-role program, reliability is a potential issue

3. Grab just the dual-role keys, and activate a window that will capture all input when they are pressed
+ When a dual-role key is not in use, input is not going through the dual-role program
+ Probably easier to implement modifier combinations like this (no possibility for conflict so can capture all modifier combinations)
- Requires a visible window (not neccessarily the worst thing if you consider that programs like plover and ibus have windows); maybe could make it really small (I'm pretty sure it still has to be mapped though)
- Requires focus switching

I recently became interested in working on this again. Yesterday I attempted to get the second method working using an X library in a different language with more extensive documentation. I now have something that allows for optionally enforcing a minimum delay time, a minimum overlap time, and release order (non-dual-role must be released first). I've never tested a dual-role program with configurable options like these before, so these are my initial observations:

1. Having a short delay alone seems to be a pretty good way of preventing incorrect results without adjusting typing (error: either the user accidentally uses the key as a modifier or they want to use it as a modifier but didn't hold it down long enough). I think this may be a viable method for using home row keys as dual-role keys.

2. I'm not sure if the difference between the key overlap time is significant enough for a minimum overlap time to be much good. It would have to be shorter than the average time a key is held when typing but longer than the overlap between two keys when typing. These two times are pretty close, so I need to test this more. If they vary enough to overlap a lot of the time, this won't be very useful.

3. Checking release order can prevent most errors as well. The potential downside is that you may have to retrain yourself to always release modifier keys last (though this isn't a huge deal). A combination of this and a delay may be very reliable.

4. While I think some combinations of these methods could give pretty good results, I'm not sure how good an using X for the implementation is. Right now, I'm encountering a problem where not all key release events are reported (not sure if this is a bug in the library or a problem with how I'm using it). I don't know if anyone is still interested, but if I can workaround this problem (given when it happens, it may not even be necessary to fix it), I can put the program up for others to test. At this stage, it seems somewhat promising, but it may turn out that it's not a viable solution. Maybe improving AHM is the way to go. I may also want to look at software like ibus to see input is captured. There is one clear benefit to this approach though. It makes it easily possible to create an extra layer for a dual-role key instead of binding it to a specific modifier. This layer could consist of both normal keypresses as well as custom shell commands. I could also easily include a piece of software that would have you type normally and then help you choose minimum delay/overlap times.
QWERTY(104wpm) -> CarpalxQ(modded) -> Colemak(118wpm) -> Colemak-DH
Mouse less.

Offline Pro XKB

  • Posts: 25
Re: Dual-role keys
« Reply #66 on: Thu, 08 December 2016, 13:23:35 »
Quote
This seems to leave only a few possibilities for creating an "intelligent" dual-role program:
Grabbing is not your only option.  You could use the RECORD extension, the ActionMessage approach I mentioned above.

Offline islisis

  • Posts: 120
  • Location: Tokyo, Japan
Re: Dual-role keys
« Reply #67 on: Fri, 09 December 2016, 07:57:02 »
my dev environment has been in limbo for almost a year, but i'm committed to long term work on this.

just a couple naive questions:

1. Is this method implementable through libinput?

2. Can you make calls to the extra layers through python easily? It would indeed be nice to have a basic framework for defining potentially unlimited mod keys, etc.

Offline angelic_sedition

  • Posts: 124
  • Location: Flatland
Re: Dual-role keys
« Reply #68 on: Wed, 14 December 2016, 16:32:21 »
Grabbing is not your only option.  You could use the RECORD extension, the ActionMessage approach I mentioned above.

Well I meant from an xlib/xcb standpoint; there is also AHM of course, which modifies evdev. As for XKB, I've never liked it, and the method described there seems a lot more complicated for both the implementor and the user. I personally wouldn't easily be able to implement dual-role that way.

1. Is this method implementable through libinput?

I know very little about libinput. My guess is that it's probably possible, but I don't now if this would be the best solution. From my understanding, this may require maintaining an alternate version of libinput (I may be wrong). I'll mess around with libinput some when I have the time. The implementation method would be very similar but possibly easier/more powerful (since like with AHM, all keys would pass through it).

2. Can you make calls to the extra layers through python easily? It would indeed be nice to have a basic framework for defining potentially unlimited mod keys, etc.

I abandoned using python with its xlib library because I couldn't understand it easily/quickly. I'm not entirely sure what you're asking, but it's easily possible to create a fake modifier with this method. It's kind of comparable to binding key combinations to "xdotool key ..." with a hotkey daemon but more direct.

Edit: I don't think it's actually possible to bind a non modifier + non modifier combination with any hotkey daemons, so it's not a very good analogy.
« Last Edit: Wed, 14 December 2016, 16:59:02 by angelic_sedition »
QWERTY(104wpm) -> CarpalxQ(modded) -> Colemak(118wpm) -> Colemak-DH
Mouse less.

Offline T42

  • Posts: 16
  • Location: Germany
another Autohotkey implementation attempt
« Reply #69 on: Mon, 22 October 2018, 12:11:57 »
I have tried to implement dual-role keys which do not require any timing tradeoffs in Autohotkey.

Unfortunately, although the automated tests suggest otherwise, it does not work in practice: Often, modifiers or layers get locked (i.e. key up events seem to be missing). At that point, I gave up for the time being. (I noticed that you can have actually fit 15 dedicated modifier keys on a standard keyboard. :-)

Since I currently have no plans to continue working on it, I share it as a forum post instead of a proper repository.

Offline kbder

  • Posts: 6
Re: Dual-role keys
« Reply #70 on: Thu, 20 December 2018, 18:30:12 »
Looks like I'm the next in line to pick up this torch and try to carry it forward!  :eek:

I'm just getting my head wrapped around QMK, but it seems that the critical thing for dual-role keys is that they can only be properly disambiguated upon the next key UP event (and that key up's corresponding key down must have started at or after the dual-role key).

for example, if key0 is dual-role as SHIFT and 'a', and key1 is just a normal 'b' key, here are some sequences and how they should be interpreted:

key0 down, key0 up -> a down, a up

key0 down, key1 down, key0 up, key1 up -> a down, b down, a up, b up

key0 down, key1 down, key1 up, key0 up -> SHIFT down, b down, b up, SHIFT up

because we have process_record_user(), I think we can pull this off, because we can completely override what QMK does with keystrokes.  We just need to buffer ambiguous keys until the next up stroke disambiguates them.

For a user with 10 fingers, the most we should need to buffer before we can start disambiguating is 10 downstrokes and 1 upstroke.  That shouldn't be a problem as far as RAM consumption.  I've gotten started throwing together a little ring buffer to accomplish this.

I'll post more as I actually get something closer to working.

Offline kbder

  • Posts: 6
Re: Dual-role keys
« Reply #71 on: Thu, 20 December 2018, 18:37:11 »

Offline kbder

  • Posts: 6
Re: Dual-role keys
« Reply #72 on: Sat, 22 December 2018, 00:51:13 »
Ok, I have an initial implementation working!  https://github.com/qmk/qmk_firmware/pull/4709

Currently it only handles dual-role modifiers.  Next I'd like to have similar dual-role momentary layer switching, and finally a "layer hold" key which will allow for switching a layer and then using the dual-role modifiers from within that layer.

Offline kbder

  • Posts: 6
Re: Dual-role keys
« Reply #73 on: Sat, 22 December 2018, 01:17:30 »
(including gifs from the github pull request for illustration, see https://github.com/qmk/qmk_firmware/pull/4709 for details)