mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-23 15:33:13 +00:00
Merge pull request #15353 (improve xrandrHeads)
When you have a setup consisting of multiple monitors, the default is that the first monitor detected by xrandr is set to the primary monitor. However this may not be the monitor you need to be set as primary. In fact this monitor set to primary may in fact be disconnected. This has happened for the original submitter of the pull request and it affected these programs: * XMonad: Gets confused with Super + {w,e,r} * SDDM: Puts the login screen on the wrong monitor, and does not currently duplicate the login screen on all monitors * XMobar: Puts the XMobar on the wrong monitor, as it only puts the taskbar on the primary monitor These changes should fix that not only by setting a primary monitor in xrandrHeads but also make it possible to make a different monitor the primary one. The changes are also backwards-compatible.
This commit is contained in:
commit
9dca737d62
@ -17,7 +17,29 @@ has the following highlights: </para>
|
||||
A consequence is that UIDs and GIDs are no longer reused.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
The module option <option>services.xserver.xrandrHeads</option> now
|
||||
causes the first head specified in this list to be set as the primary
|
||||
head. Apart from that, it's now possible to also set additional options
|
||||
by using an attribute set, for example:
|
||||
<programlisting>
|
||||
{ services.xserver.xrandrHeads = [
|
||||
"HDMI-0"
|
||||
{
|
||||
output = "DVI-0";
|
||||
primary = true;
|
||||
monitorConfig = ''
|
||||
Option "Rotate" "right"
|
||||
'';
|
||||
}
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
This will set the <literal>DVI-0</literal> output to be the primary head,
|
||||
even though <literal>HDMI-0</literal> is the first head in the list.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>The following new services were added since the last release:</para>
|
||||
|
@ -31,18 +31,51 @@ let
|
||||
pkgs.xorg.fontadobe75dpi
|
||||
];
|
||||
|
||||
xrandrOptions = {
|
||||
output = mkOption {
|
||||
type = types.str;
|
||||
example = "DVI-0";
|
||||
description = ''
|
||||
The output name of the monitor, as shown by <citerefentry>
|
||||
<refentrytitle>xrandr</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry> invoked without arguments.
|
||||
'';
|
||||
};
|
||||
|
||||
primary = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether this head is treated as the primary monitor,
|
||||
'';
|
||||
};
|
||||
|
||||
monitorConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
DisplaySize 408 306
|
||||
Option "DPMS" "false"
|
||||
'';
|
||||
description = ''
|
||||
Extra lines to append to the <literal>Monitor</literal> section
|
||||
verbatim.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Just enumerate all heads without discarding XRandR output information.
|
||||
xrandrHeads = let
|
||||
mkHead = num: output: {
|
||||
mkHead = num: config: {
|
||||
name = "multihead${toString num}";
|
||||
inherit output;
|
||||
inherit config;
|
||||
};
|
||||
in imap mkHead cfg.xrandrHeads;
|
||||
|
||||
xrandrDeviceSection = let
|
||||
monitors = flip map xrandrHeads (h: ''
|
||||
Option "monitor-${h.output}" "${h.name}"
|
||||
Option "monitor-${h.config.output}" "${h.name}"
|
||||
'');
|
||||
# First option is indented through the space in the config but any
|
||||
# subsequent options aren't so we need to apply indentation to
|
||||
@ -62,9 +95,13 @@ let
|
||||
value = ''
|
||||
Section "Monitor"
|
||||
Identifier "${current.name}"
|
||||
${optionalString (current.config.primary) ''
|
||||
Option "Primary" "true"
|
||||
''}
|
||||
${optionalString (previous != []) ''
|
||||
Option "RightOf" "${(head previous).name}"
|
||||
''}
|
||||
${current.config.monitorConfig}
|
||||
EndSection
|
||||
'';
|
||||
} ++ previous;
|
||||
@ -329,13 +366,39 @@ in
|
||||
|
||||
xrandrHeads = mkOption {
|
||||
default = [];
|
||||
example = [ "HDMI-0" "DVI-0" ];
|
||||
type = with types; listOf string;
|
||||
example = [
|
||||
"HDMI-0"
|
||||
{ output = "DVI-0"; primary = true; }
|
||||
{ output = "DVI-1"; monitorConfig = "Option \"Rotate\" \"left\""; }
|
||||
];
|
||||
type = with types; listOf (coercedTo str (output: {
|
||||
inherit output;
|
||||
}) (submodule { options = xrandrOptions; }));
|
||||
# Set primary to true for the first head if no other has been set
|
||||
# primary already.
|
||||
apply = heads: let
|
||||
hasPrimary = any (x: x.primary) heads;
|
||||
firstPrimary = head heads // { primary = true; };
|
||||
newHeads = singleton firstPrimary ++ tail heads;
|
||||
in if heads != [] && !hasPrimary then newHeads else heads;
|
||||
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
|
||||
Multiple monitor configuration, just specify a list of XRandR
|
||||
outputs. The individual elements should be either simple strings or
|
||||
an attribute set of output options.
|
||||
|
||||
If the element is a string, it is denoting the physical output for a
|
||||
monitor, if it's an attribute set, you must at least provide the
|
||||
<option>output</option> option.
|
||||
|
||||
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 if
|
||||
none of the elements contain an option that has set
|
||||
<option>primary</option> to <literal>true</literal>.
|
||||
|
||||
<note><para>Only one monitor is allowed to be primary.</para></note>
|
||||
|
||||
Be careful using this option with multiple graphic adapters or with
|
||||
drivers that have poor support for XRandR, unexpected things might
|
||||
happen with those.
|
||||
@ -469,11 +532,18 @@ in
|
||||
|
||||
nixpkgs.config.xorg = optionalAttrs (elem "vboxvideo" cfg.videoDrivers) { abiCompat = "1.18"; };
|
||||
|
||||
assertions =
|
||||
[ { assertion = config.security.polkit.enable;
|
||||
message = "X11 requires Polkit to be enabled (‘security.polkit.enable = true’).";
|
||||
}
|
||||
];
|
||||
assertions = [
|
||||
{ assertion = config.security.polkit.enable;
|
||||
message = "X11 requires Polkit to be enabled (‘security.polkit.enable = true’).";
|
||||
}
|
||||
(let primaryHeads = filter (x: x.primary) cfg.xrandrHeads; in {
|
||||
assertion = length primaryHeads < 2;
|
||||
message = "Only one head is allowed to be primary in "
|
||||
+ "‘services.xserver.xrandrHeads’, but there are "
|
||||
+ "${toString (length primaryHeads)} heads set to primary: "
|
||||
+ concatMapStringsSep ", " (x: x.output) primaryHeads;
|
||||
})
|
||||
];
|
||||
|
||||
environment.etc =
|
||||
(optionals cfg.exportConfiguration
|
||||
|
Loading…
Reference in New Issue
Block a user