Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have the following files in /etc/acpi/events and /etc/udev/rules.d

/etc/acpi/events/lidclose

# Pass all events to our one handler script
event=button/lid
action=/etc/acpi/monitors.sh

/etc/udev/rules.d/80-monitor.rules

# change monitor settings when monitor is plugged in or o$
ACTION=="change", SUBSYSTEM=="drm", HOTPLUG=="1", RUN+="/etc/acpi/monitors.sh"

Now, the (executable and owned by root) /etc/acpi/monitors.sh

#!/bin/sh

# default monitor is LVDS1
STATE=internal
INTERNAL=LVDS1
EXTERNAL=HDMI3

# functions to switch from LVDS1 to VGA and vice versa
function internal {
    echo "Switching to internal"
    xrandr --output $EXTERNAL --off --output $INTERNAL --auto
    STATE=internal
}
function external {
    echo "Switching to external"
    xrandr --output $EXTERNAL --auto --output $INTERNAL --off
    STATE=external
}
function both {
    echo "Switching to both"
    xrandr --output $EXTERNAL --auto --right-of $INTERNAL --output $INTERNAL --auto --primary
    STATE=both
}

# functions to check if VGA is connected and in use
function externalConnected {
    ! xrandr | grep "^$EXTERNAL" | grep disconnected >/dev/null
}
function lidOpen {
    ! cat /proc/acpi/button/lid/LID/state | grep closed >/dev/null
}

# actual script
if ! [ $STATE == "both" ] && externalConnected && lidOpen
then
    both
fi

if ! [ $STATE == "external" ] && externalConnected && ! lidOpen
then
    external
fi

if ! [ $STATE == "internal" ] && ! externalConnected && lidOpen
then
    internal
fi

Now, I tested the script both as root and as my user, and it worked like a charm. I also put some test output via "echo bla > /home/me/test" in it, and when called by udev and acpid it generated the output, so it is executed. The only thing is, that nothing happens with xrandr. What am I missing? How could I log the output of the script to find errors?

share|improve this question
    
The core issue is discussed in Can I launch a graphical program on another user's desktop as root? –  Gilles May 29 '11 at 21:15
add comment

1 Answer

up vote 4 down vote accepted

With the help of the guys who commented on my question, I figured out what was wrong and fixed it in the script.

Here now the updated routines how to get automatic screen switching with your laptop to work. You need acpid, kms and udev.

Create the following rules for acpi and udev

/etc/acpi/events/lidclose

# Pass all events to our one handler script
event=button/lid
action=/etc/acpi/monitors.sh

/etc/udev/rules.d/80-monitor.rules

# change monitor settings when monitor is plugged in or o$
ACTION=="change", SUBSYSTEM=="drm", HOTPLUG=="1", RUN+="/etc/acpi/monitors.sh"

now create /etc/acpi/monitors.sh

#!/bin/sh

# specify the monitors to use
INTERNAL=LVDS1
EXTERNAL=HDMI3
USERNAME=oli

# set some variables needed to control the x server
export XAUTHORITY=/home/$USERNAME/.Xauthority
export DISPLAY=:0

# functions to switch from internal screen to external screen and vice versa or to use both screens together
function internal {
    echo "Switching to internal" >> /var/log/monitors.log
    xrandr --verbose --output $EXTERNAL --off --output $INTERNAL --auto >> /var/log/monitors.log 2>&1
}
function external {
    echo "Switching to external" >> /var/log/monitors.log
    xrandr --verbose --output $EXTERNAL --auto --output $INTERNAL --off >> /var/log/monitors.log 2>&1
}
function both {
    echo "Switching to both" >> /var/log/monitors.log
    xrandr --verbose --output $EXTERNAL --auto --right-of $INTERNAL --output $INTERNAL --auto --primary >> /var/log/monitors.log 2>&1
}

# functions to check if external monitor is connected and in use
function externalConnected {
    ! xrandr | grep "^$EXTERNAL" | grep disconnected >/dev/null
}
function lidOpen {
    ! cat /proc/acpi/button/lid/LID/state | grep closed >/dev/null
}

# actual script
if externalConnected && lidOpen
then
    both
fi

if externalConnected && ! lidOpen
then
    external
fi

if ! externalConnected && lidOpen
then
    internal
fi

And hopefully it'll work.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.