Switching display/monitor/screen in Linux
Because I am using the Openbox (window manager), and I believe that the laptop Fn+F8 (or whatever combination with Fn) doesn’t work properly on Linux. Because the combination is detected as Super+p (aka Win+p). As a result, I wrote a Perl script to solve the switching display/monitor/screen issue on my laptop.
[code language=“perl”] #!/usr/bin/perl
# This script requires xrandr, and several bash script created by arandr
use strict; use warnings;
# Edit these global variables based on your setting my $primary = ’eDP1’; my $secondary = ‘HDMI1’;
my %scripts = (default => ‘default.sh’, external_only => ’large_only.sh’, clone => ‘clone.sh’, dual => ‘dual.sh’); my $script_path = ‘~/.screenlayout’; # End edit
sub get_xrandr { return `xrandr`; }
sub is_active { my ($monitor) = @_; for my $i (0 .. (scalar @$monitor - 1)) { my $line = $monitor->[$i]; if ($line =~ /\*/) { return 1; } } return 0; }
sub is_left { my ($monitor) = @_; my $line = $monitor->[0]; if ($line =~ /\d+x\d+\+(\d+)\+\d+/) { if ($1 > 0) { return 0; } } return 1; }
sub is_default { my ($primary, $secondary) = @_; return &is_active($primary) && !&is_active($secondary); }
sub is_external_only { my ($primary, $secondary) = @_; return !&is_active($primary) && &is_active($secondary); }
sub is_clone { my ($primary, $secondary) = @_; return &is_active($primary) && &is_active($secondary) && &is_left($primary) && &is_left($secondary);; }
sub is_dual { my ($primary, $secondary) = @_; return &is_active($primary) && &is_active($secondary) && &is_left($primary) && !&is_left($secondary);; }
sub get_monitor_style { my ($primary, $secondary) = &get_monitor_details; if (&is_default($primary, $secondary)) { return ‘default’; } elsif (&is_clone($primary, $secondary)) { return ‘clone’; } elsif (&is_dual($primary, $secondary)) { return ‘dual’; } elsif (&is_external_only($primary, $secondary)) { return ’external_only’; } return ‘unknown’; }
sub set_monitor_style { my ($style) = @_; my $script = join(’/’, $script_path, $scripts{$style}); my $cmd = “sh $script”; `$cmd`; }
sub switch_next_monitor_style { my $current_style = &get_monitor_style; if ($current_style eq ‘default’) { &set_monitor_style(’external_only’); } elsif ($current_style eq ’external_only’) { &set_monitor_style(‘dual’); } elsif ($current_style eq ‘dual’) { &set_monitor_style(‘clone’); } elsif ($current_style eq ‘clone’) { &set_monitor_style(‘default’); } else { print STDERR “Unknown monitor style”; } }
sub switch_prev_monitor_style { my $current_style = &get_monitor_style; if ($current_style eq ‘default’) { &set_monitor_style(‘clone’); } elsif ($current_style eq ’external_only’) { &set_monitor_style(‘default’); } elsif ($current_style eq ‘dual’) { &set_monitor_style(’external_only’); } elsif ($current_style eq ‘clone’) { &set_monitor_style(‘dual’); } else { print STDERR “Unknown monitor style”; } }
sub switch_monitor_style { my ($prev) = @_; if ($prev) { &switch_prev_monitor_style; } else { &switch_next_monitor_style; } }
sub get_monitor_details { my $xrandr = &get_xrandr; my @lines = split(/\n/, $xrandr);
my @primary_lines; my @secondary_lines; my $current_block; for my $i (0 .. $#lines) { my $line = $lines[$i]; if ($i == 0) { next; # not “continue” } if ($line =~ /^${primary}/) { $current_block = ‘primary’; } elsif ($line =~ /^${secondary}/) { $current_block = ‘secondary’; } if ($current_block eq ‘primary’) { push @primary_lines, $line; } elsif ($current_block eq ‘secondary’) { push @secondary_lines, $line; } } return (\@primary_lines, \@secondary_lines); }
sub main { my ($prev) = @_; &switch_monitor_style($prev); }
&main(@ARGV); [/code]
The script requires “xrandr” command. Furthermore, you need to have some actual switching monitor bash script, which can be created by using ARandR. Example of the script
[code language=“bash”] #!/bin/sh xrandr –output HDMI1 –primary –mode 1920x1080 –pos 0x0 –rotate normal –output VIRTUAL1 –off –output eDP1 –off [/code]
So, my Perl script will detect existing screen setup, whether it is laptop only (“default”), external only (“external_only”), laptop with external monitor at the right side (“dual”), or clone (“clone”) for both monitor sharing same screen. Therefore, we need to create four bash scripts using ARandR for these settings.
To invoke the script,
[code language=“bash”] perl /path/to/monitor_switch.pl [/code]
This will switch to the screen to the “next” setting, in this order: default -> external_only -> dual -> clone -> default.
In order to switch between default and external_only, I extended the script with an argument.
[code language=“bash”] perl /path/to/monitor_switch.pl prev [/code]
When passing with an argument (any argument), the monitor setup will switch in the reverse order: default -> clone -> dual -> external_only -> default. By this, we can switch between default and external_only easily.
Next, just apply the keybinding (aka hotkey or shortcut) to your preferred combination, then you can switch the screen with your favourite key combination.
Yeay!
P/S: The reason I wrote this script is, when I show my screen on external only, and the power is cut, the screen doesn’t switch to laptop automatically. That means, I cannot see anything to change my screen display. Before the script is written, I blindly use the Terminal, Ctrl+R, and type the keyword and press Enter to switch back. But this is extreemly impractical.