Ubuntu on a netbook screen — revisited

In my very first post (other than that abortive book review), I gave what I thought was a very clever way of getting xrandr panning to work in Ubuntu with the Unity desktop. Like all good solutions, it worked as much as possible with the available high-level tools, avoiding any kind of reinventing the wheel or tinkering directly with the X server — other than using xrandr in the first place, which is unfortunately necessary given that there is no other way to get the panning effect. I seem to recall a developer in some bug report complaining that this ought to be a feature of the compositer, and I agree.

Reality intruded when my perfect solution was destroyed by bugs. Every Ubuntu upgrade is a new and exciting opportunity to see how they have ruined something minor but irritating with an unrelated “fix”. In my case, the “Display settings” of Compiz no longer had the desired effect upon the screen, instead producing garbage. So I had to abandon panning for months. Now that I’m using Ubuntu 12.04, I thought I’d try it again and see if my bug report had any effect.

Surprisingly, it did! No more garbage was produced. Alas, this time, xrandr itself was felled by a bug caused by a “fix”; as I understand it, they were trying to prevent the mouse from going out of bounds under some circumstance, and ended up preventing all panning entirely. After some Googling, I found a useful bug on Launchpad, with (O miracle) a useful solution.  Simply install that PPA (a custom package repository), upgrade the X server, and panning will work again.

That was, of course, just the start of the journey, because it became necessary to tweak the clever solution.  You see, a different bug (whose nature I do not know) reared its head: now, whenever I resumed from suspend, the effect of xrandr is negated! Further Googling revealed that the directory /etc/pm/sleep.d contains scripts that are run upon suspending and resuming, and I made one that called xrandr with my preferred settings.

Nothing happened; xrandr claimed it could not find the display. After some kind of inspiration, I somehow learned that this was because it was being run as root, rather than my user, so I wrapped the call in su -c. Nothing happened; xrandr couldn’t open the display. This was an easy one: DISPLAY was not set; I set it to :1.0, which is what my shell said it was. Note: default is :0.0, which should have clued me in to something strange going on, since I have only one screen. Anyway, still didn’t work, though visibly, something was happening: the screen would refresh, and then refresh again, as though the panning was being reverted after being applied.

Fortunately, a look at the background made it clear that (somehow) what had happened was that the panning was applied before the desktop background was painted, and this somehow reset the display. So I put in a sleep 5 just to be safe. Nothing happened; same problem. sleep 10; same problem. It occurred to me that, even though my script was literally the last thing to run during the resume process, it might be that it was blocking the very thing that was causing the problem, so I wrapped the sleep in a background process, and that fixed it. Whew!

Well, not quite. The next day I gave a lecture in class, using Beamer as usual, and of course, plugging in the external monitor (the projector) screwed everything up and afterwards, my resume script failed again. Very mysterious! It claimed it could not find the display once more; checking back, I learned that DISPLAY=:3.0! I guess the monitor caused a new display to be created, and then unplugging it caused yet another one. But now I had the problem of figuring out how to figure out the “real” display, since apparently no predetermined number was guaranteed to work.

This is really annoying, by the way. If a script is not called by some descendant of the X server, it really has no way of knowing what the “real” display is; in fact, there is no well-defined answer to this question in general! The X server could be serving several displays, or something remote, or whatever. You can’t just ask it, you can only be told upon process creation what display you are attached to, if any. But Google once again revealed the existence of a Unix-y solution: the /tmp/X11-unix directory, containing a bunch of socket files corresponding to each X display! In my case, there were four (0–3), of which only the last one produced any results from xrandr.

At that point I gave up for a day, but earlier tonight, I realized that the obvious solution, given that I only intended to be resuming with my laptop’s natural screen active, was simply to find the latest display and go with that. So I had my script set DISPLAY by just looping down the list, probably a dumb way of doing it. That works now.

Oh, did I mention the other problem with the projector? You may recall that my clever Compiz solution was to have it create two “outputs”, one of size 1024×768, and the “real” one of size 1024×600, or more specifically, of geometry specification 1024×600+0-168, which is to say, 168 pixels up from the bottom-left corner of the big display.

Problem is, that solution only works if the big display really is 168 pixels taller than the screen. Otherwise, I just lose that much in a strip from the bottom, and that’s exactly what happens when the display gets resized for the projector (since I have it sync the outputs). I have this vague memory of just re-enabling “detect outputs” back in the fall, and I guess all winter I wasn’t using panning at all, but I have no idea if I got around this problem some other way in the past.

This pissed me off, since it seemed like that was the way of setting the outputs, but then it occurred to me that I could just as easily make 1024×600 the default output and set the other one at 1024×768+0+-168; yes, that’s a +-. It means to go below the bottom of the screen. Obviously, this correctly communicates my intent.

Was that complicated enough for you?  In summary, I need:

  • A script to set panning, say in ~/bin/xrandr_panning:
    xrandr --fb 1024x768 --output LVDS1 --mode 1024x600 --panning 1024x768
  • An autorun script (set however your window manager does this, probably gnome if you are running Ubuntu) that calls this script on startup.
  • A suspend/resume script, for example /etc/pm/sleep.d/00_xrandr (modify the user name for yourself, of course).  Do make sure that it is executable:
    case "$1" in
        # Just pick the last DISPLAY enabled
        # for some reason it sometimes grows
        for i in /tmp/.X11-unix/X*; do
          j=$(basename $i); DISPLAY=":${j#X}"
        export DISPLAY
        su -c -p - ryanr "sleep 3; ~ryanr/bin/xrandr_panning" &
      exit 1
  • Go to the Compiz config manager, and under “General options”, in the “Display settings” tab, set “Prefer smaller output”, uncheck “Detect outputs”, and under “Outputs”, add two:

Congratulations!  You now have panning.  Can I “dislike” this post?

This entry was posted in Computers, Netbook, Ubuntu. Bookmark the permalink.

8 Responses to Ubuntu on a netbook screen — revisited

  1. jose says:

    excelent work! there’s only one thing i was wondering if you could help me with.

    i’m trying o get it to work with.
    xrandr –fb 1280×750 –output LVDS1 –mode 1280×750 –panning 1280×750

    and get:
    xrandr: cannot find mode 1280×750

    so i try.
    xrandr –addmode LVDS1 1280×750
    X Error of failed request: BadMatch (invalid parameter attributes)

    any ideas here?

    • Ryan Reich says:

      Your screen would need to have an actual mode called 1280×750, but I’ll bet you only have 1024×600, 800×600, and 640×480 (if you have a netbook). However, your command is wrong: you want the --fb resolution to be the size of the large, virtual desktop that gets panned around, and you want the --mode to be the “natural” resolution of the screen. So chances are you should write --mode 1280x600.

      If you really want to add a mode, you have do it in three steps. First, run cvt 1024 750, which will print a “modeline”, for example

      $ cvt 1024 750
      Modeline "1024x750_60.00"   62.00  1024 1072 1176 1328  750 753 763 779 -hsync +vsync

      Then, take that output, cut the “Modeline” part, and run xrandr --newmode ... with … being the rest of the modeline. This will, however, almost certainly add that mode to the output called VGA1. You can’t really add modes to an LCD. Nonetheless, you can then write xrandr --addmode VGA1 "1024x750_60.00" and that will then be a valid mode for the VGA1 output, which of course doesn’t help you unless you connect an external display to your VGA port.

      So basically, don’t try to do this by adding modes (I learned that by doing more or less what you are asking about).

  2. jose says:

    well the thing that was genius was something i believe you posted sometime ago:

    xrandr –newmode “1280×750″ 113.75 1280 1624 1784 2032 750 903 913 934 -hsync +vsync
    xrandr –addmode VGA1 1280×750
    xrandr –output VGA1 –mode 1280×750 –output LVDS1 –fb 1280×750 –scale 1.25×1.25

    this had the wonderfull efect of having a 1280×750 resolution on lvds1.
    after the upgrade to 12.04 it broke.
    funny but if i boot to previous version, ubuntu still says it is 12.04 and it works. but with the new kernel it freezes up the display and crashes pretty hard. no keyboard or anything at all.

    so i tried the panning like you mention (which was something i was trying to do originally with a script called newrez), but it won’t let me jump to this resolution. it is that tiny factor of 1.25 that makes the diference on these 10” netbooks!

  3. Ryan Reich says:

    Definitely wasn’t me. The following line works for me the way I think you intend:

    xrandr --output LVDS1 --fb 1024x750 --scale 1.25x1.25

    so if it fails for you, this may be an issue with the X server. I mentioned a possible patch for that in the post; perhaps you should go check if it works? I want to point out that the --output VGA1 --mode 1024x750 in your suggested command has no effect whatsoever, though. Just setting the framebuffer is what accounts for the apparent 1024×750 resolution.

    The “newrez” script seems to be just a wrapper around the xrandr commands, by the way.

    Just a note: you can’t really “reboot into the old version” of Ubuntu unless you actually keep it on a different partition. After you’ve upgraded, all the software is changed; the best you can do is run the line that your bootloader claims is Ubuntu 11.10, but that really just loads the old kernel without any other changes. So unless this has something to do with the kernel, it wouldn’t help. If in fact you get a hard freeze with the current kernel, you may have found a bug, in which case you had better go to launchpad and report it; I can’t help you here.

    • jose says:

      you have done more than could have been asked of you!

      thanks for that.

      i did notice that the ubuntu release was 12.04, i trust from the grub listing that it is a diferent kernel. i don’t see why the kernel would be doing this if it is the only diference. i’m not very knowlegeable of this and am returning to linux after a long time away from it.

      when i do
      xrandr –output LVDS1 –fb 1024×750 –scale 1.25×1.25

      it does make the resolution go to 1024×750, but the actual desktop seems to be 1024×600 window and the mouse is restricted to that space. the remaining space is just black.

      i’m going to downgrade the kernel to the previous version to see if i can go back to use the old options.

      • Ryan Reich says:

        Well, before you downgrade, try the rest of the advice in my post. It sounds like one of two things could be your problem:

        1. It could be that you are experiencing the X bug that I had. Go install that PPA and the patched X server that you can get from the launchpad bug I link to; it takes a minute and a logout and then you’ll know if it helps.
        2. It could also be that you are having a problem with Compiz. The “black bar” problem is symptomatic of that. Install the CompizConfig Settings Manager and go look into “General options”, at the display settings tab like I describe. Uncheck the “detect outputs” and add an output called “1024×750”. Does that help?

        You may have to do both.

  4. jose says:

    good advice. the screen now stretches out to 1280×750 but the mouse doesn’t go there. you got me on the right track but it’s 4am now and way past my bedtime. thanks again!

  5. Raz says:

    Could it be that the bugs you mention have all been fixed?
    Following the ubuntu wiki (https://wiki.ubuntu.com/X/Config/Resolution) and entering:
    $ xrandr –output LVDS1 –rate 60 –mode 1024×600 –fb 1024×768 –panning 1024×768
    gives me a nice vertical panning experience.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s