
semicomplete - issue #6
current modifiers affect resulting key event (bug, feature, or just the way it works?)
What steps will reproduce the problem? 1. $ sleep 2; xdotool key ctrl+o 2. Hold down alt when xdotool runs
What is the expected output? What do you see instead? expected ^O (ctrl+o) instead ^[^O (ctrl+alt+o)
(those keyseqs should get echo'ed to the terminal)
What version of the product are you using? On what operating system? xdotool-r2197 on Arch Linux xorg-server-1.6.1.901 bash-2.3.48 xterm-243 (with metaSendsEscape set)
Please provide any additional information below.
I'm trying to use xdotool to map and focus a window and then send ctrl+o to it. This works from the shell, but when I bind a script to Alt+F2 in my window manager, alt may still be held when xdotool sends the key, and it ends up being ctrl+alt+o. If I send a 'keyup alt' before sending ctrl+o, this works fine. But my concern is that now the user may still be holding down alt, and may want to issue another alt binding. I might 'keydown alt' after sending my key, but it may as well happen that the user releases alt before that, so again, the modifier state in X would differ from the physical state of the keyboard. If tested this setup, and it seems possible that the user releases the modifier key between xdotool sending key ctrl+o and sending keyup alt.
Maybe I'm missing something obvious, but it seems to me that it's impossible to assure that a key send with xdotool will result in the exact requested key while keeping the modifier state consistent with the physical keyboard state. I'm aware that xdotool currently doesn't work or even claim to work this way. But it would be great if it could do this, possibly as an option, to help in scenarios like the above.
My knowledge of X event handling is rather limited, but wouldn't it be possible to reset all current modifiers before sending a key, and after that reset the modifier state to the current physical state of the keyboard?
Comment #1
Posted on Jun 23, 2009 by Happy CamelConfirmed. There may be something we can do here, but it's likely to be hacky (and that's probably OK).
Before we start sending keys with XTestFakeKeyEvent, we should look at the current modifiers and attempt to clear them with fake release events (like faking an alt key release) - this will need testing.
Alternately, xdotool key with a --window target should work. However, checking just now shows the latest version of xdotool fails to do this correctly. Doing 'xdotool key --window ctrl+o' only sends 'o' and with no control modifier set. I'll fix that too.
Comment #2
Posted on Jul 1, 2009 by Happy Camel(No comment was entered for this change.)
Comment #3
Posted on Jul 1, 2009 by Happy CamelThis now works: xdotool key --window ctrl+shift+n
I tested by targeting gnome-terminal and sending 'ctrl+shift+n' and it popped up a new terminal as expected.
I haven't fixed the other problem you described - when using 'xdotool key' with no target, any active modifiers on the real keyboard are also part of sent keys from xdotool.
Comment #4
Posted on Jul 1, 2009 by Massive HorseThat's definitely an improvement, and it'll work fine for my purpose, thanks alot! I'll have to tell my users to AllowSendEvents for their terminals, though.
Concerning the remaining problem, I've looked into Xlib a little and found a way to get the current state of a keycode via XQueryDeviceState. I've attached a small test program that uses this method to query the state of a keycode. I think that using this method it should be possible to:
Query the modifier state. If any modifier is held down that isn't requested, disable it using a keyup.
Send the key, now in the requested modifier state.
Query the modifier state again and send the necessary events to make the logical modifier state match the current state.
Note that I can barely write c, so I took an easy route in the test program (i.e. simply getting the keyboard device by name).
I hope this can be helpful. If it isn't, please disregard. Unfortunately I don't know enough C to try this method for xdotool myself.
- keystate.c 1.96KB
Comment #5
Posted on Jul 2, 2009 by Happy CamelThis feature you propose (clear the modifier state temporarily) sounds like a good hack to get around the problem you're having. I don't know if it should be the default behavior (I have no preference) but both behaviors should be accessible with a flag or somesuch.
Your code is a good start. I'll look at putting this into xdotool. Thanks a bunch for the code sample :)
Comment #6
Posted on Jul 2, 2009 by Grumpy OxSimilar with bekel's approach, I also suggest to clear all the pressed modifier keys before send the key event in another post: https://bugzilla.novell.com/show_bug.cgi?id=491282#c4
BTW, besides XQueryDeviceState. we can also query whether modifier keys are pressed with XQueryKeymap or XQueryPointer.
Comment #7
Posted on Jul 3, 2009 by Happy CamelClearing the modifiers only seems to be necessary when using XTEST. Sending a keyboard event with XSendEvent allows you to explicitly set which modifiers are active.
I'll publish a new version with this fix when it's ready. Thanks for the details :)
Comment #8
Posted on Jul 10, 2009 by Happy Camelsvn r2200 has fixes for xdotool type and key{up,down,} commands to allow you to clear the active modifier mapping while xdo does it's thing.
% xdotool type --clearmodifiers "hello there"
While holding shift, the above should still type 'hello there'. Remove the --clearmodifiers and the above should type 'HELLO THERE'
I'm going to test a bit more than push a new release.
Comment #9
Posted on Jul 10, 2009 by Massive HorseThis works well for my original example, as well as modifiers ctrl and alt, but now
sleep 1; ./xdotool type --clearmodifiers "Hello World"
and holding down shift will produce inconsistent results, e.g.
HelLO WoRLD HeLLO WORLD etc
(This also happens without --clearmodifiers, so I'm not sure if it's related)
(r2204)
Comment #10
Posted on Jul 11, 2009 by Happy CamelWeird. Can you run xev and hold shift when the xev window is focused? Your report sounds like your shift key is repeating - xev's output will show you.
It's also possible there's some timing problem, but that seems on the unlikely side.
Let me know :)
Comment #11
Posted on Jul 11, 2009 by Massive HorseThat was my first thought, too, but my shift key is fine, it doesn't repeat at all. I've noticed that this doesn't happen if I run the above command with Shift-Return and keep holding down Shift (in which case readline seems to ignore the shift and just gets accept-line), i.e. the shift key is held throughout the sleep, too. Maybe it's just because of using sleep beforehand, but I don't really have a clue here...
Comment #12
Posted on Jul 30, 2009 by Happy GiraffeThe clearmodifiers option would also be useful for button presses (and maybe even in general for all inputs). For instance, I'm using XMonad and trying to emulate mouse button presses with the keyboard (because the mouse buttons on my laptop keyboard stopped working), and I'd like to reuse the modifier key for XMonad, but it sends both the modifier and the button click, when I only want the button click.
Comment #13
Posted on Aug 15, 2009 by Happy CamelI'll see what I can do about clearing mouse buttons. Should be roughly the same hack as clearing key modifiers.
Comment #14
Posted on Feb 24, 2010 by Happy Camelsvn r2655 makes --clearmodifiers clear button states during typing and 'key' commands and restores them the same way buttons are restored.
Comment #15
Posted on Feb 24, 2010 by Happy Camel@h.bekel, Are you still seeing weird shift behavior?
Comment #16
Posted on Feb 25, 2010 by Massive HorseAt least in r2660 I don't see weird shift behavior as described above any more.
Comment #17
Posted on Feb 25, 2010 by Happy CamelSweet. Thanks for confirming :)
New release should go out in a few days once I squash a few more bugs and feature requests.
Status: Fixed
Labels:
Type-Defect
Priority-Medium