http://www.linuxjournal.com/content/switching-monitor-profiles
It's funny, when your home office is your couch, you tend to forget how nice it can be when you dock a laptop and have all the extra screen real estate a monitor brings. For many years, I left my work laptop docked at work, and when I worked from home, I just VPNed in with a personal laptop. Lately though, I've recognized the benefits of splitting personal life and work, so I've taken to carrying my laptop with me when I go to and from the office. Because we invested in a docking station, it's relatively simple to transition between a laptop on my lap and a laptop on a desk with an extra monitor—except for one little thing: my external monitor is in portrait mode.
It must have been about two years ago that I started favoring widescreen monitors in portrait mode (Figure 1). Really, all I need to get work done is a Web browser and a few terminals, and I found if I keep the Web browser on the laptop screen, I can fit a nice large screen session or two in all the vertical space of a portrait-mode monitor. This makes reading man pages and other documentation nice, plus I always can split my screens vertically if I need to compare the contents of two terminals (see my "Do the Splits" column in the September 2008 issue for more information on how to do that: http://www.linuxjournal.com/article/10159). The only problem with portrait mode is that all the GUI monitor configuration tools tend not to handle portrait-mode monitors well, particularly if you want to combine them with a landscape-mode laptop screen. So, I found I needed to run a special xrandr command to set up the monitor and make sure it lined up correctly with my laptop screen. Plus, every time I transition between docked and undocked modes, I need to move my terminal windows from the large portrait-mode monitor over to a second desktop on my laptop screen. This all seemed like something a script could figure out for me, so in this article, I explain the script I use to transition from docked to undocked mode.
Figure 1. Kyle's Current Desktop Setup
Basically, my script needs to do two things when it's run. First, it needs to run the appropriate xrandr command to enable or disable the external display, and second, it needs to reset all of my windows to their default location. Although I could just have one script I run when I'm docked and another when I'm undocked, I can find out my state from the system itself, so I can keep everything within one script. I've set up a script like this on my last two work-provided laptops and on the ThinkPad X220, I was able to use a /sys file to gauge the state of the dock:
Now that I can detect whether I'm docked, I should do something about it. The first thing I need to do is to enable output on my external monitor (HDMI3), tell xrandr that it's to the right of my laptop screen, and set it to portrait mode by telling xrandr to rotate it left:
It's funny, when your home office is your couch, you tend to forget how nice it can be when you dock a laptop and have all the extra screen real estate a monitor brings. For many years, I left my work laptop docked at work, and when I worked from home, I just VPNed in with a personal laptop. Lately though, I've recognized the benefits of splitting personal life and work, so I've taken to carrying my laptop with me when I go to and from the office. Because we invested in a docking station, it's relatively simple to transition between a laptop on my lap and a laptop on a desk with an extra monitor—except for one little thing: my external monitor is in portrait mode.
It must have been about two years ago that I started favoring widescreen monitors in portrait mode (Figure 1). Really, all I need to get work done is a Web browser and a few terminals, and I found if I keep the Web browser on the laptop screen, I can fit a nice large screen session or two in all the vertical space of a portrait-mode monitor. This makes reading man pages and other documentation nice, plus I always can split my screens vertically if I need to compare the contents of two terminals (see my "Do the Splits" column in the September 2008 issue for more information on how to do that: http://www.linuxjournal.com/article/10159). The only problem with portrait mode is that all the GUI monitor configuration tools tend not to handle portrait-mode monitors well, particularly if you want to combine them with a landscape-mode laptop screen. So, I found I needed to run a special xrandr command to set up the monitor and make sure it lined up correctly with my laptop screen. Plus, every time I transition between docked and undocked modes, I need to move my terminal windows from the large portrait-mode monitor over to a second desktop on my laptop screen. This all seemed like something a script could figure out for me, so in this article, I explain the script I use to transition from docked to undocked mode.
Figure 1. Kyle's Current Desktop Setup
Basically, my script needs to do two things when it's run. First, it needs to run the appropriate xrandr command to enable or disable the external display, and second, it needs to reset all of my windows to their default location. Although I could just have one script I run when I'm docked and another when I'm undocked, I can find out my state from the system itself, so I can keep everything within one script. I've set up a script like this on my last two work-provided laptops and on the ThinkPad X220, I was able to use a /sys file to gauge the state of the dock:
#!/bin/bash
DOCKED=$(cat /sys/devices/platform/dock.0/docked)
case "$DOCKED" in
"0")
echo undocked
;;
"1")
echo docked
;;
esac
Unfortunately, on my new laptop (a ThinkPad X230) this file no longer
can detect the dock state. At first I was annoyed, but when writing this
column, I realized that this made the script potentially more useful
for everyone who doesn't have a docking station. My workaround was to
use xrandr itself to check for the connection state of a video device
my external monitor was connected to that was present only when I was
docked. If you run xrandr with no other arguments, you will see a list
of a number of different potential video devices on your system:
$ xrandr
Screen 0: minimum 320 x 200, current 1366 x 768, maximum 8192 x 8192
LVDS1 connected 1366x768+0+0 (normal left inverted right x axis y axis)
↪277mm x 156mm
1366x768 60.0*+
1360x768 59.8 60.0
1024x768 60.0
800x600 60.3 56.2
640x480 59.9
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
DP1 disconnected (normal left inverted right x axis y axis)
HDMI2 disconnected (normal left inverted right x axis y axis)
HDMI3 disconnected (normal left inverted right x axis y axis)
DP2 disconnected (normal left inverted right x axis y axis)
DP3 disconnected (normal left inverted right x axis y axis)
In the above case, the laptop is not docked, so only the primary monitor
(LVDS1) is connected. When I docked the device and ran the same command,
I noticed that my monitor was connected to HDMI3, so I could grep for
the connection state of HDMI3 to detect when I'm docked. My new skeleton
script looks more like this:
#!/bin/bash
xrandr | grep -q "HDMI3 disconnected"
case "$?" in
"0")
echo undocked
;;
"1")
echo docked
;;
esac
In your case, you would compare the output of xrandr when docked (or
when an external monitor is connected) and when undocked, and use that
to determine which device it corresponds to.
Now that I can detect whether I'm docked, I should do something about it. The first thing I need to do is to enable output on my external monitor (HDMI3), tell xrandr that it's to the right of my laptop screen, and set it to portrait mode by telling xrandr to rotate it left:
/usr/bin/xrandr --output HDMI3 --auto --right-of LVDS1 --rotate left
This works fine; however, the way that the portrait-mode monitor and
my laptop line up on the desktop makes moving a mouse between the two
rather awkward. When I move from the top of the laptop screen to the far
right edge, the mouse pointer moves a foot up to the top of the external
monitor. Ideally, I'd like the mouse pointer to more or less be lined up
when it crosses between screens, but because one monitor is landscape and
the other is portrait, I need to tell xrandr to place my laptop monitor
lower in the virtual desktop. Depending on your respective resolutions,
this position takes some tinkering, but I found the following command
lined up my two displays well:
/usr/bin/xrandr --output LVDS1 --pos 0x1152
This takes care of my screen when I'm docked, so when I'm undocked, I
basically have to undo any of the above changes I've made. This means
turning the HDMI3 output off and moving the position of LVDS1 back to
the 0x0 coordinates:
/usr/bin/xrandr --output HDMI3 --off
/usr/bin/xrandr --output LVDS1 --pos 0x0
The complete case statement turns out to be:
#!/bin/bash
xrandr | grep -q "HDMI3 disconnected"
case "$?" in
"0") # undocked
/usr/bin/xrandr --output HDMI3 --off
/usr/bin/xrandr --output LVDS1 --pos 0x0
;;
"1") # docked
/usr/bin/xrandr --output HDMI3 --auto --right-of LVDS1
↪--rotate left
/usr/bin/xrandr --output LVDS1 --pos 0x1152
;;
esac
After I saved the script, I bound a key combination on my desktop I could
press to execute it whenever I docked or undocked. Of course, ideally I would
set up some sort of udev script or something like it to
run the script automatically, but so far, I haven't found the right hook that worked
on my laptop. The only other addition I've made is after the above case
statement, I sleep for a second and then call a reset_windows shell script
that uses wmctrl, much like I discussed in my November 2008 Hack and /
column "Memories of the Way Windows Were" (http://www.linuxjournal.com/article/10213), only it also contains the
same case statement so it moves windows one way when docked and another
when not:
#!/bin/bash
xrandr | grep -q "HDMI3 disconnected"
case "$?" in
"0") # undocked
wmctrl -r 'kyle-ThinkPad-X230' -t 1
wmctrl -r 'kyle-ThinkPad-X230' -e '0,2,24,1362,362'
wmctrl -r snowball -t 1
wmctrl -r snowball -e '0,2,410,1362,328'
;;
"1") # docked
wmctrl -r 'kyle-ThinkPad-X230' -t 0
wmctrl -r 'kyle-ThinkPad-X230' -e '0,1368,0,1080,1365'
wmctrl -r snowball -t 0
wmctrl -r snowball -e '0,1368,1387,1080,512'
;;
esac
Of course, the above wmctrl commands are completely custom to my terminal
titles, but it should serve as an okay guide for getting started on your own. In my
case, I want to move two terminals to the second desktop when in laptop
mode and to the external monitor on the first desktop when docked. Why not
just combine the two scripts? Well, I want to be able to reset my windows
sometimes outside of docking or undocking (this script also is bound to
a different key combo). In the end, I have a simple, easy-to-modify set of
scripts I can use to keep windows and my desktops exactly how I want them.
No comments:
Post a Comment