From bb6a5b079fe8c88a6e42c92179711b2d0a9a9842 Mon Sep 17 00:00:00 2001 From: Roger Qiu Date: Tue, 15 Mar 2016 00:00:55 +1100 Subject: [PATCH] nixos/xserver: Changed xrandrHeads to support corresponding monitor section configuration in Xorg --- nixos/doc/manual/release-notes/rl-1709.xml | 11 ++++- nixos/modules/services/x11/xserver.nix | 57 ++++++++++++++++++---- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-1709.xml b/nixos/doc/manual/release-notes/rl-1709.xml index 5fba4c34ec82..46469a4da782 100644 --- a/nixos/doc/manual/release-notes/rl-1709.xml +++ b/nixos/doc/manual/release-notes/rl-1709.xml @@ -17,7 +17,16 @@ has the following highlights: A consequence is that UIDs and GIDs are no longer reused. - + + + Xserver services module now allows one to specify configuration for each monitor. + This is done via the xrandrHeads property. It is backwards compatible, so your + existing configuration still works. You can replace each monitor designation with + an attribute set containing the monitor designation, whether the monitor is the + primary monitor, and extra configuration for that specific monitor. Only one + monitor can be the primary monitor. + + The following new services were added since the last release: diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 8438e6dcc702..b5fece488205 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -33,12 +33,30 @@ let # Just enumerate all heads without discarding XRandR output information. - xrandrHeads = let - mkHead = num: output: { - name = "multihead${toString num}"; - inherit output; - }; - in imap mkHead cfg.xrandrHeads; + xrandrHeads = ( + fold + (nextHead: { index, alreadyPrimary, processedHeads }: + let + processedHead = { name = "multihead${toString index}"; } // + (if isAttrs nextHead then + { + output = nextHead.output; + primary = if alreadyPrimary then false else nextHead.primary || index == 0; + monitorConfig = nextHead.monitorConfig; + } + else + { + output = nextHead; + primary = if alreadyPrimary then false else index == 0; + monitorConfig = ""; + } + ); + primariness = if alreadyPrimary then true else processedHead.primary; + in + { index = index - 1; alreadyPrimary = primariness; processedHeads = ([ processedHead ] ++ processedHeads); }) + { index = (length cfg.xrandrHeads) - 1; alreadyPrimary = false; processedHeads = []; } + cfg.xrandrHeads + ).processedHeads; xrandrDeviceSection = let monitors = flip map xrandrHeads (h: '' @@ -62,9 +80,13 @@ let value = '' Section "Monitor" Identifier "${current.name}" + ${optionalString (current.primary) '' + Option "Primary" "true" + ''} ${optionalString (previous != []) '' Option "RightOf" "${(head previous).name}" ''} + ${current.monitorConfig} EndSection ''; } ++ previous; @@ -329,12 +351,27 @@ in xrandrHeads = mkOption { default = []; - example = [ "HDMI-0" "DVI-0" ]; - type = with types; listOf string; + example = [ "HDMI-0" { output = "DVI-0"; primary = true; monitorConfig = ""; } ]; + type = with types; listOf (either + str + (submodule { + options.output = str; + options.primary = bool; + options.monitorConfig = lines; + }) + ); description = '' Simple multiple monitor configuration, just specify a list of XRandR - outputs which will be mapped from left to right in the order of the - list. + outputs as the values of the list. The monitors will be mapped from + left to right in the order of the list. + + By default, the first monitor will be set as the primary monitor. + However instead of a list, you can give an attribute set. That set + can contain a primary monitor specification and a custom monitor + configuration section. + + Only one monitor is allowed to be primary. If multiple monitors are + specified as primary, only the last monitor will be primary. Be careful using this option with multiple graphic adapters or with drivers that have poor support for XRandR, unexpected things might