Monthly Archives: February 2015

Customising XDM for the modern desktop

As per my previous blog post, I’m now using XDM as a login manager. By default, it looks like something straight out of the ’80s. Having said that, it’s not too difficult to give it additional functionality ad make it look nice. With the help of this tutorial, I was able to put together the following:

My custom XDM theme.

My custom XDM theme.

As per the linked tutorial, I have used an embedded xmessage window to create the Shutdown and Reboot buttons.

In order to recreate this setup, you will need to do the following:

  1. Drop the meditate-black-bottom_right.png wallpaper into /etc/X11/xdm/.

    This file can actually be references from anywhere, but it makes sense to me at least to keep it all together.

    The wallpaper was taken from the FSF’s wallpaper section (specifically here) and is distributed under either the GPL3+ or GFDL1.1+ (with no invariant or front/back-cover texts). I just slapped it on a black 1920×1080 background and exported it as a PNG. I then load this as the XDM wallpaper via xloadimage. Note if you are doing your own modifications (perhaps to change the colour or resolution) that xloadimage will only render transparent pixels as white, and there is no built-in option to change this.

  2. Edit /etc/X11/xdm/xdm-config and replace the following lines:

    DisplayManager*resources: /etc/X11/xdm/Xresources becomes DisplayManager*resources: /etc/X11/xdm/Xresources_custom

    DisplayManager*setup: /etc/X11/xdm/Xsetup becomes DisplayManager*setup: /etc/X11/xdm/Xsetup_custom

    and

    DisplayManager*startup: /etc/X11/xdm/Xstartup becomes DisplayManager*startup: /etc/X11/xdm/Xstartup_custom

    We need to create the Xresources_custom, Xsetup_custom and Xstartup_custom files in the steps that follow.

  3. Create /etc/X11/xdm/Xresources_custom.
    This is basically the same as Xresources, only with some additional lines appended to the end. It can be created with the following two commands:

    # cp -f /etc/X11/xdm/Xresources /etc/X11/xdm/Xresources_custom
    # echo "
    
    Xmessage*geometry:              170x27+20+20
    Xmessage*background:            black
    Xmessage*foreground:            red
    Xmessage*Font:                  -xos4-terminus-*-r-normal-*-*-180-*-*-*-*-*-*
    Xmessage*borderWidth:           0
    
    Xmessage*message.scrollVertical:        Never
    Xmessage*message.scrollHorizontal:      Never
    Xmessage*message*background:            black
    
    Xmessage*Text*background:       white
    Xmessage*Text*foreground:       red
    Xmessage*Text.borderColor:      black
    Xmessage*Text.borderWidth:      0
    Xmessage*Text*font:             -xos4-terminus-*-r-normal-*-*-180-*-*-*-*-*-*" >> /etc/X11/xdm/Xresources_custom
    

    This assumes you have the Terminus font installed. If you don’t have it, you can either install it through your package manager or alternatively fire up xfontsel and select something else that works for you.

  4. Create /etc/X11/xdm/Xsetup_custom with the following contents:
    #!/bin/sh
    #
    # This script is run as root before showing login widget.
    
    #--- set a fullscreen image in background
    xloadimage -onroot -quiet -fullscreen /etc/X11/xdm/meditate-black-bottom_right.png
    
    #--- set Shutdown/Reboot buttons
    (
    xmessage -buttons Shutdown:20,Reboot:21 "" ;
    case $? in
        20)
    	TERM=linux openvt -c 1 -f /usr/bin/clear
            exec openvt -c 1 -f -s -- /sbin/shutdown -hP now
            ;;
        21)
    	TERM=linux openvt -c 1 -f /usr/bin/clear
            exec openvt -c 1 -f -s /sbin/reboot
            ;;
        *)
            echo "Xmessage closed on $(date)"
            ;;
    esac
    ) &
    

    Fix the path to the image in the xloadimage command if you placed the file (or a different background image) elsewhere.

    Notice we use the openvt command to switch to the first virtual console for the purposes of executing the shutdown or reboot commands. This is because (on Debian Wheezy at least), terminating Xorg with XDM running will switch you back to the first virtual console, so you’ll need the output printed there if you wish to see anything during the shutdown sequence.

  5. Create /etc/X11/xdm/Xstartup_custom with the following contents:
    #!/bin/sh
    #
    # This script is run as root after the user logs in.  If this script exits with
    # a return code other than 0, the user's session will not be started.
    
    # terminate xmessage
    killall xmessage
    
    # set the X background to plain black
    xsetroot -solid black
    
    if [ -x /etc/X11/xdm/Xstartup ]; then
      /etc/X11/xdm/Xstartup
    fi
    
    # vim:set ai et sts=2 sw=2 tw=0:
    

    As can be seen from this last few lines, we still re-use the contents of the original Xstartup script, so keep that around if using these scripts as is.

  6. Finally, make sure the new files have the correct permissions. Xresources_custom only needs to provide read access, but Xsetup_custom and Xstartup_custom should be executable.

    # chmod 0644 /etc/X11/xdm/Xresources_custom
    # chmod 0755 /etc/X11/xdm/Xsetup_custom /etc/X11/xdm/Xstartup_custom
    

And there you have it, and beautiful-looking XDM setup, that runs extremely fast but still includes the shutdown and reboot buttons.

How to replace LightDM with XDM in Wheezy

My machine is an Asus G55VW laptop, and it seems to have a very annoying UEFI or Nvidia driver bug. Even under Windows (which the laptop came with), everybody with this model is experiencing odd behaviour – the laptop will fail to detect the display properly in certain situations and attempt to output the screen to an external monitor – even if nothing is connected! Under Windows 8.1, this means the login screen isn’t displayed, and one must press Meta+P, hit the down arrow once or twice, and press enter (and do this until the internal laptop screen is activated). It’s absolutely horrible, and has only showed itself in the Windows world upon upgrading to Windows 8.1.

On Debian with LightDM however, I have experienced what I believe is this same issue (based on Xorg log file analysis) ever since I brought home the machine. Unlike Windows, I can login okay. However logging out of XFCE to the LightDM display manager causes the internal laptop screen to not be detected correctly during the switch. The result is a blank screen, and LightDM has no way (AFAICT) to switch display output via a shortcut when it’s already running. Further, it even prevents switching to a virtual console as no image will reappear if I hit Ctrl+Alt+F1 for example (which shouldn’t ever happen without explicitly disabling it in the Xorg config at least, which I certainly haven’t). The only option in such a situation is to switch to a virtual console and blindly hit Ctrl+Alt+Del and wait for the UEFI screen to appear.

Until recently (when Windows was upgraded to 8.1 and showed similar symptoms), I had always attributed this behaviour to a bug in Wheezy (since I purchased the laptop around the time Wheezy was being marked as stable so it could not have been tested on this model) and assumed it would be solved in time with Jessie, but now I’m not so sure. Rebooting the machine is very quick (the longest part easily being the lengthy passphrase required for cryptsetup) – quick enough that I’ve never bothered getting to the bottom of it, particularly since I can generally avoid hitting the problem in the first place since I’m so familiar now with what triggers it. However now I’m seeing such odd and annoying behaviour from both operating systems, it’s time to do something about it.

The only reliable way to avoid this is to activate CSM in the UEFI (to mimic BIOS functionality), but that has a number of drawbacks. The boot output resolution is restricted to VESA modes, which look horrible on a 1920×1080 display (especially when UEFI detects the resolution perfectly and looks beautiful). It also means I can’t use the rEFInd boot manager, which I now much prefer over GRUB on desktops and laptops. CSM also prevents enabling “Fast Boot” in the BIOS, which introduces a small but unnecessary delay. Indeed, enabling CSM feels like a significant step backwards, so I will try to avoid that wherever possible.

I’ve tried GDM3 temporarily, and that had the same issue at first. However I found that pressing fn+F8 (the LCD/monitor switching/toggle button) surprisingly worked and brought the picture back so I could see the login prompt. It even seemed to remember this setting somehow as I was never able to reproduce the issue with GDM3 after that. I thought that was the end of this dilemma and I could get back to doing something else. Unfortunately GDM3 had other issues.

Firstly, upon wearing headphones during login I was able to hear my laptop internal microphone was active via a loud hissing noise, and confirmed this by tapping the mic. I could find no way to turn this off, and could not think of any reason why GDM3 would be doing that. Secondly, I didn’t like the user accounts listed for selection. I wanted to type my username, as there is no reason to make the login name unnecessarily obvious. There was an option in the GDM theme config to allow this, but it wasn’t reliable. If I started entering my username and hit Escape or Ctrl+C (with the expectation that I could clear the box in the event of a typo), the login window would disappear completely and I’d have to reboot. Yuck!

But the worst issue of all, GDM3 was just too slow to keep up with my typing speed! I would type in my username, hit enter or tab, and then start typing in my password. Only the password would be missing the first few characters since the password box had not properly appeared yet. Even after all of that, there was a noticeable delay in launching my XFCE desktop. I can only imagine what it was doing with those CPU cycles.

So looking around at other display managers packaged in Wheezy, I found two suitable options – SLiM, and XDM. I didn’t know much about SLiM. I knew XDM was about as bare-bones as one could get, I knew it was fast, and I knew it required manually typing the username… it seemed to be the way to go, so I set out to make that happen.

$ sudo apt-get install xdm

I selected XDM to be my default login manager, rebooted, and there it was in all its glory. There were some things missing however – no X session manager list to choose from (which is perfectly fine), but also no shutdown and reboot options. I could live without those, although I still expected it would be a minor inconvenience. I was happy with the speed of the prompts – it felt slightly quicker than LightDM (that is, probably no perceivable delay). However XFCE spent about 20 seconds to appear. When it had finally loaded, some issues were encountered. For one thing, USB mounting wasn’t working. Manually clicking the mount button in Nautilus caused a “Not authorized” error to be displayed, with no hint as to why. The USB drives didn’t automatically mount via my usb_mass_mount.sh script either. I eventually noticed that even Network Manager wasn’t working!

Was all of this because I was using XDM? Some quick web searches for “Debian xfce xdm” indicated as such. Was it worth trying to fix it? I logged out of XFCE (observing as I went that even the reboot, shutdown, suspend and hibernate options were either missing or greyed out) and XDM continued to output to the correct monitor. Whatever this issue is with my model of laptop, XDM is not affected. With this and it’s impressive text entry speed, I decided these XDM issues were worth looking into.

What followed was a lot of careful analysis of the scripts under /etc/X11/Xsession.d/, and much research into what was causing this. Essentially, this can all be fixed with two or three minor changes – but they are amazingly difficult to figure out if you’ve never looked into the related technologies before.

PAM
In /etc/pam.d/common-session at the bottom of the file, there is the line “session optional pam_ck_connector.so nox11“. From the pam_ck_connector(8) man page, the nox11 argument tells the PAM module to not create a session if PAM specifies an X11 display instead of a /dev/tty terminal. I guess the assumption is that the display manager will handle this automatically, but XDM is too primitive to have ConsoleKit support. Hence remove that nox11 bit from the line. I actually like to copy the line, modify the copied line and then comment out the original, so such changes are slightly more obvious and easier to undo if I ever need to revert. Alternatively, take a backup. :)

Xsession
Our session needs to be started with /usr/bin/ck-launch-session. This is supposed to happen from /etc/X11/Xsession.d/90consolekit when it’s required, but it’s broken and needs to be fixed. There are a few ways to do this. Ideally I would have found a way to just bypass this script entirely (replacing the functionality with something in my home directory) but any fix would involve some kind of modification under /etc/X11 somewhere that I figured it best to just fix this at the root of the problem. Here is my patch:

--- 90consolekit.orig	2015-02-04 17:42:07.549621276 +0800
+++ 90consolekit	2015-02-04 17:41:25.021379155 +0800
@@ -24,9 +24,17 @@ is_on_console() {
 	fi
 }
 
+is_xdm() {
+	if [ "$(pgrep -cfx /usr/bin/xdm)" -ge 1 ] ; then
+		return 0
+	else
+		return 1
+	fi
+}
+
 # gdm already creates a CK session for us, so do not run the expensive D-Bus
 # calls if we have $GDMSESSION
 if [ -z "$GDMSESSION" ] && [ -x "$CK_LAUNCH_SESSION" ] && \
- ( [ -z "$XDG_SESSION_COOKIE" ] || is_on_console ) ; then
+ ( [ -z "$XDG_SESSION_COOKIE" ] || is_on_console || is_xdm ) ; then
     STARTUP="$CK_LAUNCH_SESSION $STARTUP"
 fi

Seems to do the job. Doesn’t break compatibility with startx (presumably – my laptop display doesn’t seem to work with that either so can’t verify) or other display managers since it specifically tests to see if XDM is running.

usb_mass_mount.sh
My lovely USB automatic mount script has been intermittently failing since switching to XDM, and it wasn’t immediately obvious why since it only failed during login and could not be reproduced afterwards. I quickly discovered that the udisks command was also actually returning a Not authorized error (the same as was observed from Nautilus prior to the above fixes) – something I did not encounter under LightDM. AFAICT, the login is so fast now that it tries to run before ConsoleKit has properly initialized! I simply added in a 0.1 second delay (because as programmers know this always fixes everything), and now it’s working perfectly again.

# Mount all USB block devices that have a filesystem label.

for device in $(find /dev/disk/by-path -name '*usb*' -exec readlink -f {} \;)
do
    if [ -b "${device}" ] && blkid "${device}" | grep -q LABEL
    then
        if ! mount | grep -q "^${device} on "
        then
            ( 
                sleep 0.1
                udisks --mount "${device}"
            ) &
        fi
    fi
done

And there we have it, a lightning fast XDM login screen, and now I can actually log out and in again as well!