LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Desktop (https://www.linuxquestions.org/questions/linux-desktop-74/)
-   -   TouchCursor under Linux ; I can't believe there is no way to do that (https://www.linuxquestions.org/questions/linux-desktop-74/touchcursor-under-linux-%3B-i-cant-believe-there-is-no-way-to-do-that-771470/)

merindol 11-25-2009 08:57 AM

TouchCursor under Linux ; I can't believe there is no way to do that
 
Hi there.

I'm trying to do something like TouchCursor does (cf. touchcursor.com, there is a video). It uses the spacebar as a meta-key to give access to the navigation keys (and more) from the main keyboard, like Space+L for Right-key (see the video).

Atm, it almost works. E.g. I can Shift+Ctrl+Space+L to select the word to the right of the cursor.

But my spacebar no longer works as a spacebar. I'm trying to find a way to make it works like with TouchCursor : when I press than release the spacebar, and only if no other keys have pressed, it should spawn a space character.

I tried with Xbindkeys :
Code:

"/usr/bin/xvkbd -xsendevent -text '\[space]'"
Mode_switch+Release

but it prevents the new arrow keys from working. And, even, It wouldn't give us the result we expect (aka. print a space character when only the space bar is pressed and then released, without any other key pressed in the mean time)

Anyone has an idea ? It seams quite tricky.

Btw, here is the ~/.Xmodmap code for the navigation pad feature (keycode 65 is my spacebar ; you can use an other key to test safely) :
Code:

keycode 65 = Mode_switch Mode_switch space space nobreakspace U202F
add mod3 = Mode_switch
keysym i = i I Up NoSymbol icircumflex Icircumflex
keysym k = k K Down NoSymbol idiaeresis Idiaeresis
keysym j = j J Left NoSymbol udiaeresis Udiaeresis
keysym l = l L Right NoSymbol U0140 U013F
keysym h = h H Prior NoSymbol eth ETH
keysym n = n N Next NoSymbol notsign rightarrow
keysym u = u U Home NoSymbol ucircumflex Ucircumflex
keysym o = o O End NoSymbol oe OE
keysym comma = comma question Delete NoSymbol questiondown U2026
keysym p = p P BackSpace NoSymbol ocircumflex Ocircumflex
keysym y = y Y Insert NoSymbol ydiaeresis Ydiaeresis

Maybe should I try Xkbd ? Is it more powerful ?

Regards.

business_kid 11-26-2009 04:08 AM

Welcome to LQ.
If you really want this, use one or more of the standard meta keys (from memory - Ctrl, Alt, Shift, AltGr) and you might be able to map this function into .Xmodmap. I had a go at this in times gone by for the €uro (euro = €)sign

merindol 11-27-2009 03:30 AM

Hi and thanks for the answer.

The xmodmap mapping is not really the problem. Currently I'm using the Menu key but it's not really convenient. Using the spacebar as the modifier would be a lot more comfortable. But then there is the problem to still be able to enter space characters... thus my post.

Regards.

business_kid 11-28-2009 03:16 AM

One function per key, I'm afraid.

The design of the qwerty keyboard is far from ideal. If finding windows utilities in linux is whatyou want, I think your luck is out. You could try

1. Running touchcursor under wine, but it would probably barf or malfunction. You have a copy.
2. If speed is your aim and you're a regular typist, why not go for the dvorak keyboard? I hear much higher speeds are possible once you learn it. Linux accomodates it with keymaps and the like.

mjstone 01-08-2010 01:35 PM

Hi. I'm the author of TouchCursor.

I recently released TouchCursor under the GPL*. Obviously this means you can play around with the TC source and see if it's any help. If you get anywhere I'd be very interested in integrating a Linux version into the project. (I'm currently a total Linux newbie and I can't use Linux in earnest because I'm so dependent on TouchCursor -- so Catch 22 ;-) )

(*This is my first post here so I'm not allowed to post the URL -- It's on SourceForge; I'm sure you'll find it.)

Martin.

MTK358 01-08-2010 01:46 PM

I wonder if it's possible for a program to "steal" all X keyboard events, no matter what window is focused, and is it possible for the same program to "repeat" the events to the focused window?

If so, it might be possible to make a program that filters the keyboard events and can modify them however you like, including modifying the actions of other keys when space is held down.

merindol 01-09-2010 04:59 AM

Hello.

Mjstone, thanks to put TouchCursor under GPL, it's really nice and smart.

I've managed to quite make it work under linux but it's unusable : when writing a text the spacebar lags behind other keys ; it's impossible to write at a decent speed.

I used xbindkeysrc.scm guile configuration file (it's possible to write complex functions).

I do think the only good way to do that is to work on a lower level than those dekstop apps.

Regards.

MTK358 01-09-2010 08:08 AM

I was thinking how to do this, here I made a pseudo-code template of what it might be like:

Code:

int main() {
        bool modPressed = false;
        bool sendSpace;
        Event event;
        while(true) {
                event  = stealXKeyEvent();
                if(event.key == KEY_SPACE) {
                        if(event.type == KEY_PRESSED) {
                                modPressed = true;
                        } else {
                                modPressed = false;
                                if(sendSpace) {
                                        sendXKeyEvent(KEY_SPACE, KEY_PRESSED);
                                        sendXKeyEvent(KEY_SPACE, KEY_RELEASED);
                                }
                        }
                } else {
                        if(modPressed) {
                                sendSpace = false;
                                if(event.key == KEY_I) {
                                        sendXKeyEvent(KEY_UP, event.type);
                                } else if(event.key == KEY_K) {
                                        sendXKeyEvent(KEY_DOWN, event.type);
                                } else if(event.key == KEY_J) {
                                        sendXKeyEvent(KEY_LEFT, event.type);
                                } else if(event.key == KEY_L) {
                                        sendXKeyEvent(KEY_RIGHT, event.type);
                                } else if(event.key == KEY_U) {
                                        sendXKeyEvent(KEY_HOME, event.type);
                                } else if(event.key == KEY_O) {
                                        sendXKeyEvent(KEY_END, event.type);
                                } else if(event.key == KEY_H) {
                                        sendXKeyEvent(KEY_PGUP, event.type);
                                } else if(event.key == KEY_N) {
                                        sendXKeyEvent(KEY_PGDN, event.type);
                                } else if(event.key == KEY_Y) {
                                        sendXKeyEvent(KEY_INSERT, event.type);
                                } else if(event.key == KEY_M) {
                                        sendXKeyEvent(KEY_DELETE, event.type);
                                } else {
                                        sendSpace = true;
                                }
                        } else {
                                sendXKeyEvent(event);
                        }
                }
        }
}


mjstone 01-10-2010 08:24 AM

Well the the TouchCursor code is a bit more complicated -- I needed six states to handle all the cases I cared about, plus some extra state for delaying emitted key-presses.

For example one thing your pseudo-code doesn't handle is overlapping key presses, e.g. [Space-down, L-down, Space-up, L-up], which is the sort of thing that happens a lot when typing fast (for some typists, at least). In this case the program should emit a Space then L, but it doesn't know that until it gets the Space-up.

The interesting bit, for me at least, is what goes in your stealXKeyEvent() and sendXKeyEvent() functions, and how to insert a program into the chain of programs that process the global stream of keyboard events.

MTK358 01-10-2010 12:39 PM

Quote:

Originally Posted by mjstone (Post 3821133)
The interesting bit, for me at least, is what goes in your stealXKeyEvent() and sendXKeyEvent() functions, and how to insert a program into the chain of programs that process the global stream of keyboard events.

I don't know either, and I can't continue until I do.

bobshaffer2 01-11-2010 09:29 PM

You can get a program to grab the keyboard and modify the events and send them to the focused window like what was discussed here, BUT you must realize that some other programs may (and many will) still try to grab the keyboard themselves and/or ignore XEvents for keyboard input. xterm, for instance, has a "Secure Keyboard" mode that wouldn't work if another program had grabbed the keyboard already. Programs run through wine try to grab the keyboard pretty often too. So, while this solution is worth trying, I can be fairly certain you will run into a problem or two with it.

In order to get something completely functional, you might have to actually hack the xorg keyboard driver, and then make a patch for it.

bobshaffer2 01-11-2010 10:04 PM

Looking again at what was posted, I see you were trying to determine a few things...

How to "insert a program into the chain of programs that process the global stream of keyboard events": this is done partly by "grabbing" the keyboard. I'm not sure of the exact code, but the function is XGrabKeyboard(Display*,Window,Bool,int,int,Time). You can send the keys to a program using XSendEvent() and using XKeyEvents. You should realize that you need to send an event for the key being pressed and another for it being released. Determining where to send the event may be the difficult part. It should be possible, but I'm not sure how. One way would be to ask for XFocusChangeEvents I guess and then keep track of who has focus. I don't know if all window managers will agree to give those events, but it seems reasonable enough to try.

Like I said, some programs will try to grab the keyboard themselves and/or ignore XKeyEvents. I would be curious how well this all works if you get it all figured out, though.

MTK358 01-12-2010 07:11 AM

Quote:

Originally Posted by bobshaffer2 (Post 3823217)
Looking again at what was posted, I see you were trying to determine a few things...

How to "insert a program into the chain of programs that process the global stream of keyboard events": this is done partly by "grabbing" the keyboard. I'm not sure of the exact code, but the function is XGrabKeyboard(Display*,Window,Bool,int,int,Time). You can send the keys to a program using XSendEvent() and using XKeyEvents. You should realize that you need to send an event for the key being pressed and another for it being released. Determining where to send the event may be the difficult part. It should be possible, but I'm not sure how. One way would be to ask for XFocusChangeEvents I guess and then keep track of who has focus. I don't know if all window managers will agree to give those events, but it seems reasonable enough to try.

Like I said, some programs will try to grab the keyboard themselves and/or ignore XKeyEvents. I would be curious how well this all works if you get it all figured out, though.

I'll try looking into those later, also I wonder if there is an easy way to do it so that it does not rely on X (that is, would still work in the command line)?

bobshaffer2 01-12-2010 01:10 PM

You could write a kernel module to do it. IDK if there would be any easier way. If you did that, it would completely cover everything. Other than that you would probably be looking at maintaining two projects: one for the console and one for X. The driver would almost certainly need to built into the kernel rather than a module, and it almost seems like the standard keyboard driver would have to NOT be built in, otherwise it would probably claim the device and cause problems. I personally think doing it for just X would be the easy solution, but the other would probably be more flexible.

MTK358 01-12-2010 01:51 PM

Well, I don't know anything whatsoever about the kernel (but I hope that will change), so I guess I should go the X way.

EDIT: using X will also give me the opportunity to integrate a status icon and settings dialog (probably in GTK+).

MTK358 01-12-2010 01:54 PM

From the XGrabKeyboard man page:

Code:

display
    Specifies the connection to the X server.
grab_window
    Specifies the grab window.
keyboard_mode
    Specifies further processing of keyboard events. You can pass GrabModeSync or GrabModeAsync.
owner_events
    Specifies a Boolean value that indicates whether the keyboard events are to be reported as usual.
pointer_mode
    Specifies further processing of pointer events. You can pass GrabModeSync or GrabModeAsync.
time
    Specifies the time. You can pass either a timestamp or CurrentTime.

What is the "grab window" and owner_events, and why does it need to know the time?

bobshaffer2 01-12-2010 02:08 PM

Quote:

Originally Posted by MTK358 (Post 3824101)
From the XGrabKeyboard man page:

Code:

display
    Specifies the connection to the X server.
grab_window
    Specifies the grab window.
keyboard_mode
    Specifies further processing of keyboard events. You can pass GrabModeSync or GrabModeAsync.
owner_events
    Specifies a Boolean value that indicates whether the keyboard events are to be reported as usual.
pointer_mode
    Specifies further processing of pointer events. You can pass GrabModeSync or GrabModeAsync.
time
    Specifies the time. You can pass either a timestamp or CurrentTime.

What is the "grab window" and owner_events, and why does it need to know the time?

all XEvents are supposed to have a timestamp. It's so that events can be handled asynchronously and there is some indication as to the sequence of events. The grabbing window would most likely be *your* window. I'm not sure if your window can both grab the keyboard and remain hidden, but it's worth a try. I don't think it's possible to do anything without at least creating a widget. You may have to map it as well, and then hide it after grabbing the keyboard. You'll just have to try some things and see what happens.

MTK358 01-12-2010 03:26 PM

How do I create a "Time"?

And what's "owner_events"?

bobshaffer2 01-12-2010 03:55 PM

Quote:

Originally Posted by MTK358 (Post 3824243)
How do I create a "Time"?

And what's "owner_events"?

I think a "Time" is just a time_t, so maybe:

Time t = time();

I don't remember for sure.
And owner_events looks like it should be True for what you want. It looks like it's asking whether you want the events to be sent or not. Perhaps it's possible to use some method other than event processing to get the status of the keyboard. I don't know for sure, I tend to test things when I'm not sure, as sometimes the Xlib documentation is somewhat cryptic.
Hope that helps some.

MTK358 01-12-2010 05:03 PM

No, it says that time is of type "Time" (with a capital T), not "time_t".


All times are GMT -5. The time now is 08:12 PM.