Disabling/enabling monitor does not call RandRFunc
Closed this issue · 8 comments
Upfront Information
-
Fvwm3 version: fvwm3 1.0.7 (1.0.6a-8-g2327aac1)
-
Linux distribution or BSD name/version: Debian 11.6 Bullseye
-
Platform (run:
uname -sp
): Linux unknown
Expected Behaviour
I expected RandRFunc to trigger when connecting/disconnecting a monitor. Basically on xrandr --output HDMI-1 --off
and xrandr --output HDMI-1 --auto
.
Actual Behaviour
The RandRFunc is not triggered.
FvwmEvent's monitor_enabled
/monitor_enabled
functions are also not triggered.
RandRFunc is called correctly on resolution and position change (for example xrandr --output HDMI-1 --right-of DP-1
)
Steps to Reproduce
I'm using this minimal configuration file:
BugOpts DebugRandR true
DestroyFunc RandRFunc
AddToFunc RandRFunc
+ I Echo "randrfunc called"
Then executing xrandr --output HDMI-1 --auto
followed by xrandr --output HDMI-1 --off
gives the following output in the log, but "randrfunc called" is not logged.
[1676715323.394479] monitor_output_change: monitor_output_change: outputs have changed
[1676715323.397734] monitor_update_ewmh: monitor debug...
[1676715323.397788] monitor_dump_state: Monitor Debug
[1676715323.397808] monitor_dump_state: number of outputs: 2
[1676715323.397833] monitor_dump_state: Name: DP-1
Disabled: false
Is Primary: yes
Is Current: yes
Is Previous: yes
Output: 68
Coords: {x: 0, y: 0, w: 2560, h: 1440}
VirtScr: {
VxMax: 0, VyMax: 0, Vx: 0, Vy: 0
EdgeScrollX: 0, EdgeScrollY: 0
CurrentDesk: 0
CurrentPage: {x: 0, y: 0}
MyDisplayWidth: 2560, MyDisplayHeight: 1440
}
Desktops: yes
Flags:global
[1676715323.397884] monitor_dump_state: Name: HDMI-1
Disabled: false
Is Primary: no
Is Current: no
Is Previous: no
Output: 71
Coords: {x: 0, y: 0, w: 1920, h: 1080}
VirtScr: {
VxMax: 0, VyMax: 0, Vx: 0, Vy: 0
EdgeScrollX: 0, EdgeScrollY: 0
CurrentDesk: 0
CurrentPage: {x: 0, y: 0}
MyDisplayWidth: 2560, MyDisplayHeight: 1440
}
Desktops: yes
Flags:global
[1676715323.417977] ewmh_ComputeAndSetWorkArea: monitor 'DP-1': {l: 0, r: 0, t: 0, b: 0} {x: 0, y: 0, w: 2560, h: 1440}
[1676715323.419066] ewmh_ComputeAndSetWorkArea: monitor 'HDMI-1': {l: 0, r: 0, t: 0, b: 0} {x: 0, y: 0, w: 1920, h: 1080}
[1676715329.950613] monitor_output_change: monitor_output_change: outputs have changed
[1676715329.954508] monitor_update_ewmh: monitor debug...
[1676715329.954562] monitor_dump_state: Monitor Debug
[1676715329.954579] monitor_dump_state: number of outputs: 2
[1676715329.954593] monitor_dump_state: Name: DP-1
Disabled: false
Is Primary: yes
Is Current: yes
Is Previous: yes
Output: 68
Coords: {x: 0, y: 0, w: 2560, h: 1440}
VirtScr: {
VxMax: 0, VyMax: 0, Vx: 0, Vy: 0
EdgeScrollX: 0, EdgeScrollY: 0
CurrentDesk: 0
CurrentPage: {x: 0, y: 0}
MyDisplayWidth: 2560, MyDisplayHeight: 1440
}
Desktops: yes
Flags:global
[1676715329.954656] monitor_dump_state: Name: HDMI-1
Disabled: false
Is Primary: no
Is Current: no
Is Previous: no
Output: 71
Coords: {x: 0, y: 0, w: 1920, h: 1080}
VirtScr: {
VxMax: 0, VyMax: 0, Vx: 0, Vy: 0
EdgeScrollX: 0, EdgeScrollY: 0
CurrentDesk: 0
CurrentPage: {x: 0, y: 0}
MyDisplayWidth: 2560, MyDisplayHeight: 1440
}
Desktops: yes
Flags:global
[1676715329.956858] ewmh_ComputeAndSetWorkArea: monitor 'DP-1': {l: 0, r: 0, t: 0, b: 0} {x: 0, y: 0, w: 2560, h: 1440}
[1676715329.957642] ewmh_ComputeAndSetWorkArea: monitor 'HDMI-1': {l: 0, r: 0, t: 0, b: 0} {x: 0, y: 0, w: 1920, h: 1080}
Yes. I'm sure when I last looked into this, using xrandr --off isn't the same thing as yanking an HDMI cable out the back of the monitor...
Ah, ok. I was trying to debug a multimonitor-problem and thought it would be easier to run an xrandr-command than to reach under the table to yank the cable.
After actually trying to unplug/replug the cable I should maybe describe the original problem I had:
The problem I'm trying to solve is to automatically move FvwmButtons to the currently primary monitor.
- If the external monitor is not plugged in, the laptop's monitor is primary
- If the external monitor is plugged in, this monitor is primary
I'm using autorandr to reconfigure which monitor is primary, based on if the external monitor is plugged in or not.
So in summary the actual issue is that RandRFunc is not called when autorandr reconfigures the screens, including changing the primary screen. So if fvwm can't do this I might have to find another way. Or perhaps functionality to detect randr's changing of primary screen could be implemented in fvwm somehow?
I'll look into it.
Have a look at the ta/add-prev-primary
branch, which now introduces a new variable $[monitor.prev_primary]
which you can use to ascertain the name of a previous monitor which was marked as primary. Hence:
DestroyFunc RandRFunc
DestroyFunc RandRFunc
+ I Echo "Primary is: $[monitor.primary], previous: $[monitor.prev_primary]"
To your earlier observations, I was remembering correctly. If you use xrandr
to turn off one of your monitors, have a look at the output from xrandr
-- it will still show as connected.
Your patch works fine when executing the xrandr-commands manually. But annoyingly enough not when letting autorandr handle the monitors.
I think I traced autorandr's behaviour to the following. At least I get the same end result:
(HDMI-1 is my external monitor and DP-1 internal)
- connect cable
xrandr --output HDMI-1 --right-of DP-1 --primary --auto
- disconnect cable
xrandr --output HDMI-1 --off
I think this is the culpritxrandr --output DP-1 --primary
End result: RandrFunc is not called when setting primary in the last step. Maybe because the HDMI monitor has been turned off and fvwm cannot keep track of it anymore?
These steps works as expected. And will cause RandRFunc to be called when setting primary:
- connect cable
xrandr --output HDMI-1 --right-of DP-1 --primary --auto
- disconnect cable
xrandr --output DP-1 --primary
End result: RandrFunc is not called when setting primary in the last step. Maybe because the HDMI monitor has been turned off and fvwm cannot keep track of it anymore?
Yup.
Ok, but how about ignoring which other monitor was primary, and just check if the monitor in question was not primary. Like this:
diff --git a/fvwm/events.c b/fvwm/events.c
index 1ae159fa..10218213 100644
--- a/fvwm/events.c
+++ b/fvwm/events.c
@@ -1855,12 +1855,7 @@ monitor_emit_broadcast(void)
}
if (m->flags & MONITOR_PRIMARY) {
- struct monitor *pm = m, *mnew;
-
- if ((mnew = monitor_by_last_primary()) == NULL)
- break;
-
- if (pm != mnew) {
+ if (m->flags & MONITOR_PRIMARY && !m->was_primary) {
execute_function_override_window(
NULL, NULL, randrfunc, NULL, 0, NULL);
}
Perhaps. This is already an ugly hack as it is. At least my version mirrors other variables where there's a previous state.