Shallow Thoughts : tags : crikey

Akkana's Musings on Open Source Computing and Technology, Science, and Nature.

Tue, 26 Mar 2013

Pasting the Primary X Selection into Firefox

Sometimes I need to take a URL from some text app -- like a shell window, or an IRC comment -- and open it in Firefox.

If it's a standard http://, that's trivial: I highlight the URL with my house (often a doubleclick will do it), go to my Firefox window and middleclick somewhere in the content area, anywhere that's not a link, and Firefox goes to the URL.

That works because selecting anything, in X, copies the selection to the Primary selection buffer. The Primary selection is different from the Clipboard selection that's used with Windows and Mac style Ctrl-X/Ctrl-C/Ctrl-V copy and paste; it's faster and doesn't require switching between keyboard and mouse. Since your hand is already on the mouse (from selecting the text), you don't have to move to the keyboard to type Ctrl-C, then back to the mouse to go to the Firefox window, then back to the keyboard to type Ctrl-V.

But it fails in some cases. Like when someone says in IRC, "There's a great example of that at coolhacks.org/greatexample". You can highlight coolhacks.org/greatexample and middleclick in Firefox all you want, but Firefox doesn't recognize it as a URL and won't go there. Or if I want to highlight a couple of search terms and pass them into a Google search.

(Rant: middlemouse used to work for these cases, but it was disabled -- without even an option for getting it back -- due to a lot of whining in bugzilla by people coming from Windows backgrounds who didn't like middleclick paste because they found it unexpected, yet who weren't willing to turn it off with the middlemouse.contentLoadURL pref).

So in those cases, what I've been doing is:

It works, but it's a lot more steps, and entails several switches between keyboard and mouse. Frustrating!

It would be a little less frustrating if I had a key binding in Firefox that said "Paste the current X primary selection." A web search shows that quite a few other people have been bothered by this problem -- for instance, here and here -- but without any solutions. Apparently in a lot of apps, Ctrl-Insert inserts the Primary X selection -- but in Firefox and a few others, it inserts the Clipboard instead, just like Ctrl-C.

I could write my own fix, by unzipping Firefox's omni.ja file and editing various .xul and .js files inside it. But if I were doing that, I could just as easily revert Firefox's original behavior of going to the link. Neither of these is difficult; the problem is that every time I Firefox updates (which is about twice a week these days), things break until I manually go in and unzip the jar and make my changes again. I used to do that, but I got tired of needing to do it so often. And I tried to do it via a Firefox extension, until Mozilla changed the Firefox extension API so that extensions couldn't modify key bindings any more.

Since Firefox changes so often, it's nicer to have a solution that's entirely outside of Firefox. And a comment in one of those discussion threads gave me an idea: make a key binding in my window manager that uses xset to copy the primary selection to the clipboard, then use my crikey program to insert a fake Ctrl-V that Firefox will see.

Here's a command to do that:

xsel -o -p | xsel -i -b; crikey -s 1 "^V"

xsel -o prints a current X selection, and -p specifies the Primary. xsel -i sets an X selection to whatever it gets on standard input (which in this case will be whatever was in the Primary selection), and -b tells it to set the Clipboard selection.

Then crikey -s 1 "^V" waits one second (I'll probably reduce this after more testing) and then generates an X event for a Ctrl-V.

I bound that command to Ctrl-Insert in my window manager, Openbox, like this:

<keybind key="C-Insert">
  <action name="Execute">
    <execute>/bin/sh -c 'xsel -o -p | xsel -i -b; crikey -s 1 "^V"'</execute>
  </action>
</keybind>
Openbox didn't seem happy with the pipe, so I wrapped the whole thing in a sh -c.

Now, whenever I type Ctrl-Insert, whatever program I'm in will do a Ctrl-V but insert the Primary selection rather than the Clipboard. It should work in other recalcitrant programs, like LibreOffice, as well. In Firefox, now, I just have to type Ctrl-L Ctrl-Insert Return.

Of course, it's easy enough to make a binding specific to Firefox that does the Ctrl-L and the Return automatically. I've bound that to Alt-Insert, and its execute line looks like this:

    <execute>/bin/sh -c 'xsel -o -p | xsel -i -b; crikey -s 1 "^L^V\\n"'</execute>

Fun with Linux! Now the only hard part will be remembering to use the bindings instead of doing things the hard way.

Tags: , , , ,
[ 20:35 Mar 26, 2013    More linux/cmdline | permalink to this entry | ]

Wed, 19 Aug 2009

Crikey 0.8.3: bug fixes and several new syntaxes

Sometimes I love open source. A user contacted me about my program Crikey!, which lets you generate key events to do things like assign a key that will type in a string you don't want to type in by hand. He had some thorny problems where crikey was failing, and a few requests, like sending Alt and other modifier keys.

We corresponded a bit, figured out exactly how things should work and some test cases, went through a couple iterations of changes where I got lots of detailed and thoughtful feedback and more test cases, and now Crikey can do an assortment of new useful stuff.

New features: crikey now handles number codes like \27, modifier keys like \A for alt, does a better job with symbols like \(Return\), and handles a couple of new special characters like \e for escape. It also works better at sending window manager commands, like "\A\t" to change the active window.

I've added some better documentation on all the syntaxes it understands, both on the web page and in the -h and -l (longhelp) command-line arguments, and made a release: crikey 0.8.3.

Plus: a list of great regression tests that I can use when testing future updates (in the file TESTING in the tarball).

Tags: , , ,
[ 17:38 Aug 19, 2009    More programming | permalink to this entry | ]

Wed, 14 Jan 2009

Crikey 0.8

Mostly this week has been consumed with preparations for LCA ... but programming is a sickness. When you get email from someone suggesting something relatively simple and obviously useful, well ... it's simply impossible not to pull out that emacs window and start typing.

And so it was when I got a request for a backspace character in crikey. Of course backspace and delete seem like perfectly reasonable and useful characters to want; don't know why I didn't think of putting them in before. So I did.

But while I was in there, suddenly it occurred to me that it really wouldn't be much harder to let users specify any key by symbol. (Did I mention being a programmer is a sickness?) And then I realized that specifying control characters with a caret, like ^H, would also be quite useful. (Did I mention that ...)

So anyway, now there's a Crikey 0.8 and it's time to get back to packing and endless fiddling with my talk slides. Except, wait, I need to update my netscheme script to work right with the new laptop, and ...

Did I mention that programming is a sickness?

Tags: ,
[ 21:56 Jan 14, 2009    More programming | permalink to this entry | ]

Sun, 25 May 2008

Crikey in Python, and generating key events with XTest

A user on the One Laptop Per Child (OLPC, also known as the XO) platform wrote to ask me how to use crikey on that platform.

There are two stages to getting crikey running on a new platform:

  1. Build it, and
  2. Figure out how to make a key run a specific program.

The crikey page contains instructions I've collected for binding keys in various window managers, since that's usually the hard part. On normal Linux machines the first step is normally no problem. But apparently the OLPC comes with gcc but without make or the X header files. (Not too surprising: it's not a machine aimed at developers and I assume most people developing for the machine cross-compile from a more capable Linux box.)

We're still working on that (if my correspondant gets it working, I'll post the instructions), but while I was googling for information about the OLPC's X environment I stumbled upon a library I didn't know existed: python-xlib. It turns out it's possible to do most or all of what crikey does from Python. The OLPC is Python based; if I could write crikey in Python, it might solve the problem. So I whipped up a little key event generating script as a test.

Unfortunately, it didn't solve the OLPC problem (they don't include python-xlib on the machine either) but it was a fun exercises, and might be useful as an example of how to generate key events in python-xlib. It supports both event generating methods: the X Test extension and XSendEvent. Here's the script: /pykey-0.1.

But while I was debugging the X Test code, I had to solve a bug that I didn't remember ever solving in the C version of crikey. Sure enough, it needed the same fix I'd had to do in the python version. Two fixes, actually. First, when you send a fake key event through XTest, there's no way to specify a shift mask. So if you need a shifted character like A, you have to send KeyPress Shift, KeyPress a. But if that's all you send, XTest on some systems does exactly what the real key would do if held down and never released: it autorepeats. (But only for a little while, not forever. Go figure.)

So the real answer is to send KeyPress Shift, KeyPress a, KeyRelease a, KeyRelease Shift. Then everything works nicely. I've updated crikey accordingly and released version 0.7 (though since XTest isn't used by default, most users won't see any change from 0.6). In the XSendEvent case, crikey still doesn't send the KeyRelease event -- because some systems actually see it as another KeyPress. (Hey, what fun would computers be if they were consistent and always predictable, huh?)

Both C and Python versions are linked off the crikey page.

Tags: , , ,
[ 15:50 May 25, 2008    More programming | permalink to this entry | ]