xterm_icon

Connecting an old API

x-term icon, not really pretty

I managed to improve my program a bit this week-end, the icon on the program sending the event is now converted to a growl icon within the program and not round-tripped via the file-system. Using the file-system has the advantage that I could use existing APIs: X11 knows how to export files in the x-bitmap format, a format that strangely enough, OS X still can read. Safari on OS X is one of the last browsers that supports that strange format (don’t bother checking for buffer overflows, I already did).

Doing the conversion explicitly in the program required some API archeology, I used XLib a bit when I was in the university, but I have largely forgotten what I did then, and I was mostly concerned in pushing pixels out, her the goal is to read some structures provided by the window manager.

I managed to get something that kind of works, which basically mimics the behaviour of XWriteBitmapFile, resolving the pixels using XGetPixel. This means I can get the same black/white images I already had, but instead of pushing to a file, I write the data into a buffer which I give the Core Image, which I used to scale the image and serialise it for Growl.

The frustrating part is that XGetPixel does not return information in RGB format, instead I get a reference in some colour table. From the documentation, I should call XQueryColor to resolve the colour into RGB, but when I do so, the whole program crashes with an illegal access. So I’m stuck with OK images for basic programs like xlogo and broken ones for things link xterm.

It is interesting to consider the two graphic APIs I’m trying to connect: their designs are a quarter century apart the first one handles colours as precious resources that are named and allocated and associated with a screen, you cannot simply work with an unattached image buffer. The other is all about buffers and transformations, memory is not the main constraint, but structuring the data-flow in a way that is understandable for the GPU is.

Anyhow, the new version is available in the releases section of github.

flattr this!

Growl notification displaying “xkbgrowl works!”

xkbgrowl – memory management

Growl notification displaying “xkbgrowl works!”

I have created a new release for xkbgrowl, the main visible difference is that the tool should now use the XQuartz icon as default icon, instead of the generally missing X11 app icon. Less visible is the change I did to the code related to memory management. The original code was using C style strings and memory pools and doing manual reference management on the objective-C side. I rewrote the code to use std::string as much as possible, and it is compiled using ARC. As a result, the code is simpler, and the only manual memory management is related to X11 structures. Finally, instead of a simple zip archive, I built an installer package, which should, hopefully, put all files in the right places. The package is available from github.

The change I would like to do, if I have the time, is to rewrite the image conversion logic, currently the tools emits a xbm file on one side, and reads it from the other, which involves a round-trip to the file-system, but also forces all the images into 1-bit depth.

flattr this!

xlogo: it works

xkbgrowl on Google Code

xlogo: it works

Quite some time has passed since I last updated my small growl tool. I finally cleaned up the code and uploaded all of it to a google code repository. I also fixed a few bugs: the program should no longer crash when retrieving a non existing desktop manager icon, text encoding are now done according to the spec (iso-latin-1), and more information is added to the notification text, including the name of the X11 display used by the client. For more information, have a look at https://code.google.com/p/xkbgrowl/.
Edit: the project has now its own page on this blog.

flattr this!

screen & X11

One of the most powerful command line tools under Unix is screen. This tool lets you run a terminal emulator from within a terminal emulator. This is way more useful as it sound, it basically means you can have command-line sessions that are persistent between connections. So if you have a server, you can let the session run, even while you disconnect from the server. You can also have multiple logical terminals running in the same window, a shared information bar and of course, and abstruse configuration format. Here is the configuration I have, largely inspired by the one of a colleague. It sets control-Y to trigger screen commands, displays a bar at the bottom, with the name of the machine, the various screen sessions, the dimension of the terminal and the current time.

escape ^Yy
startup_message off
defutf8 on
info
vbell off
wrap off
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %d/%m%{W}%c %{g}]'
#!/bin/bash
set +e
for i in {10..15}
  do
  export DISPLAY="localhost:${i}.0"
  xdpyinfo -display $DISPLAY > /dev/null 2> /dev/null
  if [ $? -eq 0 ] ; then break; fi
done
message="DISPLAY: $DISPLAY"
xkbbell -display $DISPLAY "$message"

One issue with string is the definition of the X11 DISPLAY variable. As per Unix rules, this is inherited from the shell from which screen was started, so if you connect using ssh -Y it will be correct for the first ssh connection. The next time you connect, it probably will point to a non existing port. To solve this issue, I wrote a small shell script that scans for the right port, sets DISPLAY accordingly and sends a notification about it using xkbbell (as you want to inherit the DISPLAY variable, you should source this script.

#!/bin/bash
original=`basename $0`
command=${original:1}
$command "$@"
if [ $? -eq 0 ]; then
  xkbbell -v -100 -display $DISPLAY "$command $1: success"
else
  xkbbell -v 100 -display $DISPLAY "$command $1: failure"
fi

Finally I wrote a wrapper script that runs a command and then displays a status message using xkbbell once the command has finished running. The notification gets routed using xkbgrowl and displayed by Growl on my Mac OS X laptop.
The following script basically tries to run a command with the same name as itself with the first character stripped. So if you want to create a version of make that displays a notification once finished, you can write a script called xmake with the following code. For other commands, you just need to create a symbolic link (or even a hard one for the matter).

flattr this!

Set up KDE to send X11 Bell Events

KDE System Settings, use system bell instead of system notification

If you are connecting to a remote Linux box and are using KDE applications over X11, you can set up KDE to use X11 keyboard notifications. If you are using xkbgrowl, this means errors will display as growl notifications. If you set the volume to zero, you won’t get a beep, but instead a low priority notification. To set the preferences, launch systemsettings, select the notification item / icon and then the System Bell item and check the Use system bell instead of system notification item.

flattr this!

xlogo: it works

xkbgrowl

xlogo: it works

A few weeks back, I posted about a way to setup Growl to display X11 keyboard notifications. While the technique I described works, it was not really satisfying. So I decided to write a small program that would offer the same functionality (and a few others), the result is xkbgrowl.

Edit: all information has been moved into a dedicated page.

flattr this!

x11_logo

xkbbell & xkbevd

X11 Logo ⓒ MIT

So I started working with Eclipse on Linux. I was hoping to redefine the keyboard shortcuts to use the meta key, as I’m connecting remotely with a Mac OS X laptop and X11. I though it would be an easy task. I was wrong. In KDE applications, this just requires you to select the action, type in the new shortcut and it is done. With gtk2 this does not work. I checked with xev, the key events are the expected one: left-meta. I searched online, no useful information, just other lost users and the nagging feeling that Gnome does not honor the xmod file. Changing the keyboard settings in the gnome-control-center has no effect, this might be related to the fact I’m running a KDE desktop, but I have hardly the choice, on my virtual machine Gnome just crashes. I tried reproducing the issue on my laptop but installing gnome-terminal and launching result in the program dying horribly on launch, probably because there is no gnome desktop running, and plain X11 is way too scary. I have not solved the issue (getting rid of all things gtk would probably be the sanest solution), but digging around I stumbled on a interesting X11 extension: X Keyboard.

I have written a small binary program called xbkgrowl that does the same thing than the script presented here. It does not require any configuration file and does a few other things, link priority translation. Please check it out.

In short, this extension can be used to control the lights and modifiers on the keyboard, it also gives a way of sending notifications to the X11 server. This would be something useful when I’m working on a remote Linux box, streaming back sounds is wasteful and far from stable. On my Mac, I have Growl installed so it would be really convenient to be able to trigger growl notifications. There are versions of Growl, or Growl-like project under linux, and Growl has network support, but this requires a fixed IP adresses, an open port on my Mac, and installing software or at least writing some script. But actually by using the X keyboard dæmon and an old command line you can do this using the X11 connection and without installing anything on the Linux side.

  • Install growlnotify on Mac OS X.
  • Create a configuration file xkbevd.cf with the following content:
    Bell()  shell "/usr/local/bin/growlnotify --message \"$(name)\" --appIcon X11; true "
    
  • Start the X11 server (you can just start xlogo)
  • Start the X keyboard dæmon with the following command xkbevd -cfg xkbevd.cf -bg. This will start the program in background using the configuration defined in xkbevd.cf.
  • You can now trigger a notification using the command xkbbell message, for instance xkbbell "lasers offline". This should work both locally and on remote machines.

    This only works if the X11 display on your Unix box point back to the X11 server on your Mac. You can test this by launching xlogo on the Unix box, it should display the logo on the Mac’s screen. If you have connected using ssh, make sure you selected the -Y option.

Some notes:

  • This is an old protocol (1995) which has never been seriously supported. Use at your own risk.
  • The xkbevd program, is buggy. In particular, there seems to be some issue with the memory buffer used for command substitution, no end marker is inserted, so when a long message is followed by a short one, the short command will have the last characters from the long one at its end. This is why the second command is true, which ignores all its arguments.
  • While the xkbbell command recognises many options, only the volume flag seems to be carried to the server. The volume is in the $(volume) variable, with the value of 50 added.
  • The notifications are carried over NX, but the text message is discarded.
  • There are some standard bell names defined in the header files, but any arbitrary ASCII string seems to work.
  • Instead of growl, you can also use the Mac OS X command say. In that case, the configuration file would be:
    Bell()  shell "/usr/bin/say \"$(name)\" ; true "
    
  • It is possible to define different actions for different messages, so for instance.
    Bell()  shell "/usr/local/bin/growlnotify --message \"$(name)\" --appIcon X11; true "
    Bell(Warning) shell "/usr/bin/say Warning
    

I more or less fixed the gtk issue with xmodmap, but this is really a kludge.

flattr this!