6

I have a display I use for programming in portrait mode. To watch videos, I pivot it to landscape mode multiple times a day. The physical transformation is quick but I have to dig into the monitor configuration each time to adjust the orientation / the resolution. Is there any way to automate this under Linux? The Monitor in question is a BenQ BL2410PT, which has an auto-pivot feature in the software it comes with and I use an AMD graphics card.

I can change the rotation to portrait mode with

$ xrandr --output DVI-1 --rotation left

and back to landscape mode with

$ xrandr --output DVI-1 --rotation normal

so the question boils down to detecting the orientation change of the monitor.

Bengt
  • 741
  • 1
  • 8
  • 15
  • 1
    This question appears to be off-topic because it is about the setup of monitors under Linux. –  Feb 04 '14 at 04:38
  • I was wondering about this and essentially what you are asking is that the computer detects the monitor rotation in the same way that a handheld device detects changes - this is only possible in handheld devices due to the presence of a gyroscope in the device which monitors positional changes. – Adam Apr 11 '17 at 13:12
  • Since you are in GUI mode you could set up a menu button to click which would be faster than the CLI. – Adam Apr 11 '17 at 13:12
  • 3
    @Adam No, there must be a sensor for the pivot orientation in the monitor, since the Windows driver supports changing the resolution and orientation automatically. So what I am looking for is a utility that reads this information from the monitor and triggers the window manager to use the changed resolution. Changing the resolution by hand isn't practical if one pivots ones monitor multiple times a day. – Bengt Apr 18 '17 at 09:59
  • 1
    Tried your link to BenQ but their site didn't bring it up, nor can I find it by searching on BL2410PT, so I can't check what sort of sensor it is. I just bought an LQ monitor and this wasn't something I checked for. Hopefully it has it, it sounds useful (if you can get it to work). – Adam Apr 19 '17 at 09:15

2 Answers2

1

Duck Duck Go and internet archive led me to this hack for ubuntu and Nvidia propriety drivers. Unfortunately, it's a bit old as it has you edit xorg.conf instead of XSession.d files, but given you originally asked on programmers.stackexchange.com I'm hoping you can adapt it:

open xorg.conf and edit the nvidia section that looks like this:

Section “Device”
Identifier “some text about nvidia here”
Driver “nv”

to include Option “Rotate” “CW” (You can also add the option “Rotate” “CCW” for counter-clockwise rotation)

Restart X (Ctrl-Alt-Backspace)

virtualxtc
  • 1,043
  • 16
  • 25
1

As far as I can tell, this is done via DDC/CI. But I don’t think DDC supports any kind of display-initiated events. Which means some software on the PC constantly has to poll the screen to tell that something changed. Which of course cannot be done too quickly or it would start to waste resources.
Benq has a video online, that shows their Auto Pivot feature with Windows, and the quite notable delay seems to suggest this is the case for their Windows drivers.

Of course, on Linux, this is quite trivial to replicate.
All you need is a script that runs in the background, with a loop that polls the DDC value indicating the rotation, and sleeps a bit until the next poll. If it found that the value changed, it would run xrandr to rotate the display. Throw this into your init system of choice, and you’re done. It’s not pretty, because polling never is. (Interrupts would be the correct way to do something like this.) But it works.
As a plus, you can set the polling time, and I made it so that if you need to trigger anything else from this, you can just drop it in the correct directory.

#! /bin/bash
# Some older systems might prefer using “/usr/bin/env bash” above.

# Internals
declare -A values
configDir="$( [[ "$UID" == 0 ]] && echo "/etc/ddc-event/" || echo "$HOME/.config/dde-event" )"
debugMode=true

# (First time, each time) initialization
if [[ ! -e "$configDir/config" ]]; then
  $debugMode && echo "Creating configuration in ”$configDir/config”."
  mkdir -p "$configDir"
  cat > "$configDir/config" <<-EOD
  delay=1 # seconds
  features=( AA ) # Set your VCPs here, separated be a space character. Find them via “ddcutil capabilities”.
  debugMode=true
EOD
fi
. "$configDir/config" # Loads configuration
for feature in ${features[@]}; do
  $debugMode && echo "Creating handler directories for features ( ${features[*]} ) in ”$configDir/”."
  [[ -e "$configDir/$feature" ]] || mkdir -p "$configDir/$feature"
done

# Handler manager
callHandlers() { local feature="$1"; local value="$2";
  for handler in "$configDir/$feature/"*; do
    $debugMode && echo "  Calling handler “$handler” for feature "$feature" with value “$value”."
    "$handler" "$value"
  done
}

# Main script
while true; do
  for feature in ${features[@]}; do
    newValue="$( ddcutil -t getvcp "$feature" | cut -d ' ' -f 4 )"
    if [[ "$newValue" != "${value[$feature]}" ]]; then
      $debugMode && echo "Feature “$feature”: Value “${value[$feature]}” -> “$newValue”."
      value[$feature]="$newValue"
      callHandlers "$feature" "$newValue"
    fi
  done
  sleep "$delay"
done

Save this in e.g. /usr/local/bin/ddc-event, then chmod +x /usr/local/bin/ddc-event. Install ddcutil, so it works. Now run ddc-event via your init system of choice or just via any session autostart of your desktop or .bashrc (in the background with ddc-event &) or whatever.

Next, place the following rotation handler in either $HOME/.config/ddc-event/AA/pivot or /etc/ddc-event/AA/pivot, depending on whether the above daemon runs as your user or as root, and chmod +x it too:

#! /bin/bash

display="DVI-0"

if [[ "$1" == "x01" ]]; then
  xrandr --output "$display" --rotation normal
elif [[ "$1" == "x02" ]]; then
  xrandr --output "$display" --rotation left
fi

If the directory does not exist, you forgot to run the first script first. :)

After that, you can set which features to look for in $HOME/.config/ddc-event/config or /etc/ddc-event/config, again depending on if it runs as root.
I found a delay of 5 seconds (resulting in 2.5s delay on average) to be perfectly fine. Even 10s might be ok, so it will take very little resources.
The features to look for can be found via ddcutil capabilities (The hex values.). ddc-event should automatically create the directories for the features on launch. You can then throw any scripts in there that you like.
You can also set debugMode=true and just run it from the console, to watch the events come in and handlers get executed.
Finally, if you want to stop it, just kill the process. Nothing special about it, unless your handlers are special.

It’s an universal DDC event handler in the classic Unix/Linux style.

I hope this finally solved the problem. :)

Evi1M4chine
  • 636
  • 6
  • 9
  • This is awesome. Thanks for your answer! I don't own this monitor anymore, and my current one does not support pivot. However, this feature makes me want to try a workflow like that again. Very interesting! – Bengt May 18 '23 at 20:14
  • 1
    BTW, here’s a minimized one-liner, that’ll do exactly the same if you just want one rotation step and nothing else: `o=_;while true;do n=$(ddcutil -t getvcp AA|cut -d ' ' -f4);[[ $n != $o ]]&&{ o=$n;xrandr --output DVI-0 --rotation $([[ $n == x02 ]]&&echo left||echo normal);};sleep 5;done` – Evi1M4chine May 19 '23 at 17:26