-
Notifications
You must be signed in to change notification settings - Fork 0
/
switch-screen
executable file
·126 lines (110 loc) · 5.26 KB
/
switch-screen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/bin/bash
# Generic bash options which I always use for safety. Not all may be needed for this particular script.
set -o nounset
set -o pipefail
set -o errexit
set -o errtrace
trap 'echo "Error at line $LINENO, exit code is $?" >&2' ERR
shopt -s nullglob
shopt -s failglob
# CONFIGURATION ################################################################
# WARNING: You currently have to manually set the screen resolution and name
# of the external display (e.g. "VIRTUAL8") in the actual code below!
# See the code of the 'case "$1" in'.
# TODO: Make it auto-detect reasonable settings.
# If you're not using LightDM set this to the location of your display manager's Xauthority file
export XAUTHORITY='/var/run/lightdm/root/:0'
export DISPLAY=':0'
LOCK='/tmp/bumblebee-multiscreen-tools.switch-screen.lock'
################################################################################
print_usage() {
echo "Usage: $0 [external|dual|internal]"
}
if [ $# -ne 1 ]; then
print_usage
exit 1
fi
# Ensure the script cannot run multiple times in parallel.
# Open lock file and assign descriptor to LOCK_DESCRIPTOR
exec {LOCK_DESCRIPTOR}> "$LOCK"
# Since switch-screen spawns a daemon subprocess (intel-virtual-output)
# the file descriptor is inherited by it (can be be prevented, but bash
# doesn't do that) and thus kept open even upon exit of this script.
# This means the lock isn't released by descriptor closure so we need to
# release it manually upon exit.
trap 'flock --unlock "$LOCK_DESCRIPTOR"' EXIT
# Try to acquire the lock
if ! flock -w 60 "$LOCK_DESCRIPTOR" ; then
echo "Another instance is running, waited 60 sec but it didn't quit!" >&2
exit 1
fi
# On certain systems switching the GPU sometimes (very rarely) causes the SATA hard disk to be disconnected.
# To avoid data loss flush the file system buffers.
sync
# Workaround for not finding modprobe command if using this from a LightDM display-setup-script.
if [[ ":$PATH:" != *":/sbin:"* ]]; then
export PATH="/sbin:$PATH"
fi
# TODO: Make README tell user to add it to /etc/modules?
modprobe bbswitch
# TODO: Set niceness of Xorg
case "$1" in
'external')
# Docked mode - External screen only, DisplayPort #2 on dock (not using #1 because using #2 makes zip-tieing the cables easier :)
# Rendered by Intel card, can use NVidia card on demand with optirun/primusrun.
echo ON > /proc/acpi/bbswitch
optirun true
# (Won't start a second one if already running)
intel-virtual-output
# Set "--mode" to the xrandr mode of your external display.
# You can lookup the mode's of your external display on DisplayPort #2 aka "DP-5" aka "VIRTUAL8", by: "xrandr --query"
# For that to work do the above 3 commands manually. Once you know the mode of VIRTUAL8 do "switch-screen internal" to undo this.
# TODO: Using "--mode" is a workaround for "--auto" not working as of 2017-10-27 on Kubuntu 14.04. Try --auto instead of --mode once you're on a newer distribution.
# TODO: "--primary" is an attempted workaround to improve vsync with videos in Chromium as of 2017-10-27 on Kubuntu 14.04. Remove if it doesn't help / vsync improves on a newer distribution.
xrandr --output LVDS1 --off
xrandr --output VIRTUAL8 --mode VIRTUAL8.742-1920x1200 --primary
;;
'dual')
# Docked mode with dualscreen - laptop screen left to DisplayPort #2 screen.
# Rendered by Intel card, can use NVidia card on demand with optirun/primusrun.
echo ON > /proc/acpi/bbswitch
optirun true
intel-virtual-output
# Change "--left-of" / "--right-of" / "--primary" according to your preferences
# Set "--mode" like above.
xrandr --output LVDS1 --left-of VIRTUAL8 --primary --auto
xrandr --output VIRTUAL8 --right-of LVDS1 --mode VIRTUAL8.742-1920x1200
;;
'internal')
# Mobile mode - only the laptop's internal screen.
# Rendered by Intel card, NVidia card is off to reduce power usage.
xrandr --output VIRTUAL8 --off
xrandr --output LVDS1 --auto
echo "Waiting for intel-virtual-output to terminate..."
killall --wait --exact --quiet intel-virtual-output || true
# killall does not support matching processes by their command line arguments so we must use pkill/pgrep
pkill --full 'Xorg(.*):8(.*)' || true
echo "Waiting for Xorg to terminate..."
while [ "$(pgrep --full --count 'Xorg(.*):8(.*)')" != '0' ] ; do
sleep 0.1s
done
# TODO: Make it ignore "rmmod: ERROR: Module nvidia_drm is not currently loaded" and remove the "|| true" to avoid also ignoring the fact that it cannot be unloaded because something is using it.
rmmod nvidia_drm || true
rmmod nvidia_modeset || true
rmmod nvidia_uvm || true
rmmod nvidia || true
echo OFF > /proc/acpi/bbswitch
# This is likely a working workaround for the below "NOTICE:"
echo ON > /proc/acpi/bbswitch
echo OFF > /proc/acpi/bbswitch
# NOTICE: Check kernel log for "Refused to change power state, currently in D0", if that happened then disabling the GPU failed.
# It will probably work if you re-enable it (= docked mode) and try to disable it again.
# The idle power consumption as displayed by "upower --dump" should go down from 25 to 11 watts if the card is off.
;;
# FIXME: Add mode for allowing use of the internal screen with bumblebee. Or put into a separate script, e.g. "nvidia-power [on|off]"
*)
print_usage
exit 1
;;
esac
exit 0