Is there a way to keybind display changes?
asked 2015-05-31 20:00:24 +0000
This post is a wiki. Anyone with karma >100 is welcome to improve it.
I would like to run a command when I plug or unplug a monitor. Gnome puts new outputs in their largest resolution, switches to single-monitor when I close my laptop lid, and remembers which side I put the external on relative to the laptop screen and what workspaces were there when I reopen the lid. I am trying to replicate this all in an i3ish way.
As glue, I generate screenlayouts with arandr and save them to ~/.screenlayout
, and use this:
#!/bin/sh
# screenlayout.sh
export LAYOUTS=~/.screenlayout/
xrandr --auto
$SHELL ${LAYOUTS}$((cd ${LAYOUTS}; ls *) | zenity --list --column=Screenlayout)
I have been invoking this in my ~/.xinitrc
so that when I boot I get a choice. This works well enough for a system I don't use too often, but I want to do better now. I want to configure i3 to react to randr changes, is this possible?
Sniffing the X events, there is an event which. But
[kousu@spun ~]$ xev -event randr
Outer window is 0x2200001, inner window is 0x2200002
RRNotify event, serial 25, synthetic NO, window 0x2200001,
subtype XRROutputPropertyChangeNotifyEvent
output VGA1, property EDID, timestamp 35432061, state Delete
RRScreenChangeNotify event, serial 25, synthetic NO, window 0x2200001,
root 0x7e, timestamp 5696498, config_timestamp 35433437
size_index 65535, subpixel_order SubPixelUnknown
rotation RR_Rotate_0
width 1280, height 1024, mwidth 337, mheight 269
RRNotify event, serial 25, synthetic NO, window 0x2200001,
subtype XRROutputChangeNotifyEvent
output VGA1, crtc 63, mode 800x600 (800x600)
rotation RR_Rotate_0
connection RR_Disconnected, subpixel_order SubPixelUnknown
But
bindsym RRScreenChangeNotify exec screenlayout
does not do anything (neither error nor result) which doesn't surprise me as that's an XEvent not an XKeySym. Is there any way to bind to generic X events (without writing my own C program?). There isn't a secret i3 bindevent, is there?
I have a better `screenlayout.sh':
#!/bin/sh
xrandr --auto
xrandr --output VGA1 --right-of LVDS1 2>/dev/null
The first form of xrandr isn't documented, but (as of xrandr 1.4.3), it resets the outputs to their boot state, which for me is: either only the internal monitor turned on, or both monitors on at the same resolution if the external is plugged in (the i3 user guide doesn't mention this trick; instead it explicitly configures both: xrandr --output VGA1 --mode 1024x768 --same-as LVDS1
). The second one then sets the external monitor where I want it, but if the external isn't plugged in it will fail silently, which is fine.
I would like to run this script whenever the screen configuration changes. How do I listen for randr events?
I would also like to run it too when I close my laptop lid, but xev doesn't show any event on lid close; my understanding is that you need to hook ACPI (!) just for this, and also that turning off the power to the monitor (dpms) doesn't remove it from xrandr's list of active monitors, so the script above is not enough. Is there a simple XCloseLid that I missed and could ...
Haven't read through all of this, but: i3 emits an `output` event on the IPC and you can always subscribe to that and use `i3-msg` to execute any command you want.