Shallow Thoughts : tags : X11

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

Thu, 06 Apr 2017

Clicking through a translucent window: using X11 input shapes

It happened again: someone sent me a JPEG file with an image of a topo map, with a hiking trail and interesting stopping points drawn on it. Better than nothing. But what I really want on a hike is GPX waypoints that I can load into OsmAnd, so I can see whether I'm still on the trail and how to get to each point from where I am now.

My PyTopo program lets you view the coordinates of any point, so you can make a waypoint from that. But for adding lots of waypoints, that's too much work, so I added an "Add Waypoint" context menu item -- that was easy, took maybe twenty minutes. PyTopo already had the ability to save its existing tracks and waypoints as a GPX file, so no problem there.

[transparent image viewer overlayed on top of topo map] But how do you locate the waypoints you want? You can do it the hard way: show the JPEG in one window, PyTopo in the other, and do the "let's see the road bends left then right, and the point is off to the northwest just above the right bend and about two and a half times as far away as the distance through both road bends". Ugh. It takes forever and it's terribly inaccurate.

More than once, I've wished for a way to put up a translucent image overlay that would let me click through it. So I could see the image, line it up with the map in PyTopo (resizing as needed), then click exactly where I wanted waypoints.

I needed two features beyond what normal image viewers offer: translucency, and the ability to pass mouse clicks through to the window underneath.

A translucent image viewer, in Python

The first part, translucency, turned out to be trivial. In a class inheriting from my Python ImageViewerWindow, I just needed to add this line to the constructor:


Plus one more step. The window was translucent now, but it didn't look translucent, because I'm running a simple window manager (Openbox) that doesn't have a compositor built in. Turns out you can run a compositor on top of Openbox. There are lots of compositors; the first one I found, which worked fine, was xcompmgr -c -t-6 -l-6 -o.1

The -c specifies client-side compositing. -t and -l specify top and left offsets for window shadows (negative so they go on the bottom right). -o.1 sets the opacity of window shadows. In the long run, -o0 is probably best (no shadows at all) since the shadow interferes a bit with seeing the window under the translucent one. But having a subtle .1 shadow was useful while I was debugging.

That's all I needed: voilà, translucent windows. Now on to the (much) harder part.

A click-through window, in C

X11 has something called the SHAPE extension, which I experimented with once before to make a silly program called moonroot. It's also used for the familiar "xeyes" program. It's used to make windows that aren't square, by passing a shape mask telling X what shape you want your window to be. In theory, I knew I could do something like make a mask where every other pixel was transparent, which would simulate a translucent image, and I'd at least be able to pass clicks through on half the pixels.

But fortunately, first I asked the estimable Openbox guru Mikael Magnusson, who tipped me off that the SHAPE extension also allows for an "input shape" that does exactly what I wanted: lets you catch events on only part of the window and pass them through on the rest, regardless of which parts of the window are visible.

Knowing that was great. Making it work was another matter. Input shapes turn out to be something hardly anyone uses, and there's very little documentation.

In both C and Python, I struggled with drawing onto a pixmap and using it to set the input shape. Finally I realized that there's a call to set the input shape from an X region. It's much easier to build a region out of rectangles than to draw onto a pixmap.

I got a C demo working first. The essence of it was this:

    if (!XShapeQueryExtension(dpy, &shape_event_base, &shape_error_base)) {
        printf("No SHAPE extension\n");

    /* Make a shaped window, a rectangle smaller than the total
     * size of the window. The rest will be transparent.
    region = CreateRegion(outerBound, outerBound,
                          XWinSize-outerBound*2, YWinSize-outerBound*2);
    XShapeCombineRegion(dpy, win, ShapeBounding, 0, 0, region, ShapeSet);

    /* Make a frame region.
     * So in the outer frame, we get input, but inside it, it passes through.
    region = CreateFrameRegion(innerBound);
    XShapeCombineRegion(dpy, win, ShapeInput, 0, 0, region, ShapeSet);

CreateRegion sets up rectangle boundaries, then creates a region from those boundaries:

Region CreateRegion(int x, int y, int w, int h) {
    Region region = XCreateRegion();
    XRectangle rectangle;
    rectangle.x = x;
    rectangle.y = y;
    rectangle.width = w;
    rectangle.height = h;
    XUnionRectWithRegion(&rectangle, region, region);

    return region;

CreateFrameRegion() is similar but a little longer. Rather than post it all here, I've created a GIST: transregion.c, demonstrating X11 shaped input.

Next problem: once I had shaped input working, I could no longer move or resize the window, because the window manager passed events through the window's titlebar and decorations as well as through the rest of the window. That's why you'll see that CreateFrameRegion call in the gist: -- I had a theory that if I omitted the outer part of the window from the input shape, and handled input normally around the outside, maybe that would extend to the window manager decorations. But the problem turned out to be a minor Openbox bug, which Mikael quickly tracked down (in openbox/frame.c, in the XShapeCombineRectangles call on line 321, change ShapeBounding to kind). Openbox developers are the greatest!

Input Shapes in Python

Okay, now I had a proof of concept: X input shapes definitely can work, at least in C. How about in Python?

There's a set of python-xlib bindings, and they even supports the SHAPE extension, but they have no documentation and didn't seem to include input shapes. I filed a GitHub issue and traded a few notes with the maintainer of the project. It turned out the newest version of python-xlib had been completely rewritten, and supposedly does support input shapes. But the API is completely different from the C API, and after wasting about half a day tweaking the demo program trying to reverse engineer it, I gave up.

Fortunately, it turns out there's a much easier way. Python-gtk has shape support, even including input shapes. And if you use regions instead of pixmaps, it's this simple:

    if self.is_composited():
        region = gtk.gdk.region_rectangle(gtk.gdk.Rectangle(0, 0, 1, 1))
        self.window.input_shape_combine_region(region, 0, 0)

My came out nice and simple, inheriting from and adding only translucency and the input shape.

If you want to define an input shape based on pixmaps instead of regions, it's a bit harder and you need to use the Cairo drawing API. I never got as far as working code, but I believe it should go something like this:

    # Warning: untested code!
    bitmap = gtk.gdk.Pixmap(None, self.width, self.height, 1)
    cr = bitmap.cairo_create()
    # Draw a white circle in a black rect:
    cr.rectangle(0, 0, self.width, self.height)

    # draw white filled circle
    cr.arc(self.width / 2, self.height / 2, self.width / 4,
           0, 2 * math.pi);

    self.window.input_shape_combine_mask(bitmap, 0, 0)

The translucent image viewer worked just as I'd hoped. I was able to take a JPG of a trailmap, overlay it on top of a PyTopo window, scale the JPG using the normal Openbox window manager handles, then right-click on top of trail markers to set waypoints. When I was done, a "Save as GPX" in PyTopo and I had a file ready to take with me on my phone.

Tags: , , ,
[ 17:08 Apr 06, 2017    More programming | permalink to this entry | comments ]

Sun, 31 Jan 2016

Setting mouse speed in X

My mouse died recently: the middle button started bouncing, so a middle button click would show up as two clicks instead of one. What a piece of junk -- I only bought that Logitech some ten years ago! (Seriously, I'm pretty amazed how long it lasted, considering it wasn't anything fancy.)

I replaced it with another Logitech, which turned out to be quite difficult to find. Turns out most stores only sell cordless mice these days. Why would I want something that depends on batteries to use every day at my desktop?

But I finally found another basic corded Logitech mouse (at Office Depot). Brought it home and it worked fine, except that the speed was way too fast, much faster than my old mouse. So I needed to find out how to change mouse speed.

X11 has traditionally made it easy to change mouse acceleration, but that wasn't what I wanted. I like my mouse to be fairly linear, not slow to start then suddenly zippy. There's no X11 property for mouse speed; it turns out that to set mouse speed, you need to call it Deceleration.

But first, you need to get the ID for your mouse.

$ xinput list| grep -i mouse
⎜   ↳ Logitech USB Optical Mouse                id=11   [slave  pointer  (2)]

Armed with the ID of 11, we can find the current speed (deceleration) and its ID:

$ xinput list-props 11 | grep Deceleration
        Device Accel Constant Deceleration (259):       3.500000
        Device Accel Adaptive Deceleration (260):       1.000000

Constant deceleration is what I want to set, so I'll use that ID of 259 and set the new deceleration to 2:

$ xinput set-prop 11 259 2

That's fine for doing it once. But what if you want it to happen automatically when you start X? Those constants might all stay the same, but what if they don't?

So let's build a shell pipeline that should work even if the constants aren't.

First, let's get the mouse ID out of xinput list. We want to pull out the digits immediately following "id=", and nothing else.

$ xinput list | grep Mouse | sed 's/.*id=\([0-9]*\).*/\1/'

Save that in a variable (because we'll need to use it more than once) and feed it in to list-props to get the deceleration ID. Then use sed again, in the same way, to pull out just the thing in parentheses following "Deceleration":

$ mouseid=$(xinput list | grep Mouse | sed 's/.*id=\([0-9]*\).*/\1/')
$ xinput list-props $mouseid | grep 'Constant Deceleration'
        Device Accel Constant Deceleration (262):       2.000000
$ xinput list-props $mouseid | grep 'Constant Deceleration' | sed 's/.* Deceleration (\([0-9]*\)).*/\1/'

Whew! Now we have a way of getting both the mouse ID and the ID for the "Constant Deceleration" parameter, and we can pass them in to set-prop with our desired value (I'm using 2) tacked onto the end:

$ xinput set-prop $mouseid $(xinput list-props $mouseid | grep 'Constant Deceleration' | sed 's/.* Deceleration (\([0-9]*\)).*/\1/') 2

Add those two lines (setting the mouseid, then the final xinput line) wherever your window manager will run them when you start X. For me, using Openbox, they go in .config/openbox/autostart. And now my mouse will automatically be the speed I want it to be.

Tags: , ,
[ 13:42 Jan 31, 2016    More linux | permalink to this entry | comments ]

Sun, 11 Oct 2015

How to get X output redirection back

X stopped working after my last Debian update.

Rather than run a login manager, I typically log in on the console. Then in my .zlogin file, I have:

if [[ $(tty) == /dev/tty1 ]]; then
  # do various things first, then:
  startx -- -dumbSched >& $HOME/.xsession-errors
Ignore -dumbSched for now; it's a fix for a timing problem openbox has when bringing up initial windows. The relevant part here is that I redirect both standard output and standard error to a file named .xsession-errors. That means that if I run GIMP or firefox or any other program from a menu, and later decide I need to see their output to look for error messages, all I have to do is check that file.

But as of my last update, that no longer works. Plain startx, without the output redirection, works fine. But with the redirect, X pauses for five or ten seconds, then exits, giving me my prompt back but with messed-up terminal settings, so I have to type reset before I do anything else.

Of course, I checked that .xsession file for errors, and also the ~/.local/share/xorg/Xorg.0.log file it referred me to (which is where X stores its log now that it's no longer running as root). It seems the problem is this:

Fatal server error:
(EE) xf86OpenConsole: VT_ACTIVATE failed: Operation not permitted
Which wasn't illuminating but at least gave me a useful search keyword.

I found a fair number of people on the web having the same problem. It's related to the recent Xorg change that makes it possible to run Xorg as a regular user, not root. Not that running as a user should have anything to do with capturing standard output and error. But apparently Xorg running as a user is dependent on what sort of virtual terminal it was run from; and the way it determines the controlling terminal, apparently, is by checking stderr (and maybe also stdout).

Here's a slightly longer description of what it's doing, from the ever useful Arch Linux forums.

I'm fairly sure there are better ways of determining a process's controlling terminal than using stderr. For instance, a casual web search turned up ctermid; or you could do checks on /dev/tty. There are probably other ways.

The Arch Linux thread linked above, and quite a few others, suggest adding the server option -keeptty when starting X. The Xorg manual isn't encouraging about this as a solution:

Prevent the server from detaching its initial controlling terminal. This option is only useful when debugging the server. Not all platforms support (or can use) this option.
But it does work.

I found several bugs filed already on the redirection problem. Freedesktop has a bug report on it, but it's more than a year old and has no comments or activity: Freedesktop bug 82732: rootless X doesn't start if stderr redirected.

Redhat has a bug report: Xorg without root rights breaks by streams redirection, and supposedly added a fix way back in January in their package version xorg-x11-xinit-1.3.4-3.fc21 ... though it looks like their fix is simply to enable -keeptty automatically, which is better than nothing but doesn't seem ideal. Still, it does suggest that it's probably not harmful to use that workaround and ignore what the Xorg man page says.

Debian didn't seem to have a bug filed on the problem yet (not terribly surprising, since they only enabled it in unstable a few days ago), so I used reportbug to attempt to file one. I would link to it here if Debian had an actual bug system that allowed searching for bugs (they do have a page entitled "BTS Search" but it gives "Internal Server Error", and the alternate google groups bug search doesn't find my bug), or if their bug reporting system acknowledged new bugs by emailing the submitter the bug number. In truth I strongly suspect that reportbug is actually a no-op and doesn't actually do anything with the emailed report.

But I'm not sure the Debian bug matters since the real bug is Xorg's, and it doesn't look like they're very interested in the problem. So anyone who wants to be able to access output of programs running under X probably needs to use -keeptty for the forseeable future.

Update: the bug acknowledgement came in six hours later. It's bug 801529.

Tags: , ,
[ 12:31 Oct 11, 2015    More linux | permalink to this entry | comments ]

Tue, 08 Jul 2014

Big and contrasty mouse cursors

[Big mouse cursor from Comix theme] My new home office with the big picture windows and the light streaming in come with one downside: it's harder to see my screen.

A sensible person would, no doubt, keep the shades drawn when working, or move the office to a nice dim interior room without any windows. But I am not sensible and I love my view of the mountains, the gorge and the birds at the feeders. So accommodations must be made.

The biggest problem is finding the mouse cursor. When I first sit down at my machine, I move my mouse wildly around looking for any motion on the screen. But the default cursors, in X and in most windows, are little subtle black things. They don't show up at all. Sometimes it takes half a minute to figure out where the mouse pointer is.

(This wasn't helped by a recent bug in Debian Sid where the USB mouse would disappear entirely, and need to be unplugged from USB and plugged back in before the computer would see it. I never did find a solution to that, and for now I've downgraded from Sid to Debian testing to make my mouse work. I hope they fix the bug in Sid eventually, rather than porting whatever "improvement" caused the bug to more stable versions. Dealing with that bug trained me so that when I can't see the mouse cursor, I always wonder whether I'm just not seeing it, or whether it really isn't there because the kernel or X has lost track of the mouse again.)

What I really wanted was bigger mouse cursor icons in bright colors that are visible against any background. This is possible, but it isn't documented at all. I did manage to get much better cursors, though different windows use different systems.

So I wrote up what I learned. It ended up too long for a blog post, so I put it on a separate page: X Cursor Themes for big and contrasty mouse cursors.

It turned out to be fairly complicated. You can replace the existing cursor font, or install new cursor "themes" that many (but not all) apps will honor. You can change theme name and size (if you choose a scalable theme), and some apps will honor that. You have to specify theme and size separately for GTK apps versus other apps. I don't know what KDE/Qt apps do.

I still have a lot of unanswered questions. In particular, I was unable to specify a themed cursor for xterm windows, and for non text areas in emacs and firefox, and I'd love to know how to do that.

But at least for now, I have a great big contrasty blue mouse cursor that I can easily see, even when I have the shades on the big windows open and the light streaming in.

Tags: ,
[ 10:25 Jul 08, 2014    More linux | permalink to this entry | comments ]

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". You can highlight 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>
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 | comments ]

Mon, 31 Oct 2011

Synaptics horizontal scrolling (and other touchpad configurations)

My new netbook (about which, more later) has a trackpad with areas set aside for both vertical and horizontal scrolling. Vertical scrolling worked out of the box on Squeeze without needing any extra fiddling. My old Vaio had that too, and I loved it.

Horizontal scrolling took some extra research. I was able to turn it on with a command:

synclient HorizEdgeScroll=1
(thank you, AbsolutelyTech). Then it worked fine, for the duration of that session.

But it took a lot more searching to find out the right place to set it permanently. Nearly every page you find on trackpad settings tells you to edit /etc/X11/xorg.conf. Distros haven't normally used xorg.conf in over three years! Sure, you can generate one, then edit it -- but surely there's a better way.

And there is. At least in Debian Squeeze and Ubuntu Natty, you can edit /usr/share/X11/xorg.conf.d/50-synaptics.conf and add this options line inside the "InputClass" section:

        options "HorizEdgeScroll" "1"
Don't forget the quotes, or X won't even start.

In theory, you can use this for any of the Synaptics driver options -- tap rate and sensitivity, even multitouch. Your mileage may vary -- horizontal scroll is the only one I've tested so far. But at least it's easier than generating and maintaining an xorg.conf file!

Tags: , ,
[ 16:20 Oct 31, 2011    More linux/laptop | permalink to this entry | comments ]

Tue, 27 Sep 2011

Banishing errant tooltips

Every now and then I have to run a program that doesn't manage its tooltips well. I mouse over some button to find out what it does, a tooltip pops up -- but then the tooltip won't go away. Even if I change desktops, the tooltip follows me and stays up on all desktops. Worse, it's set to stay on top of all other windows, so it blocks anything underneath it.

The places where I see this happen most often are XEphem (probably as an artifact of the broken Motif libraries we're stuck with on Linux); Adobe's acroread (Acrobat Reader), though perhaps that's gotten better since I last used it; and Wine.

I don't use Wine much, but lately I've had to use it for a medical imaging program that doesn't seem to have a Linux equivalent (viewing PETscan data). Every button has a tooltip, and once a tooltip pops up, it never goes aawy. Eventually I might have five of six of these little floating windows getting in the way of whatever I'm doing on other desktops, until I quit the wine program.

So how does one get rid of errant tooltips littering your screen? Could I write an Xlib program that could nuke them?

Finding window type

First we need to know what's special about tooltip windows, so the program can identify them. First I ran my wine program and produced some sticky tooltips.

Once they were up, I ran xwininfo and clicked on a tooltip. It gave me a bunch of information about the windows size and location, color depth, etc. ... but the useful part is this:

  Override Redirect State: yes

In X, override-redirect windows are windows that are immune to being controlled by the window manager. That's why they don't go away when you change desktops, or move when you move the parent window.

So what if I just find all override-redirect windows and unmap (hide) them? Or would that kill too many innocent victims?


I thought I'd have to write my little app in C, since it's doing low-level Xlib calls. But no -- there's a nice set of Python bindings, python-xlib. The documentation isn't great, but it was still pretty easy to whip something up.

The first thing I needed was a window list: I wanted to make sure I could find all the override-redirect windows. Here's how to do that:

from Xlib import display

dpy = display.Display()
screen = dpy.screen()
root = screen.root
tree = root.query_tree()

for w in tree.children :
    print w

w is a Window (documented here). I see in the documentation that I can get_attributes(). I'd also like to know which window is which -- calling get_wm_name() seems like a reasonable way to do that. Maybe if I print them, those will tell me how to find the override-redirect windows:

for w in tree.children :
    print w.get_wm_name(), w.get_attributes()

Window type, redux

Examining the list, I could see that override_redirect was one of the attributes. But there were quite a lot of override-redirect windows. It turns out many apps, such as Firefox, use them for things like menus. Most of the time they're not visible. But you can look at w.get_attributes().map_state to see that.

So that greatly reduced the number of windows I needed to examine:

for w in tree.children :
    att = w.get_attributes()
    if att.map_state and att.override_redirect :
        print w.get_wm_name(), att

I learned that tooltips from well-behaved programs like Firefox tended to set wm_name to the contents of the tooltip. Wine doesn't -- the wine tooltips had an empty string for wm_name. If I wanted to kill just the wine tooltips, that might be useful to know.

But I also noticed something more important: the tooltip windows were also "transient for" their parent windows. Transient for means a temporary window popped up on behalf of a parent window; it's kept on top of its parent window, and goes away when the parent does.

Now I had a reasonable set of attributes for the windows I wanted to unmap. I tried it:

for w in tree.children :
    att = w.get_attributes()
    if att.map_state and att.override_redirect and w.get_wm_transient_for():

It worked! At least in my first test: I ran the wine program, made a tooltip pop up, then ran my killtips program ... and the tooltip disappeared.

Multiple tooltips: flushing the display

But then I tried it with several tooltips showing (yes, wine will pop up new tooltips without hiding the old ones first) and the result wasn't so good. My program only hid the first tooltip. If I ran it again, it would hide the second, and again for the third. How odd!

I wondered if there might be a timing problem. Adding a time.sleep(1) after each w.unmap() fixed it, but sleeping surely wasn't the right solution.

But X is asynchronous: things don't necessarily happen right away. To force (well, at least encourage) X to deal with any queued events it might have stacked up, you can call dpy.flush().

I tried adding that after each w.unmap(), and it worked. But it turned out I only need one

at the end of the program, just exiting. Apparently if I don't do that, only the first unmap ever gets executed by the X server, and the rest are discarded. Sounds like flush() is a good idea as the last line of any python-xlib program.

killtips will hide tooltips from well-behaved programs too. If you have any tooltips showing in Firefox or any GTK programs, or any menus visible, killtips will unmap them. If I wanted to make sure the program only attacked the ones generated by wine, I could add an extra test on whether w.get_wm_name() == "".

But in practice, it doesn't seem to be a problem. Well-behaved programs handle having their tooltips unmapped just fine: the next time you call up a menu or a tooltip, the program will re-map it.

Not so in wine: once you dismiss one of those wine tooltips, it's gone forever, at least until you quit and restart the program. But that doesn't bother me much: once I've seen the tooltip for a button and found out what that button does, I'm probably not going to need to see it again for a while.

So I'm happy with killtips, and I think it will solve the problem. Here's the full script: killtips.

Tags: , , , ,
[ 11:36 Sep 27, 2011    More programming | permalink to this entry | comments ]

Thu, 14 Jul 2011

Using default-frame-alist to specify Emacs window size, position and font

Seems like every few years I need to change the way I specify my preferred emacs fonts and window sizes.

Historically this all used to happen from one file, ~/.Xdefaults, where you set up your defaults for all X programs. In a way that was nice, since you could set up defaults and see the same font everywhere. On the other hand, it made for a huge, somewhat hard to read file, and it's increasingly out of favor on modern desktops, with modern toolkits like GTK just ignoring it.

Emacs still reads Xdefaults -- but only sort of. A lot of the values I used to set there no longer work properly. Some time ago I commented out my various attempts at setting emacs font, like

Emacs*font: -*-clean-bold-*-*-*-13-*-*-*-c-*-*-*
Emacs*font: DejaVu Sans Mono-10:bold
Emacs*font: clean-13:bold
Wmacs*font: Liberation Mono-10:bold
Emacs.font: 7x13bold
Emacs.faceName: Dejavu-10:style=bold
since none of them worked, and worked out a way of setting fonts inside my .emacs file:
(set-face-attribute 'default nil :font "Terminus-12:bold")

That worked to set the font, but it had another annoying attribute: it doesn't happen at startup, so it messed up my window size. See, emacs would start up, see the size I specified in .Xdefaults:

Emacs*geometry: 80x45
and try to set that. But it hadn't read .emacs yet, so it was still using whatever its default font and size is, and that's huge -- so 45 lines made a window too tall to fit on my laptop screen. Emacs would then shrink its window to fit the screen (41 lines). Only then would it open .emacs, whereupon it would see the set-face-attribute, change the font, and resize the window again, much, smaller, still 41 lines.

What a pain!

The emacs manual, in addition to talking about these various Xdefaults properties and command-line options, does mention a couple of variables, set-screen-height and set-screen-width, that looked promising. I tried putting (set-screen-height 45) in my .emacs right after I set the font -- no dice. Apparently that doesn't work because by the time those are read, emacs has already decided that 41 lines is as big as the window can possibly be.

Here's the answer: another variable that goes inside .emacs, default-frame-alist, but this one can override that maximum-height decision that emacs has already made. Here's an example of it in some useful defaults for emacs, and based on that, I was able to come up with this:

(setq default-frame-alist
      '((top . 10) (left . 2)
        (width . 80) (height . 53)
        (font . "terminus-iso8859-1-bold-14")

Curiously, that height setting, 53, needs to be 3 more than what I actually want according to the size emacs reports to the window manager. So don't take the number too seriously; just try numbers a little bigger than what you actually want until you get the size you're after. The font setting is the X font specifier: I ran xlsfonts | grep -i terminus | grep 14 then picked one of the simpler of the lines it printed out, but you can use a full specifier like -xos4-terminus-bold-r-normal--14-140-72-72-c-80-iso8859-1 like you get from xfontsel, if you prefer.

Startup still isn't pretty -- emacs still shows a big window at one place on the screen, resizes it several times then jumps it over to the top/left coordinates I specified. Of course, I could tell my window manager to start it in the right place so the jumping-around would be minimized; but that wouldn't help the visible resizing. Just a minor irritation.

I'm sure there's lots more useful stuff buried in that sample emacs config file (it was suggested to me when I asked about this on the #emacs IRC channel), so I'll be reading it to see what else I can glean.

Tags: , ,
[ 12:24 Jul 14, 2011    More linux/editors | permalink to this entry | comments ]

Tue, 18 Jan 2011

X Terminal Colors (and dark and light backgrounds)

[Displaying colors in an xterm] At work, I'm testing some web programming on a server where we use a shared account -- everybody logs in as the same user. That wouldn't be a problem, except nearly all Linuxes are set up to use colors in programs like ls and vim that are only readable against a dark background. I prefer a light background (not white) for my terminal windows.

How, then, can I set things up so that both dark- and light-backgrounded people can use the account? I could set up a script that would set up a different set of aliases and configuration files, like when I changed my vim colors. Better, I could fix all of them at once by changing my terminal's idea of colors -- so when the remote machine thinks it's feeding me a light color, I see a dark one.

I use xterm, which has an easy way of setting colors: it has a list of 16 colors defined in X resources. So I can change them in ~/.Xdefaults.

That's all very well. But first I needed a way of seeing the existing colors, so I knew what needed changing, and of testing my changes.

Script to show all terminal colors

I thought I remembered once seeing a program to display terminal colors, but now that I needed one, I couldn't find it. Surely it should be trivial to write. Just find the escape sequences and write a script to substitute 0 through 15, right?

Except finding the escape sequences turned out to be harder than I expected. Sure, I found them -- lots of them, pages that conflicted with each other, most giving sequences that didn't do anything visible in my xterm.

Eventually I used script to capture output from a vim session to see what it used. It used <ESC>[38;5;Nm to set color N, and <ESC>[m to reset to the default color. This more or less agreed Wikipedia's ANSI escape code page, which says <ESC>[38;5; does "Set xterm-256 text coloor" with a note "Dubious - discuss". The discussion says this isn't very standard. That page also mentions the simpler sequence <ESC>[0;Nm to set the first 8 colors.

Okay, so why not write a script that shows both? Like this:

#! /usr/bin/env python

# Display the colors available in a terminal.

print "16-color mode:"
for color in range(0, 16) :
    for i in range(0, 3) :
        print "\033[0;%sm%02s\033[m" % (str(color + 30), str(color)),

# Programs like ls and vim use the first 16 colors of the 256-color palette.
print "256-color mode:"
for color in range(0, 256) :
    for i in range(0, 3) :
        print "\033[38;5;%sm%03s\033[m" % (str(color), str(color)),

Voilà! That shows the 8 colors I needed to see what vim and ls were doing, plus a lovely rainbow of other possible colors in case I ever want to do any serious ASCII graphics in my terminal.

Changing the X resources

The next step was to change the X resources. I started by looking for where the current resources were set, and found them in /etc/X11/app-defaults/XTerm-color:

$ grep color /etc/X11/app-defaults/XTerm-color
irrelevant stuff snipped
*VT100*color0: black
*VT100*color1: red3
*VT100*color2: green3
*VT100*color3: yellow3
*VT100*color4: blue2
*VT100*color5: magenta3
*VT100*color6: cyan3
*VT100*color7: gray90
*VT100*color8: gray50
*VT100*color9: red
*VT100*color10: green
*VT100*color11: yellow
*VT100*color12: rgb:5c/5c/ff
*VT100*color13: magenta
*VT100*color14: cyan
*VT100*color15: white
! Disclaimer: there are no standard colors used in terminal emulation.
! The choice for color4 and color12 is a tradeoff between contrast, depending
! on whether they are used for text or backgrounds.  Note that either color4 or
! color12 would be used for text, while only color4 would be used for a
! Originally color4/color12 were set to the names blue3/blue
!*VT100*color4: blue3
!*VT100*color12: blue
!*VT100*color4: DodgerBlue1
!*VT100*color12: SteelBlue1

So all I needed to do was take the ones that don't show up well -- yellow, green and so forth -- and change them to colors that work better, choosing from the color names in /etc/X11/rgb.txt or my own RGB values. So I added lines like this to my ~/.Xdefaults:

!! color2 was green3
*VT100*color2: green4
!! color8 was gray50
*VT100*color8: gray30
!! color10 was green
*VT100*color10: rgb:00/aa/00
!! color11 was yellow
*VT100*color11: dark orange
!! color14 was cyan
*VT100*color14: dark cyan
... and so on.

Now I can share accounts, and I no longer have to curse at those default ls and vim settings!

Update: Tip from Mikachu: ctlseqs.txt is an excellent reference on terminal control sequences.

Tags: , , , , ,
[ 10:56 Jan 18, 2011    More linux | permalink to this entry | comments ]

Mon, 13 Sep 2010

Of Laptops, Docking Stations and Changing Resolution

I've been setting up a new Lenovo X201 laptop at work. (Yes, work -- I've somehow fallen into an actual job where I go in to an actual office at least some of the time. How novel!)

At the office I have a Lenovo docking station, attached to a monitor and keyboard. The monitor, naturally, has a different resolution from the laptop's own monitor.

Under Gnome and compiz, when I plugged in the monitor, I could either let the monitor mirror the laptop display -- in which case X would refuse to work at greater than 1024x768, much smaller than the native resolution of either the laptop screen or the external monitor -- or I could call up the classic two-monitor configuration dialog, where I could configure the external monitor to be its correct size and sit alongside the computer's monitor. I had to do this every time I plugged in.

If I wanted to work on the big screen, then when I undocked, I had to drag all the windows on all desktops back to the built-in LCD first, or they'd be lost. Using just the external monitor and turning off the laptop screen didn't seem to be an allowed option.

That all lasted for about two days. Gnome and I just don't get along. Pretty soon gdm was mysteriously refusing to let me log in (probably didn't like my under-1000 user id), and after wasting half a day fighting it I gave up and reverted with relief to my familiar Openbox desktop.

But now I'm in the Openbox world and don't have that dialog anyway. What are my options?

xrandr monitor detection

Fortunately, I already knew about using xrandr to send to a projector; it was only a little more complicated using it for the monitor in the docking station. Running xrandr with no arguments prints all the displays it currently sees, so you can tell whether an external display or projector is connected and even what resolutions it supports.

I used that for a code snippet in my .xinitrc:

# Check whether the external monitor is connected: returns 0 on success
xrandr | grep VGA | grep " connected "
if [ $? -eq 0 ]; then
  xrandr --output VGA1 --mode 1600x900;
  xrandr --output LVDS1 --off
  xrandr --output VGA1 --off
  xrandr --output LVDS1 --mode 1280x800

That worked nicely. When I start X it checks for an external monitor, and if it finds one it turns off the laptop display (so it's off when the laptop is sitting closed in the docking station) and sets the screen size for the external monitor.

Making it automatic

All well and good. I worked happily all day in the docking station, suspended the laptop and un-docked it, brought it home, woke it up -- and of course the display was still off. Oops.

Okay, so it also needs the same check when resuming from suspend. That used to be in /etc/acpi/resume.d, but in Lucid they've moved it (because we definitely wouldn't want users to get complacent and think they know how to configure things!) and now it lives in /etc/pm/sleep.d. I created a new file, /etc/pm/sleep.d/20_enable_display which looks like this:


case "$1" in
        # Check whether the external monitor is connected:
        # returns 0 on success
        xrandr | grep VGA | grep " connected "
        if [ $? -eq 0 ]; then
            xrandr --output VGA1 --mode 1600x900
            xrandr --output LVDS1 --off
            xrandr --output VGA1 --off
            xrandr --output LVDS1 --mode 1280x800
        hsetroot -center `find -L $HOME/Backgrounds -name "*.*" | $HOME/bin/randomline`

exit $?

Neat! Now, every time I wake from suspend, the laptop checks whether an external monitor is connected and sets the resolution accordingly. And it re-sets the background (using my random wallpaper method) so I don't get a tiled background on the big monitor.

Update: hsetroot -fill works better than -center given that I'm displaying background images on two different resolutions. Of course, if I wanted to get fancy I could make separate background sets, one for each monitor, and choose images from the appropriate set.

We're almost done. Two more possible adjustments.

Detecting undocking

First, while poking around in /etc/acpi I noticed a script named In theory, I can put the same code snippet in there, and then if I un-dock the laptop without suspending it first, it will immediately change resolution. I haven't actually tried that yet.


Second, this business of turning off the built-in display if there's anything plugged into the VGA port is going to break if I use this laptop for presentations, since a projector will also show up as VGA1. So the code may need to be a little smarter. For example:

xrandr | grep VGA | grep " connected " | grep 16.0x

The theory here is that an external monitor will be able to do 1680 or 1600, so it will have a line like VGA1 connected 1680x1050+0+0 (normal left inverted right x axis y axis) 434mm x 270mm. The 1680x matches the 16.0x pattern in grep. A projector isn't likely to do more than 1280, so it won't match the pattern '16.0x'. However, that isn't very robust; it will probably fail for one of those fancy new 1920x1080 monitors. You could extend it with

xrandr | grep VGA | grep " connected " | egrep '16.0x|19.0x'
but that's getting even more hacky ... and it might be time to start writing some more intelligent code.

Which doubtless I'll do if I ever get a 1920x1080 monitor.

Tags: , ,
[ 23:11 Sep 13, 2010    More linux/laptop | permalink to this entry | comments ]

Mon, 16 Nov 2009

More on kernel options needed for new X servers

A week ago I wrote about my mouse woes and how they were solved by enabling the "Enable modesetting on intel by default" kernel option.

But all was still not right with X. I could boot into a console, start X, and everything was fine -- but once X was running, I couldn't go back to console mode. Switching to a console, e.g. Ctrl-Alt-F2, did nothing except make the mouse cursor disappear, and any attempt to quit X to go back to my login shell put the monitor in sleep mode permanently -- the machine was still up, and I could ssh in or ctrl-alt-Delete to reboot, but nothing else I did would bring my screen back.

It wasn't strictly an Ubuntu problem, though this showed up with Karmic; I have a Gentoo install on another partition and it had the same problem. And I knew it was a kernel problem, because the Ubuntu kernel did let me quit X.

I sought in vain among the kernel's various Graphics settings. You might think that "enable modesetting" would be related to, you know, being unable to change video modes ... but it wasn't. I tried different DRM options and switching framebuffer on and off. Though, oddly, enabling framebuffer didn't actually seem to enable the framebuffer.

Finally I stepped through the Graphics section of make menuconfig comparing my settings with a working kernel, and saw a couple of differences that didn't look at all important: "Select compiled-in fonts" and "VGA 8x16 font". Silly, but what could they hurt? I switched them on and rebuilt.

And on the next boot, I had a framebuffer, and mode switching.

So be warned: those compiled-in fonts are not optional if you want a framebuffer; and you'd better want a framebuffer, because that isn't optional either if you want to be able to get out of X once you start it.

Tags: , , ,
[ 20:22 Nov 16, 2009    More linux/kernel | permalink to this entry | comments ]

Tue, 10 Nov 2009

Mouse failures with 2.6.31, Karmic and Intel

I've been seeing intermittent mouse failures since upgrading to Ubuntu 9.10 "Karmic". At first, maybe one time out of five I would boot, start X, and find that I couldn't move my mouse pointer. But after building a kernel, things got worse and it happened nearly every time.

It wasn't purely an X problem; if I enabled gpm, the mouse failed in the console as well as in X. And it wasn't hardware, because if I used Ubuntu 9.10's standard kernel, my mouse worked every time.

After much poking around with kernel options, I discovered that if I tunred off the Direct Rendering manager ("Intel 830M, 845G, 852GM, 855GM, 865G (i915 driver)"), my mouse would work. But that wasn't a satisfactory solution; aside from not being able to run Google Earth, it seems that Intel graphics needs DRM even to get reasonable performance redrawing windows. Without it, every desktop switch means watching windows slowly redraw over two or three seconds.

(Aside: why is it that Intel cards with shared CPU memory need DRM to draw basic 2-D windows, when my ancient ATI Radeon cards without shared memory had no such problems?)

But I think I finally have it nailed. In the kernel's Direct Rendering Manager options (under Graphics), the "Intel 830M, 845G, 852GM, 855GM, 865G (i915 driver)" using its "i915 driver" option has a new sub-option: "Enable modesetting on intel by default".

The help says:

Choose this option if you want kernel modesetting enabled by default, and you have a new enough userspace to support this. Running old userspaces with this enabled will cause pain. Note that this causes the driver to bind to PCI devices, which precludes loading things like intelfb.

Sounds optional, right? Sounds like, if I want to build a kernel that will work on both karmic and jaunty, I should leave that off so as not to "cause pain".

But no. It turns out it's actually mandatory on karmic. Without it, there's a race condition where about 80-90% of the time, hal won't see a mouse device at all, so the mouse won't work either in X or even on the console with gpm.

It's sort of the opposite of the "Remove sysfs features which may confuse old userspace tools" in General Setup, where the name implies that it's optional on new distros like Karmic, but in fact, if you leave it on, the kernel won't work reliably.

So be warned when configuring a kernel for brand-new distros. There are some new pitfalls, and options that worked in the past may not work any longer!

Update: see also the followup post for two more non-optional options.

Tags: , , , ,
[ 23:34 Nov 10, 2009    More linux/kernel | permalink to this entry | comments ]

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 | comments ]

Sun, 07 Jun 2009

No X acceleration (DRI) in Jaunty: solved

I upgraded to Ubuntu's current 9.04 release, "Jaunty Jackalope", quite a while ago, but I haven't been able to use it because its X server crashes or hangs regularly. (Fortunately I only upgraded a copy of my working 8.10 "Intrepid" install, on a separate partition.)

The really puzzling thing, though, wasn't the crashes, but the fact that X acceleration didn't work at all. Programs like tuxracer (etracer) and Google earth would display at something like one frame update every two seconds, and glxinfo | grep renderer said

OpenGL renderer string: Software Rasterizer

But that was all on my old desktop machine, with an ATI Radeon 9000 card that I know no one cares about much. I have a new machine now! An Intel dual Atom D945GCLF2D board with 945 graphics. Finally, a graphics chip that's supported! Now everything would work!

Well, not quite -- there were major teething pains, including returning the first nonworking motherboard, but that's a separate article. Eventually I got it running nicely with Intrepid. DRI worked! Tuxracer worked! Even Google Earth worked! Unbelievable!

I copied the Jaunty install from my old machine to a partition on the new machine. Booted into it and -- no DRI. Just like on the Radeon.

Now, there's a huge pile of bugs in Ubuntu's bug system on problems with video on Jaunty, all grouped by graphics card manufacturer even though everybody seems to be seeing pretty much the same problems on every chipset. But hardly any of the bugs talk about not getting any DRI at all -- they're all about whether EXA acceleration works better or worse than XAA and whether it's worth trying UXA. I tried them all: EXA and UXA both gave me no DRI, while XAA crashed/rebooted the machine every time. Clearly, there was something about my install that was disabling DRI, regardless of graphics card. But I poked and prodded and couldn't figure out what it was.

The breakthrough came when, purely by accident, I ran that same glxinfo | grep renderer from a root shell. Guess what?

OpenGL renderer string: Mesa DRI Intel(R) 945G GEM 20090326 2009Q1 RC2 x86/MMX/SSE2

As me (non-root), it still said "Software Rasterizer." It was a simple permissions problem! But wait ... doesn't X run as root?

Well, it does, but the DRI part doesn't, as it turns out. (This is actually a good thing, sort of, in the long term: eventually the hope is to get X not to need root permissions either.)

Armed with the keyword "permissions" I went back to the web, and the Troubleshooting Intel Performance page on the Ubuntu wiki, and found the solution right away. (I'd looked at that page before but never got past the part right at the beginning that says it's for problems involving EXA vs. UXA vs. XAA, which mine clearly wasn't).

The Solution

In Jaunty, the user has to be in group video to use DRI in X. But if you've upgraded from an Ubuntu version prior to Jaunty, where this wasn't required, you're probably not in that group. The upgrader (I used do-release-upgrade) doesn't check for this or warn you that you have desktop users who aren't in the video group, so you're on your own to find out about the problem. Fixing it is easy, though: edit /etc/group as root and add your user(s) to the group.

You might think this would have been an error worth reporting, say, at X startup, or in glxinfo, or even in /var/log/Xorg.0.log. You'd think wrong. Xorg.0.log blithely claims that DRI is enabled and everything is fine, and there's no indication of an error anywhere else.

I hope this article makes it easier for other people with this problem to find the solution.

Tags: , , ,
[ 20:23 Jun 07, 2009    More linux/install | permalink to this entry | comments ]

Wed, 15 Apr 2009

Which app owns a particular X window?

Someone on a mailing list was trying to figure out what app brought up a particular Gnome window, so she could run it on a machine that didn't have the Gnome desktop menus or panel.

Sounded like an interesting puzzle. I found a couple of ways, neither of them totally reliable. They both use xprop.

A lot of apps set something called WM_COMMAND to the original command that was run. So

xprop | grep COMMAND
and then click on the window you're interested in, and it gives you something ugly like
WM_COMMAND(STRING) = { "xterm", "-geometry", "80x69+0+0" }

That doesn't seem to work for more modern apps (at least, xchat and firefox don't set WM_COMMAND) so for those, try this:

xprop | grep PID

For apps that support NET_WM_PID, that gives you the process id, e.g.

and then you can
ps aux | grep 4095

Neither method is perfect, and there are a few apps that won't respond to either one. But most will yield to at least one of these approaches.

[ 15:32 Apr 15, 2009    More linux | permalink to this entry | comments ]

Wed, 11 Mar 2009

Upgraded to Intrepid: X keyboard options and losing network after suspend

I finally got around to upgrading to the current Ubuntu, Intrepid Ibex. I know Intrepid has been out for months and Jaunty is just around the corner; but I was busy with the run-up to a couple of important conferences when Intrepid came out, and couldn't risk an upgrade. Better late than never, right?

The upgrade went smoothly, though with the usual amount of babysitting, watching messages scroll by for a couple of hours so that I could answer the questions that popped up every five or ten minutes. Question: Why, after all these years of software installs, hasn't anyone come up with a way to ask all the questions at the beginning, or at the end, so the user can go have dinner or watch a movie or sleep or do anything besides sit there for hours watching messages scroll by?

XKbOptions: getting Ctrl/Capslock back

The upgrade finished, I rebooted, everything seemed to work ... except my capslock key wasn't doing ctrl as it should. I checked /etc/X11/xorg.conf, where that's set ... and found the whole file commented out, preceded by the comment:

# commented out by update-manager, HAL is now used
Oh, great. And thanks for the tip on where to look to get my settings back. HAL, that really narrows it down.

Google led me to a forum thread on Intrepid xorg.conf - input section. The official recommendation is to run sudo dpkg-reconfigure console-setup ... but of course it doesn't allow for options like ctrl/capslock. (It does let you specify which key will act as the Compose key, which is thoughtful.)

Fortunately, the release notes give the crucial file name: /etc/default/console-setup. The XKBOPTIONS= line in that file is what I needed.

It also had the useful XKBOPTIONS="compose:menu" option left over from my dpkg-configure run. I hadn't known about that before; I'd been using xmodmap to set my multi key. So my XKBOPTIONS now looks like: "ctrl:nocaps,compose:menu".

Fixing the network after resume from suspend

Another problem I hit was suspending on my desktop machine. It still suspended, but after resuming, there was no network. The problem turned out to lie in /etc/acpi/suspend.d/ It makes a list of interfaces which should be brought up and down like this:

IFDOWN_INTERFACES="`cat /etc/network/run/ifstate | sed 's/=.*//'`"
IFUP_INTERFACES="`cat /etc/network/run/ifstate`"
However, there is no file /etc/network/run/ifstate, so this always fails and so /etc/acpi/resume.d/ fails to bring up the network.

Google to the rescue again. The bad thing about Ubuntu is that they change random stuff so things break from release to release. The good thing about Ubuntu is a zillion other people run it too, so whatever problem you find, someone has already written about. Turns out ifstate is actually in /var/run/network/ifstate now, so making that change in /etc/acpi/suspend.d/ fixes suspend/resume. It's bug 295544, fixed in Jaunty and nominated for Intrepid (I just learned about the "Nominate for release" button, which I'd completely missed in the past -- very useful!) Should be interesting to see if the fix gets pushed to Intrepid, since networking after resume is completely broken without it.

Otherwise, it was a very clean upgrade -- and now I can build the GIMP trunk again, which was really the point of the exercise.

Tags: , , , ,
[ 18:28 Mar 11, 2009    More linux/install | permalink to this entry | comments ]

Fri, 06 Feb 2009

Widescreen laptop for presentations

I've written before about how I'd like to get a netbook like an Asus Eee, except that the screen resolution puts me off: no one makes a netbook with vertical resolution of more than 600. Since most projectors prefer 1024x768, I'm wary of buying a laptop that can't display that resolution.

(What was wrong with my beloved old Vaio? Nothing, really, except that the continued march of software bloat means that a machine that can't use more than 256M RAM is hurting when trying to run programs (*cough* Firefox *cough) that start life by grabbing about 90M and goes steadily up from there. I can find lightweight alternatives for nearly everything else, but not for the browser -- Dillo just doesn't cut it.)

Ebay turned out to be the answer: there are lots of subnotebooks there, nice used machines with full displays at netbook prices. And so a month before LCA I landed a nice Vaio TX650 with 1.5G RAM, Pentium M, Intel 915GM graphics and Centrino networking. All nice Linux-supported hardware.

But that raised another issue: how do widescreen laptops (the TX650 is 1366x768) talk to a projector? I knew it was possible -- I see people presenting from widescreen machines all the time -- but nobody ever writes about how it works.

The first step was to get it talking to an external monitor at all. I ran a VGA cable to my monitor, plugged the other end into the Vaio (it's so nice not to need a video dongle!) and booted. Nothing. Hmm.

But after some poking and googling, I learned that with Intel graphics, xrandr is the answer:

xrandr --output VGA --mode 1024x768
switches the external VGA signal on, and
xrandr --auto
switches it back off.

Update, April 2010: With Ubuntu Lucid, this has changed and now it's
xrandr --output VGA1 --mode 1024x768
-- in other words, VGA changed to VGA1. You can run xrandr with no arguments to get a list of possible output devices and find out whether X sees the external projector or screen correctly.

Well, mostly. Sometimes it doesn't work -- like, unfortunately, at the lightning talk session, so I had to give my talk without visuals. I haven't figured that out yet. Does the projector have to be connected before I run xrandr? Should it not be connected until after I've already run xrandr? Once it's failed, it doesn't help to run xrandr again ... but a lot of fiddling and re-plugging the cable and power cycling the projector can sometimes fix the problem, which obviously isn't helpful in a lightning talk situation.

Eventually I'll figure that out and blog it (ideas, anyone?) but the real point of today's article is resolution. What I wanted to know was: what happened to that wide 1366-pixel screen when I was projecting 1024 pixels? Would it show me some horrible elongated interpolated screen? Would it display on the left part of the laptop screen, or the middle part?

The answer, I was happy to learn, is that it does the best thing possible: it sends the leftmost 1024 pixels to the projector, while still showing me all 1366 pixels on the laptop screen.

Why ... that means ... I can write notes for myself, to display in the rightmost 342 screen pixels! All it took was a little bit of CSS hacking in my HTML slide presentation package, and it worked fine. Now I have notes just like my Mac friends with their Powerpoint and their dual-head video cards, only I get to use Linux and HTML. How marvellous! I could get used to this widescreen stuff.

Tags: , , , , , ,
[ 22:12 Feb 06, 2009    More linux/laptop | permalink to this entry | comments ]

Wed, 16 Jul 2008

Running a second X: Xnest, Xephyr and xinit

I had a silly problem: I needed to make some screenshots, but my window borders were too pretty.

The problem isn't actually that they're pretty; it's that the theme I wrote for openbox is very different from the much simpler theme I used to use in fvwm, and I needed new screenshots that matched the old fvwm look. Preferably without actually going back to using fvwm -- I'm quite happy with openbox these days.

Anyway, the obvious solution is to run a second X. I had done that in the past (when I needed to test something repeatedly, like a wacom tablet, and didn't want to be restarting X all the time) so I knew that was possible. But then someone told me about Xnest. It's a way to run an X server embedded in a window of the current X session. What a neat idea! I wanted to try it.

I made a simple .xinitrc.xnest file that starts fvwm after loading .Xdefaults. It took some fiddling to find a combination of arguments that worked. In the end, this was it:
xinit ~/.xinitrc.xnest -- /usr/bin/Xnest -ac :1 -geometry 1024x768
And indeed, a 1024x768 window popped up with an fvwm running inside it. Cool! Except it turned out to be not so cool -- because as soon as I switched desktops, I found that the Xnest window wouldn't repaint itself. Not even after being covered with another window then uncovered -- it just didn't seem to get any expose events. Bummer!

Next I tried Xephyr -- I heard that it was similar to Xnest, a little more heavyweight but a little more reliable. It turned out the arguments were just the same, so I ran it exactly like Xnest:
xinit ~/.xinitrc.xnest -- /usr/bin/Xephyr -ac :1 -geometry 1024x768
but Xephyr was even worse about window redrawing, plus it had some problems with the mouse pointer, which kept jumping to random places.

Too bad! They both sounded fun, and I'm sure they'll improve and will eventually become usable. But for now, I'm back to the simpler solution, running a second X server. Here's how that works: first I have to log in on console 2 (ctl-alt-F2). For some reason, I can't run a second X except from there. Then I run:
startx ~/.xinitrc.xnest -- :1 and I get a new X session, on ctl-alt-F8 (with my regular session still accessible on ctl-alt-F7).

Tags: ,
[ 21:01 Jul 16, 2008    More linux | permalink to this entry | comments ]

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 | comments ]

Thu, 10 Apr 2008

A minimal xorg.conf

Dave has been experimenting with xorg configuration lately -- trying to figure out why the latest Xorg no longer supports 1600x1200 on his monitor. (I've looked for bug reports and found gazillions of them, all blaming it on the video card but involving three different makes of video card, so color me skeptical.)

Anyway, part of this has involved taking out parts of his /etc/X11/xorg.conf file to see which parts might be causing the problem, and he's found something interesting.

What do you suppose is the minimal useful xorg.conf file? You might suppose, oh, screen and monitor sections, an input section for the keyboard and another one for a generic mouse, and that might be all you need ... right?

Okay, try it. Let's start with a really minimal file -- nothing -- and gradually add sections. To try it, make a backup of your current xorg.conf, then zero out the file:

cd /etc/X11
mv xorg.conf xorg.conf.sav
cp /dev/null xorg.conf

Now exit X if you hadn't already, and start it up again (or let gdm do it for you). Be prepared to do repairs from the console in case X doesn't start up: e.g. sudo cp /etc/X11/xorg.conf.bak /etc/X11/xorg.conf

What happened?

In my case, on the laptop running Hardy beta, X starts right up and looks just the same as it did before.

xorg.conf -- who needs it?

A specious question, of course, which has a perfectly good answer: anyone who needs a resolution other than whatever xorg picks as the default; anyone with additional hardware, like a wacom tablet; anyone who wants customizations like XkbOptions = ctrl:nocaps. There are lots of reasons to have an xorg.conf. But it's fun to know that at least on some machines, it's possible to run without one.

Update: turns out this is part of Ubuntu's new BulletProof X feature. It doesn't work on other distros or older versions. Thanks to James D for the tip.

Tags: ,
[ 11:25 Apr 10, 2008    More linux | permalink to this entry | comments ]

Tue, 05 Feb 2008

Synaptics and USB mouse simultaneously

A month or so back, I spent some time fiddling with the options for the Synaptics touchpad driver. The Alps (not Synaptics) trackpad on my laptop has always worked okay with just the standard PS/2 mouse driver, but in recent kernels it's become overly sensitive to taps, registering spurious clicks when I'm in the middle of typing a word (so suddenly I'm typing in a completely different window without knowing it).

I eventually got it working. I tried various options, but here's what I settled on:

Section "InputDevice"
        Identifier      "Trackpad"
        Driver          "synaptics"
        Option          "SHMConfig"             "true"
        Option          "SendCoreEvents"        "true"
        Option          "Device"                "/dev/psaux"
        Option          "Protocol"              "auto-dev"
        Option          "MinSpeed"              "0.5"
        Option          "MaxSpeed"              "0.75"
# AccelFactor defaults to .0015 -- synclient -l to check
        Option          "TouchpadOff"           "2"
        Option          "Emulate3Buttons"       "true"

Section "InputDevice"
        Identifier      "Configured Mouse"
        Driver          "mouse"
        Option          "CorePointer"
        Option          "Device"                "/dev/input/mice"
        Option          "Protocol"              "ExplorerPS/2"
        Option          "ZAxisMapping"          "4 5"
        Option          "Emulate3Buttons"       "true"

Life was groovy (I thought). Fast forward to LCA, a few days before my talk, when I decide to verify that I can run my USB mouse and the slide-advancing presentation gizmo through a hub off the single USB port. Quel surprise: the USB mouse doesn't work at all!

I didn't really need a mouse for that presentation (it was on GIMP scripting, not GIMP image editing) so I put it on the back burner, and came back to it when I got home. As I suspected, the USB mouse was working fine if I commented out the Synaptics entry from xorg.conf; it just couldn't run both at the same time.

A little googling led me to the answer, in a thread called Can't use Synaptics TouchPad and USB Mouse -- it wasn't the first google hit for synaptics "xorg.conf" usb mouse, so perhaps this entry will help its google-fu. The important part I was missing was in the "ServerLayout" section:

        InputDevice     "Trackpad"              "AlwaysCore"
        InputDevice     "Configured Mouse"      "CorePointer"

Adding "AlwaysCore" and "CorePointer" parts was what did the trick. Thanks to "finferflu" who posted the right answer in the thread.

Tags: ,
[ 22:54 Feb 05, 2008    More linux | permalink to this entry | comments ]

Sat, 25 Aug 2007

Widescreen Monitor, Intel Graphics on Ubuntu

On a seemingly harmless trip to Fry's, my mother got a look at the 22-inch widescreen LCD monitors and decided she had to have one. (Can't blame her ... I've been feeling the urge myself lately.)

We got the lovely new monitor home, plugged it in, configured X and discovered that the screen showed severe vertical banding. It was beautiful at low resolutions, but whenever we went to the monitor's maximum resolution of 1680x1050, the bands appeared.

After lots of testing, we tentatively pinned the problem down to the motherboard. It turns out ancient machines with 1x AGP motherboards can't drive that many pixels properly, even if the video card is up to the job. Who knew?

Off we trooped to check out new computers. We'd been hinting for quite some time that it might be about time for a new machine, and Mom was ready to take the plunge (especially if it meant not having to return that beautiful monitor).

We were hoping to find something with a relatively efficient Intel Core 2 processor and Intel integrated graphics: I've been told the Intel graphics chip works well with Linux using open source drivers. (Mom, being a person of good taste, prefers Linux, and none of us wanted to wrestle with the proprietary nvidia drivers). We found a likely machine at PC Club. They were even willing to knock $60 off the price since she didn't want Windows.

But that raised a new problem. During our fiddling with her old machine, we'd tried burning a Xubuntu CD, to see if the banding problem was due to the old XFree86 she was running. Installing it hadn't worked: her CD burner claimed it burned correctly, but the resulting CD had errors and didn't pass verification. So we needed a CD burned. We asked PC Club when buying the computer whether we might burn the ISO to CD, but apparently that counts as a "data transfer" and their minimum data transfer charge is $80. A bit much.

No problem -- a friend was coming over for dinner that night, and he was kind enough to bring his Mac laptop ... and after a half hour of fiddling, we determined that his burner didn't work either (it gave a checksum error before starting the burn). He'd never tried burning a CD on that laptop.

What about Kinko's? They have lots of data services, right? Maybe they can burn an ISO. So we stopped at Kinko's after dinner. They, of course, had never heard of an ISO image and had no idea how to burn one on their Windows box. Fearing getting a disk with a filesystem containing one file named "xubuntu-7.04-alternate-i386.iso", we asked if they had a mac, since we knew how to burn an ISO there. They did, though they said sometimes the CD burner was flaky. We decided to take the risk.

Burning an ISO on a mac isn't straightforward -- you have to do things in exactly the right order. It took some fast talking to persuade them of the steps ("No, it really won't work if you insert the blank CD first. Yes, we're quite sure") and we had to wait a long time for Kinko's antivirus software to decide that Xubuntu wasn't malware, but 45 minutes and $10 later, we had a disc.

And it worked! We first set up the machine in the living room, away from the network, so we had to kill aptitude update when the install hung installing "xubuntu-desktop" at 85% (thank goodness for alternate consoles on ctl-alt-F2) but otherwise the install went just fine. We rebooted, and Xubuntu came up ... at 1280x1024, totally wrong. Fiddling with the resolution in xorg.conf didn't help; trying to autodetect the monitor with dpkg-reconfigure xorg crashed the machine and we had to power cycle.

Back to the web ... turns out that Ubuntu "Feisty" ships with a bad Intel driver. Lots of people have hit the problem, and we found a few elaborate workarounds involving installing X drivers from various places, but nothing simple. Well, we hadn't come this far to take all the hardware back now.

First we moved the machine into the computer room, hooked up networking and reinstalled xubuntu with a full network, just in case. The resolution was still wrong. Then, with Dave in the living room calling out steps off a web page he'd found, we began the long workaround process.

"First," Dave suggested, reading, "check the version of xserver-xorg-video-intel. Let's make sure we're starting with the same version this guy is."

dpkg -l xserver-xorg-video-intel ... "Uh, it isn't installed," I reported. I tried installing it. "It wants to remove xserver-xorg-video-i810." Hmm! We decided we'd better do it, since the rest of the instructions depended on having the intel, not i810, driver.

And that was all it needed! The intel driver autodetected the monitor and worked fine at 1680x1050.

So forget the elaborate instructions for trying X drivers from various sources. The problem was that xubuntu installed the wrong driver: the i810 driver instead of the more generic intel driver. (Apparently that bug is fixed for the next Ubuntu release.)

With that fix, it was only a few more minutes before Mom was happily using her new system, widescreen monitor and all.

Tags: , ,
[ 14:23 Aug 25, 2007    More linux | permalink to this entry | comments ]

Sun, 17 Jun 2007

Openbox 3.4

It was a bit over two years ago that I switched from icewm to fvwm as my window manager. Fvwm proved to be very fast, very configurable, and "good enough" most of the time. But lately, I've found myself irritated with it, particularly with its tendency to position windows off screen (which got a lot worse in 2.5.18). It looked like it was time to try another window manager, so when I learned that the Openbox project is headed by a fellow LinuxChixor, I had to try it.

Openbox impressed me right away. I'd tried it once before, a couple of years ago, when I found it a little inconsistent and immature. It's grown up a lot since then! It's still very fast and lightweight, but it has good focus handling, excellent window positioning, a good configuration window (obconf), and a wide variety of themes which are pretty but still don't take up too much of my limited screen space.

But more important, what it has is a very active and friendly community. I hit a couple of snags, mostly having to do with focus handling while switching desktops (the problem that drove me off icewm to fvwm), so I hopped onto the IRC channel and found myself chatting with the active developers, who told me that most of my problems had already been fixed in 3.4, and there were .deb files on the website for both of the distros I'm currently using. Indeed, that cured the problem; and when I later hit a more esoteric focus bug, the developers (particularly Dana Jansens) were all over it and fixed it that same day. Wow!

Since then I've been putting it through its paces. I have yet to see a window positioned badly in normal usage, and it handles several other problems I'd been seeing with fvwm, like focus handling when popping up dialogs (all those secondary GIMP Save-as dialogs that don't get focused when they appear). It's just as flexible as fvwm was when it comes to keyboard and mouse configuration, maybe even more so (plus it has lots of useful default bindings I might not have thought of, like mousewheel bindings to change desktops or "shade" a window).

I was going to stay out of theme configuration, because there were several pretty good installed themes already. But then in response to a half-joking question on my part of whether a particular theme came in blue, someone on the IRC channel made me a custom theme file -- and I couldn't resist tweaking it from there, and discovered that tweaking openbox themes is just as easy as fiddling with its other defaults.

I don't use transparency (I find it distracting), but my husband is addicted to transparent windows, so when I noticed on the web site that openbox handles transparency I pointed him there. (He's been using an old Afterstep, from back when it was still small and light, but it's been a constant battle getting it to build under newer gccs.) He reports that openbox handles transparency as well as afterstep did, so he's switched too.

I haven't looked at the openbox code yet, but based on how fast the developers add features and fix bugs, I bet it's clean, and I hope I can contribute at some point.

Anyway, great focus handling, great window positioning, fast, lightweight, super configurable, and best of all a friendly and helpful developer and user community. What more could you ask for in a window manager? I'm an openbox convert. Thanks, Dana, Mikachu and all the rest.

Tags: , ,
[ 14:13 Jun 17, 2007    More linux | permalink to this entry | comments ]

Sat, 09 Dec 2006

Getting a Wacom Tablet Working under Edgy

Another person popped into #gimp today trying to get a Wacom tablet working (this happens every few weeks). But this time it was someone using Ubuntu's new release, "Edgy Eft", and I just happened to have a shiny new Edgy install on my laptop (as well as a Wacom Graphire 2 gathering dust in the closet because I can never get it working under Linux), so I dug out the Graphire and did some experimenting.

And got it working! It sees pressure changes and everything. It actually wasn't that hard, but it did require some changes. Here's what I had to do:

  1. Install wacom-tools and xinput
  2. Edit /etc/X11/xorg.conf and comment out those ForceDevice lines that say "Tablet PC ONLY".
  3. Reconcile the difference between udev creating /dev/input/wacom and xorg.conf using /dev/wacom: you can either change xorg.conf, change /etc/udev/rules.d/65-wacom.rules, or symlink /dev/input/wacom to /dev/wacom (that's what I did for testing, but it won't survive a reboot, so I'll have to pick a device name and make udev and X consistent).

A useful tool for testing is /usr/X11R6/bin/xinput list (part of the xinput package). That's a lot faster than going through GIMP's input device preference panel every time.

I added some comments to Ubuntu's bug 73160, where people had already described some of the errors but nobody had posted the steps to work around the problems.

While I was fiddling with GIMP on the laptop, I decided to install the packages I needed to build the latest CVS GIMP there. It needed a few small tweaks from the list I used on Dapper. I've updated the package list on my GIMP Building page accordingly.

Tags: , , , ,
[ 16:12 Dec 09, 2006    More linux | permalink to this entry | comments ]

Mon, 10 Jul 2006

Screen Blanking Under X

An unexplained change in the screen blanking timeout sent me down the primrose path of learning about dpms, vbetool and screen blanking. I guess it had to happen eventually.

It started when my laptop, which normally can sit for about ten minutes before the screen goes black, suddenly started blanking the screen after only two minutes.

After a few days of sporadic research, I now know what pieces are involved and how to fix the timeout. But it turns out not everything works the way it's supposed to. I've written up my findings: A Primer on Screen Blanking Under Xorg.

Tags: ,
[ 12:55 Jul 10, 2006    More linux | permalink to this entry | comments ]

Mon, 20 Mar 2006

Getting rid of all those .serverauth.???? files

Dave has been complaining for a long time about the proliferation of files named .serverauth.???? (where ???? is various four-digit numbers) in his home directory under Ubuntu. I never saw them under Hoary, but now under Breezy and Dapper I'm seeing the same problem.

I spent some time investigating, with the help of some IRC friends. In fact, Carla Schroder, author of O'Reilly's Linux Cookbook, was the one who pinned down the creation of the files to the script /usr/bin/startx.

Here's the deal: if you use gdm, kdm, or xdm, you'll never see this. But for some reason, Ubuntu's startx uses a program called xauth which creates a file containing an "MIT-MAGIC-COOKIE". (Don't ask.) Under most Linux distributions, the magic cookie goes into a file called .Xauthority. The startx script checks an environment variable called XENVIRONMENT for the filename; if it's not set to something else, it defaults to $HOME/.Xenvironment.

Ubuntu's version is a little different. It still has the block of code where it checks XENVIRONMENT and sets it to $HOME/.Xenvironment if it isn't already set. But a few lines later, it proceeds to create the file under another, hardwired, name: you guessed it, $HOME/.serverauth.$$. The XENVIRONMENT variable which was checked and set is never actually used.

Programmers take note! When adding a feature to a script, please take a moment and think about what the script does, and check to see whether it already does something like what you're adding. If so, it's okay -- really -- to remove the old code, rather than leaving redundant and obsolete code blocks in place.

Okay, so why is the current code a problem? Because startx creates the file, calls xinit, then removes the file. In other words, it relies on xinit (and the X server) exiting gracefully. If anything else happens -- for example, if you shut your machine down from within X -- the startx script (which does not catch signals) can die without ever getting to the code that removes the file. So if you habitually shut down your machine from within X, you will have a .serverauth.???? file from each X session you ever shut down that way.

Note that the old setup didn't remove the file either, but at least it was always the same file. So you always have a single .Xauthority file in your home directory whether or not it's currently in use. Not much of a problem.

I wasn't seeing this under Hoary because under Hoary I ran gdm, while with Dapper, gdm would no longer log me in automatically so I had to find another approach to auto-login.

For Ubuntu users who wish to go back to the old one-file XAUTHORITY setup, there's a very simple fix: edit /usr/bin/startx (as root, of course) and change the line:

to read instead

If you want to track this issue, it's bug bug 35758.

Tags: , ,
[ 21:24 Mar 20, 2006    More linux | permalink to this entry | comments ]

Mon, 01 Aug 2005

Enabling Remote X

Another in the series of "I keep forgetting how to do this and have to figure it out again each time, so this time I'm going to write it down!"

Enabling remote X in a distro that disables it by default:

Of course, you need xhost. For testing, xhost + enables access from any machine; once everything is working, you may want to be selective, xhost hostname for the hosts from which you're likely to want to connect.

If you log in to the console and start X, check /etc/X11/xinit/xserverrc and see if it starts X with the -nolisten flag. This is usually the problem, at least on Debian derivatives: remove the -nolisten tcp.

If you log in using gdm, gdmconfig has an option in the Security tab: "Always disallow TCP connections to X server (disables all remote connections)". Un-checking this solves the problem, but logging out won't be enough to see the change. You must restart X; Ctrl-Alt-Backspace will do that.

Update: If you use kdm, the configuration to change is in /etc/kde3/kdm/kdmrc

Tags: , ,
[ 13:52 Aug 01, 2005    More linux | permalink to this entry | comments ]

Mon, 13 Dec 2004

Back to the Future -- fvwm

I've been alternating between icewm and openbox for my window manager, but I'm not entirely happy with either one. They're both fast to start up, which is important to me, but I've had frustrations mostly relating to window focus -- which window becomes focused when switching from one desktop to another (icewm's biggest problem) or when a window resizes (openbox), and also with initial window positioning and desktop location (e.g. making one window span all desktops without having to select a menu item every time I run that app).

Someone was opining on IRC about fvwm and its wonderful configurability, and that made me realize that I haven't really given fvwm a chance in a long, long time. Time to see if I was missing anything!

The defaults are terrible. No wonder I didn't stick with fvwm after newer windowmanagers came out! It's definitely not an install-and-go sort of program. Nor is the documentation (a long and seemingly thorough man page) clear on how to get started configuring it.

Eventually I figured out that it looks for ~/.fvwm/config, and that some sample configs were in /usr/share/doc/fvwm/sample.fvwmrc (which is a directory), and I went from there. After several hours of hacking, googling, and asking questions on #fvwm, I had a setup which rivals any window manager I've found: it's fast, lets me configure the look of my windows, lets me bind just about anything to keys, and seems pretty well behaved focus behavior. More important, it also allows me to specify special behavior for certain windows, for example, making xchat always occupy all desktops:

Style "xchat"    Sticky
which is something I've wanted but haven't been able to do in any other lightweight window manager. That alone may keep me in fvwm for the forseeable future.

Tips for things that were non-obvious:

Rotating through three desktops

In other window managers, I define three desktops, and use ctrl-alt-right and left to cycle through them, rotating, so going right from 3 goes to desktop 1. fvwm has both "pages" (a virtual desktop can be bigger than the screen, and mousing off the right side scrolls right one page) and desktops. I didn't want pages, only desktops, so DeskTopSize 1x1 turns off the pages, and it was clear from the man page that
PointerKey Left        A CM     GotoDesk -1
would go left one desk (the only unclear part about that is that A in the modifier list means "Any", not "Alt", and "M" (presumably for "meta" means alt, not the windows-key which some programs use for meta). "PointerKey" is needed instead of "Key" because otherwise fvwm gets confused when using the "sloppy focus" model (the man page warns about that).

The question was, how to limit fvwm to three desktops, and wrap around, rather than just going left to new desktops forever? The answer (courtesy of someone on IRC) turned out to be:

PointerKey Left        A CM     GotoDesk -1 0 2
PointerKey Right       A CM     GotoDesk 1 0 2
PointerKey Left        A CMS    MoveToDesk -1 0 2
PointerKey Right       A CMS    MoveToDesk 1 0 2
The only problem at this point is that MoveToDesk doesn't then change to the new desktop, the way other window managers do, but I'm confident that will be easily solved.

Titlebar buttons

I had the hardest time getting buttons (e.g. maximize, close) to appear on the titlebars of my windows. You'd think this would happen by default, but it doesn't. It turned out that titlebar buttons aren't drawn unless there's a key or mouse action bound to that button, which they aren't by default. So to get buttons for window menu, maximize, and close, I had to do:
Mouse 1 6       A       Close
Mouse 1 8       A       Maximize
Mouse 1 1       A       Menu Window-Ops Nop
But then showing buttons 6 and 8 (the even buttons are numbered from the top right) automatically turns on 2 and 4 (I chose 6 and 8 because their default shapes were vaguely mnemonic), so they have to be turned off again:
Style * NoButton 2
Style * NoButton 4

Smaller titlebar and window frame

I also wanted to reduce the titlebar height and the width of the window frame: I don't like wasting all that screen real estate. That, too, took a long time to figure out. It turns out I had to define my own theme in order to do that, then add a couple of undocumented items to my theme. There's lots of documentation around on how to make buttons and background images and menus and key bindings in themes, but none of the documentation mentions simple stuff like titlebar height.
DestroyDecor MyDecor
AddToDecor   MyDecor
+ TitleStyle Height 16
+ Style "*"       BorderWidth 5, HandleWidth 5
+ ButtonStyle All -- UseTitleStyle
Style "*" UseDecor MyDecor

New windows should grab focus

Most window managers do this by default, but fvwm doesn't, and requires: Style * FPGrabFocus

Full config file

For any other settings, see my fvwm config file.

Tags: , ,
[ 18:14 Dec 13, 2004    More linux | permalink to this entry | comments ]

Mon, 09 Aug 2004

Trying ion3, the window manager

Searching, as always, for the perfect window manager ...

Helix likes ion3, because it handles key accelerators very well, so I thought I'd try it.

I don't really like the "tiled or fullscreen" model it uses by default, but found the answer in the FAQ (after a rude RTFM comment which made no sense, since I already had RTFM and it doesn't give information on anything but runtime arguments): press F9 and get it to prompt for the type of the new workspace (the correct answer is the one with "Float" in the name).

All of the available themes use the "small grab handle around the title, but the rest of the titlebar isn't there" look. I don't like that (it's harder to find a place to grab to move windows around) though I suppose I could get used to it. Not a big deal.

It does look like it has good key binding support, and ways to specify different behavior for different apps, both of which would be very nice. Focus behavior on resize seems to be the same as openbox and icewm, though: if the window resizes out from under the cursor, it loses focus. Also the root menus (right-click) are a pain: they don't stay posted, and they're small, so it's hard to navigate them.

I'm sure ion3 has some coolnesses, but I decided that it didn't look likely enough to solve my problems to be worth learning how to configure it (and that unjustified RTFM left a bad taste in my mouth about how easy that configuration was likely to be). So I'm back on openbox for a little while, anyway.

Here's what I want out of a window manager:

Tags: , ,
[ 18:36 Aug 09, 2004    More linux | permalink to this entry | comments ]

Sat, 31 Jul 2004

Got the external mouse working again

For some reason X on the laptop hasn't been seeing the external USB mouse. But last night I got it working again. Turns out that /dev/input/mouse0 no longer works; I have to use /dev/input/mice because the mouse number changes each time it's plugged in (which I don't think was a problem with earlier kernels). Thanks to Peter S. for helping me track the problem down.

I also learned (unrelated to the mouse issue) about a couple of very useful Debian apps, deborphan and debfoster, for finding orphaned and no longer needed libraries. I'd always wanted something like that to help clean up my crufty debian systems.

Tags: , ,
[ 19:39 Jul 31, 2004    More linux | permalink to this entry | comments ]

Wed, 07 Jul 2004

DRI works after all

Got an account on alioth, akkana-guest.

Discovered that the tuxracer problem I've been having isn't actually Debian sid having broken DRI, but merely some problem with the commercial tuxracer (probably not loading the gl libs properly or something). Free tuxracer still works. Yay.

Tags: , , ,
[ 20:00 Jul 07, 2004    More linux | permalink to this entry | comments ]