Iocane: poison the rodent (simulate X11 mouse events from keyboard)

Iocane: the colorless, oderless, tasteless poision that will rid your system of its rodent infestation. Though no promises about its effectiveness against Rodents Of Unusual Size.

Iocane simulates mouse events from the keyboard. Iocane can be passed a few parameters which - ideally - could each have a key binding in your favorite window manager.

If iocane is called with no parameters it starts in interactive mode (which currently lacks documentation ... hey, I just wrote this this morning). In interactive mode the directional arrows or h/j/k/l keys move the mouse cursor. The number keys simulate button presses (1 = left button, 2 = middle, 3 = right). The page up and page down keys simulate mouse wheel activation. "q" quits from interactive mode returning any grabbed keys to their normal behavior. Key bindings are all controlled from a simple rc file.

Iocane can also be passed a series of commands on the command line or the filename for a script file with a list of iocane commands. Iocane can also read command from its standard input.

Iocane is conceptually similar to some functions of xdotool, but iocane should work under any window manager (or no wm at all), is much smaller, and the interactive mode allows for a sequence of many actions without the program having to start up and close down many times in rapid succession.

Please report bugs or feature requests here. Iocane is currently 127 lines of C, and it will remain small; in other words, features will only be added if the can be added without substantially increasing resource use.

Cloned, built, and working perfectly. Thank you. Looking at the source code, it looks like it would be fairly easy to add a "relative warp" command -- ratpoison's "ratrelwarp" command takes an x and y argument and moves the mouse pointer relative to the current position. Would that be something you'd like to add?

Thank you. It's just a bit more flexible than your predefined move sizes. It allows (for example) for an easy implementation of "small move left" and "big move left" bound to different keys, or for diagonal moves.

I've got a couple development (git) aur packages that I break enough already. This one is simple enough that I'm going to get it ready for a versioned release to put in the AUR. That way I can break it at my leasure without worrying about who else will be affected by my experimentation.

EDIT: OK I made an AUR package for this. The man page is still absent, but I figured I can still put a v0.1 out there for people to play with. I'll update to 0.2 after this goes through some testing and has a man page.

Thanks avx, A and C were things I was thinking of as well. I'll add B to the todo list to.

This first version was a quick and dirty hack - almost proof of concept type; it will take some adjusting to build in the flexibility for options such as these and other projects are a little higher on the priority list, but you can hope to see these features in a future release, probably by year-end.

I have just implemented (experimental forms) of A and part of B and they are on github. The AUR version will not be updated until I build in a bit more, do some testing, and prepare a version 0.2, but anyone who wants to try what is currently on my github can note the following changes.

Iocane can take multiple "chained" commands on the command line. They must each be separated by a <space><colon><space>. For example:

iocane 0 0 : sleep 1 : offset 640 480 : sleep 1 : powder

This will not do much of anything useful other than highlight how iocane can be used. This will move the mouse to 0,0 wait for one second, move the cursor 640px right and 480 down, wait one second, then move the cursor off screen (iocane powder kills rodents - at least those of normal size). You can see two new commands, "sleep <time>" and the absence of a command is read as specific x and y cooridinates.

I've also made a script mode, so if you pass a single "-" as iocanes only parameter, it will read from its stdin for a script file composed of iocane commands each on their own line. So as an example to parallel the above (useless) behavior:

I plan on trying to get "drag" working by adding mouse down and mouse up commands which could have a move/offset between them.

Avx, what features of multitouch would you be instersted in? As I understand it - which admittedly may not be very well - multitouch input is translated by a tool such as synclient into regular X11 mouse events. A two finger drag, for example, would be translated into a mouse wheel motion with common settings. Iocane can already simulate mouse wheel scrolling.

Avx, what features of multitouch would you be instersted in? As I understand it - which admittedly may not be very well - multitouch input is translated by a tool such as synclient into regular X11 mouse events. A two finger drag, for example, would be translated into a mouse wheel motion with common settings. Iocane can already simulate mouse wheel scrolling.

I don't know personally how the drivers translate the events(using the mtrack driver btw). But what I do know is that the drivers aren't yet perfect and some gestures aren't recognized often for me, so I thought using this - or another - tool might be of help.

Also, that would require support for more mousebuttons. My Logitech already has 11 buttons, while mtrack uses AFAIK 14 (or even more).

Good job on the rest, will try that out on the weekend.

One thing came to mind, don't know if that is possible, though. If I could somehow pass a window name or ID, it should be possible to set the cursor on 0,0 of that window (real content, not titlebar or some other decoration), so that wherever the window might be placed, I could script actions on it.

Any arbitrary number of buttons should be easy enough to simulate - provided the Xserver actually responds to events with that button number. An update I'll push to github tomorrow will include a few changes, including buttons 1-9, but if there is need/desire I could increase that. Sticking to 1-9 allows for the computationally cheaper hack of converting a string to a number by simple substracting 48 from the value of the first character; numbers greater than 9 would require the use of atoi() or some funky conditionals. In the grand scheme of things this is fairly trivial, but unless there is a real reason to use more than 9 mouse buttons I'd prefer to keep the lighter code.

Passing a window name and getting it's coordinates is possible but after considering it I've decided it wouldn't fit well in iocane. The reason being that to do a half-arsed job of it would be pretty easy. To do it properly, however, it would take quite a bit of scanning through recursive calls to XQueryTree, polling atoms/wmhints, matching strings, checking for subwindows in the case of reparenting window managers, and a bunch of other nonsense ... all to get two coordinates.

However iocane will play nicely with any tool that will provide those coordinates from a given window name, so I can imagine and invocation such as the following to move the mouse 10 pixels right and down from the top left of a window - lets call it FlamingSquirrel - and simulate a click there:

iocane $(cool_app FlamingSquirrel) : move 10 10 : button 1

Currently that could only be done from a command line invocation, not from a script or interactive session, as it requires shell processing for the command substitution. I can add support for this type of invocation in scripts and interactive mode as well. Then all you need to do is find (or write) a program that will give coordinates for a window given a title/name. I suspect such a program probably exists out there, or if you are comfortable with C, I could give you the starting framework for it as I made something that would have much code in common for another task on these forums (it's in jumpstart.c in the "misc" repo on my github).

See your problems on the buttons and that you'll prefer to keep it simple, maybe you/me/someone could provide a simple patch and keep it updated, so it's not a part of the main tree.

As more my plans, I'm not going to use this interactively I guess. Don't know about other systems, but I would bind it to keys in my configuration for FVWM where I could replace 'cool_app' easily with a function call around things like '$[w.id]' and friends. I'm pretty sure, not every DE/WM has that possibility, but `xprop` should be a start for many people.

What I see as a bigger problem here, is the use of "<somefile", since that is shell-bound. I'd prefer to have something like this

iocane ${HOME}/somefile $options

where "$options" can override settings in "somefile" on the fly. Granted, that adds a level of complexity I'm not sure you're willing to do, though.

You would not believe , I was searching for 'xdotool' alternative a few minutes ago. Though it is not a complete replacement. But hey it is just a new born baby....I like it , especially when combined with something like this :

iocane p && xinput disable OM

and to enable

xinput enable OM

Last edited by illusionist (2012-11-01 05:53:15)

Never argue with stupid people,They will drag you down to their level and then beat you with experience.--Mark Twain@github

Thanks illusionist. Iocane will never be a complete xdotool replacement. Xdotool is well made, there is no reason to make another program that does everything just the same. Iocane is and will only be about simulating mouse events and - in that sense - is more limited than xdotool. But I hope iocane's flexibility in script or interactive mode will give it advantages over xdotool on the tasks for which it is designed.

I did just put up a version 0.2 which introduced notable changes. There is now a (limited) man page which describes the various commands that iocane recongizes. Note that the "offset" command is now gone, but has been replaced by "move" which now moves the selected number of pixels. The behavior of the previous move command - to go to specific coordinates - is now acheived by just passing two coordinates with no command.

A colon-separated list of commands can be passed on the command line, or iocane can be run in script mode by passing a single "-" as the first parameter. In script mode iocane will read either from its stdin or from a script file provided as the second parameter.

I have also made it so iocane can respond to any arbitrary mouse button numbers, but these are simply passed on to the X server, so the response depends on the server being able to handle them.

I have also experimented with simulating "drag-like" events, but there doesn't seem to be any practical way of accomplishing this. I can simulate mouse-down and mouse-up events separately, but these are completely useless and tend to be either treated like regular clicks, or just ignored entirely.

Lastly, the keybindings are now all controlled from a rc file (e.g. ~/.iocanerc). A sample rc file with a good set of keybindings is packaged with v0.2.

EDIT: I just installed gtkpod (the first gtk3 program I could find) and confirmed this is a problem. I'll start investigating.

EDIT2: I have been browsing the source code of gtk3 .... that is a miserable tangle of nonsense. I also made a very simple gtk3 "hello world" type program (which is larger than my window manager ... why the hell do people like these toolkits?). I have further confirmed that gtk3 programs do not properly receive events sent via XSendEvent. I have no leads yet on how to solve this.

Hi Trilby , maybe you can refer to source code for X Server itself. X server implements mousekeys. (can be toggled using shift+numlock). Mousekeys works correctly with all apps. Maybe you can browse the source code for that.

Mousekeys doesn't have any of its own actual code - it is basically just a configuration for xbindkeys to bind certain keys to actions.

The center keypad button is mapped to "action = PointerButton()". But I grepped through the entire source tree of xbindkeys and every one of it's dependencies (through evdev) to find where this action is defined. I couldn't find it anywhere.

Hi Trilby, I binded the xdotool click functions to my numeric keypad, and found that some (not all) clicking actions of xdotool do work in Gtk3 apps. for example in nautilus 3.6, the right-click doesnt work but the left click works in it.also, scrolling action works.the problem is only when there is some menu. the left click doesn't work on menus. I tried this with both gtk2 and gtk3 apps.so , i think you can refer to source code of xdotool. what do you think? is this a bug in Gtk toolkit itself?