From 67ddbe23ab1fb8b7fbad245120eeb08e5b2ae309 Mon Sep 17 00:00:00 2001 From: "R. Steve McKown" Date: Sat, 31 Jan 2015 16:27:52 -0700 Subject: [PATCH] New blog entry dispcfg --- in/blog/dispcfg.md | 163 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 in/blog/dispcfg.md diff --git a/in/blog/dispcfg.md b/in/blog/dispcfg.md new file mode 100644 index 0000000..b0e872d --- /dev/null +++ b/in/blog/dispcfg.md @@ -0,0 +1,163 @@ +title: dispcfg +linktitle: dispcfg +parent: 2015-01 +ctime: 2015-01-30 +mtime: 2015-01-31 + +# Automatic Display Configuration + +I've been using a Thinkpad X201 for a few years now, and had previously written +a script, [[displayset]], which I called from application shortcuts. `l` +set laptop mode and `super` set dual external display mode. + +Over time, this proved to be too restrictive. For example, when working on-site +at a customer location, I may receive access to one or two monitors of differing +resolutions than the monitors in my office used when the notebook was docked. I +ended up using a display configuration app bundled with XFCE, which was fine but +was far from automatic. + +I decided to smarten up [[displayset]] so that it would query attached displays +via XRANDR and then configure according to some simple rules. [[dispcfg]] was +born. + +# Goals of dispcfg + +My goals for a smarter display configuration tool were fairly straight forward: + +* Find the output devices `xrandr` shows as connected, +* Configure the 'best' two outputs as the canvas for X, and +* Require no human intervention. + +For dispcfg to configure the displays automatically, I had to set some rules. +Namely, the priority of display devices, and the positioning of display devices +relative to each other. + +## Display priority + +The Thinkpad X201 has four display outputs, but the Intel graphics hardware can +only use any two at one time. I elected to prefer external displays to the +internal LCD panel, and to prefer digital external outputs over analog external +outputs. `xrandr` shows the possible X201 outputs in the order of ascending +preference, least preferable first, which was perfect for my case but may not be +true for other computer systems. The four X201 display outputs are: + +* LVDS1 -- the internal LCD panel +* VGA1 -- output on notebook and on dock +* HDMI1 -- output on dock +* DP1 -- output on dock + +Therefore a simple, repeatable algorithm can be used to select the display +devices. In the given order above, pick the last two outputs showing connected +state if two or more outputs are showing connected. If one output is showing +connected it will be LVDS1, as the LCD panel is (should be) always connected. + +## Display positioning + +To automatically configure the displays for use by X, positioning information is +required. To meet the goal of no human intervention, some automated method for +determining, or remembering, positioning information is requried. The most +powerful method would be to implement a database of display combinations, using +information provided by each display so each set of displays can have a +persistent positioning configuration. I didn't investigate this option, because +it was more work than I wanted to put into this project. I also expect DPMS +information from the monitors would be less than ideal for this strategy, +although it's possible something could be crafted that would be good enough to +be useful. + +I elected for a much simpler methodology. Instead, I always asssume that +connected displays are always arranged from left to right, with the most +preferred display on the left when two displays will be utilized. So if any one +external monitor is connected, it is assumed to be on the immediate left of the +LCD panel. And if any two external monitors are connected, it is assumed they +are side by side. If HDMI1 and VGA1 are connected, HDMI1 is on the left. If +DP1 is connected, it is on the left. + +Not accounting for presentation situations, this simple positioning rule works +perfectly for all the places I've used my X201 with external monitors. It +doesn't work for vertically stacked orientations, which I've not really used +much. Nor does it serve to perfectly fine-tune vertical positioning between +panels of different vertical display heights. But for my use these limitations +are not significant. + +# How it works + +The [[dispcfg]] script is written in python. The documentation for the Xlib +module for Python assumes familiarity with Xlib and how the XRANDR extension +works. To reduce the time investment for this project I instead opted to parse +the output of the `xrandr` command line utility instead. I'm running +[[dispcfg]] on Xubuntu 14.04, but it probably would work fine on any recent-ish +version of Linux and display devices that support XRANDR. + +The operation of the script is quite simple: (1) find the connected devices, (2) +select the one or two best, then (3) use `xrandr` to configure these outputs. X +receives notification of the change in display, which is then passed on to the +window manager, which then presumably will do something useful given the change. +Thankfully the result of running `xrandr` to configure outputs in the same +manner in which they are already configured results in no apparently disruption +to X, as far as I can tell, so running [[dispcfg]] when one doesn't need to is +safe. + +Then, one need only invoke [[dispcfg]] whenever the display connections are +changed, or when they are likely to have changed. I'm calling [[dispcfg]] when: + +* The window manager starts +* The computer resumes from suspend +* Upon the user depressing the Alt+ScrollLock key combination + +This strategy has proven to work quite well. I generally end up changing +display configurations when the computer is suspended, for example moving from +my office to a customer location. So running [[dispcfg]] automatically when +resuming catches most display configuration changes I see. I rarely power off +my computer or reboot it, but when I do, calling [[dispcfg]] when the window +manager starts catches these events. Finally, for the case when I'm changing +displays while the computer is active, a simple tap on Alt+ScrollLock does the +job. + +# Possible improvements + +## Automatically detect monitor changes + +The XRANDR extension and infrastructure allows one to create a daemon that is +listening for display changes. [[dispcfg]] could be daemonized so its operation +would even be more automatic. However, this might actually be undesirable. For +example, unplugging a monitor and then plugging it back in has a no net effect +to the output devices available, but the transition of one monitor leaving and +then returning might have a less than desirable affect for how the window +manager ends up positioning windows. While it is certainly possible for +[[dispcfg]] to become this automated, the increased utility might be eclipsed by +annoying side effects. + +## Presentations + +I occasionally give presentations. Often it is very convenient to mirror the +notebook LCD panel with an external display such as a projector. [[dispcfg]] +offers no support for this mode of operation. Being able to run [[dispcfg]] +with an option to request presentation mode could alter its behavior to use the +'best' connected external monitor and the internal LCD panel at the highest +resolution common to both devices, possibly with fall-back to 1024x768 for older +projectors that don't support DPMS correctly. It wouldn't be terribly difficult +to add this feature. + +# Where's the code? + +The [[dispcfg]] utility is available in the GIT repository located +[here](/gitweb/?p=dispcfg.git;a=summary). + +# What about displayset's maximized window mode? + +The original [[displayset]] offered one interesting feature that [[dispcfg]] +does not. When [[displayset]] was executed with the `lcd` option, it would +configure only the LCD output, set all current windows to maximized, and +instruct the window manager to create all future windows maximized. This was +useful because the X201 LCD panel is only 1366x768. Especially in vertical +resolution the LCD panel is wanting, and maximizing application windows helps. + +This feature is not present in [[dispcfg]] for two reasons. First, it seems to +me that the role of [[dispcfg]] is to configure displays for use by X. How X +uses the display area is generally the role of the window manager, and any +behavior embedded in [[dispcfg]] to give hints to a window manager could make it +less generic. Second, I've changed to a tiling window manager, where a 'hint' +to maximize windows isn't really useful. I'm having a great experience with +[i3][] and hope to write about it in the future. + +[i3]: http://i3wm.org "i3 Tiling Window Manager" -- 2.39.2