The i3 FAQ has migrated to https://github.com/i3/i3/discussions. All content here is read-only.
Ask Your Question
1

Is there a way to keybind display changes?

asked 2015-05-31 20:00:24 +0000

this post is marked as community wiki

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 ... (more)

edit retag flag offensive close merge delete

Comments

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.

Airblader gravatar imageAirblader ( 2015-05-31 20:48:38 +0000 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2015-06-01 05:04:47 +0000

Airblader gravatar image

updated 2015-06-01 05:12:44 +0000

So now I read your question and I'm fairly certain this is what you are looking for. You can use i3subscribe and execute this on startup:

while read event; do ~/scripts/screenlayout.sh; done < <(i3subscribe output)

Moving on:

I would like to have i3 remember which workspaces were on which outputs and put them back; does anyone have an idea how I could do that?

i3 will move all workspaces to another existing output if an output disappears, it doesn't remember on which output they were before. You could submit this as a feature request on Github, though. To get it working right now, the easiest way would indeed be to just put specific workspaces on specific outputs.

I would also like to run it too when I close my laptop lid, but xev doesn't show any event on lid close

No, I don't think there's an event for that. AFAIK, i3 subscribes to all RandR events and if this caused the output to disappear, i3 would crash in all released versions (there was a bug/feature regarding this) since no output is available anymore. But I'm sure we would've received plenty bug reports if this would've been the case. Hence, I doubt such an event is fired from X.

edit flag offensive delete link more

Comments

Ah. i3subscribe is what I want, thank you.

kousu gravatar imagekousu ( 2015-06-01 05:48:03 +0000 )edit

Question Tools

Stats

Asked: 2015-05-31 20:00:24 +0000

Seen: 198 times

Last updated: Jun 02