autorandr icon indicating copy to clipboard operation
autorandr copied to clipboard

Handle DPI settings

Open blueyed opened this issue 9 years ago • 19 comments

I'd like to (re)store any DPI settings, which I currently set via xrandr --dpi 120.

This results in these changes in the output from xdpyinfo (from 96 to 120):

<   dimensions:    1366x768 pixels (361x203 millimeters)
<   resolution:    96x96 dots per inch

---
>   dimensions:    1366x768 pixels (289x162 millimeters)
>   resolution:    120x120 dots per inch

This does not appear to be reflected in the output of xrandr -q --verbose.

I am using xsettings now (instead of gnome-settings-daemon), and a script to automatically set it there via xdpyinfo (source).

However, xdpyinfo for my laptop display (Lenovo X220t) is not correct, and therefore I set it manually.

It would be nice if this could be set per display, but apparently it's per X display (screen).

(The real DPI is 125, but I've read that you should stick to certain factors from the default of 96 (a factor of 1.25 in this case))

blueyed avatar May 18 '15 04:05 blueyed

This does not appear to be reflected in the output of xrandr -q --verbose.

Couldn't we extract this from the first line (it states effective resolution and physical device size in mm) of each output?

phillipberndt avatar May 18 '15 06:05 phillipberndt

I just tried. No, that doesn't work, and that it doesn't makes a lot of sense, too, now that I've come to think about it.. What xrandr displays is per-output DPI only, which can be different from the screen's DPI and also isn't alterable (the physical screen size is hard-coded in the EDID, bytes 21 & 22). What --dpi alters, on the other hand, is the screen's DPI, which corresponds to the FB resolution (first line in xrandr's output)

I don't think that including a call to xdpyinfo in autorandr is a good idea. For one, that would be an external dependency. For the other, it currently doesn't fiddle with the FB size at all (but lets xrandr decide how to set it), but once we'd set --dpi, we'd need to set --fb as well, and I don't know what sorts of regression that might create.

What we could do, if you need this, is to integrate a plugin structure that would enable you to do this without maintaining your own fork - I'm thinking of something simple like importing all modules from a plugin directory and calling well-named hooks from those plugins at detection and application time, probably with a mechanism to store custom settings?!

phillipberndt avatar May 18 '15 09:05 phillipberndt

A plugin structure would be nice, but a more simple approach is probably just looking at autorandr's output, and then call by xsettings-setup manually.

I can use just autorandr and look for "(detected)", right? (It would not change the current setup)

But then again (and for other use cases), it would be useful to have information about if the detected setup is already applied, without calling "autorandr -c", which would apply the changes.

In the end, I think two lines should be added to the output: "detected: X" and "current: X" (or something similar).

Currently I could just use -c and then grep for the (detected) line, especially since I will likely move calling autorandr to a custom script anyway. "Config already loaded" could then be used there to not apply any changes (again).

blueyed avatar May 18 '15 13:05 blueyed

If you're fine with configuring this manually, then you can also place a script called postswitch in your profile's directory. It is executed after applying a profile, and only then.

Changing autorandr's default output is a good idea. The current output comes from the legacy bash version (not quite, it exits after it has found the "detected" configuration), and I always thought that it is quite useless in its current form, too. For increased backwards compatibility, we could keep it in its current form, but just replace "(detected)" with "(current)" for the currently loaded configuration?!

phillipberndt avatar May 18 '15 13:05 phillipberndt

Oh yeah, postswitch is useful in this case - had forgotten about it.

Re backwards compatibility: a change from "(detected)" to "(current)" would then also be not backwards compatible.

I think this issue can be closed for now - there's no need to change anything currently.

blueyed avatar May 18 '15 13:05 blueyed

Re backwards compatibility: a change from "(detected)" to "(current)" would then also be not backwards compatible.

Right. But it'd require less changes in existing scripts. (Maybe I'll change this.. if anyone complains this could always be reverted.)

I think this issue can be closed for now - there's no need to change anything currently.

Ok

phillipberndt avatar May 18 '15 13:05 phillipberndt

But it'd require less changes in existing scripts. (Maybe I'll change this.. if anyone complains this could always be reverted.)

:+1:

blueyed avatar May 18 '15 14:05 blueyed

@blueyed Would you please share your final solutions? I have an internal and external display that differ a lot in dpi.

rriemann avatar Jun 04 '15 16:06 rriemann

A couple of thoughts on DPI from my experience First, in X there is no such thing as per-display DPI from practical standpoint. You have to choose some global value that suits you. Second, xdpyinfo is a sufficiently reliable source of the current DPI. It is directly affected by xrandr's --dpi parameter and can be used as the base for further manipulations. Said manipulations would include exporting that value to xrdb and fontconfig. With DPI value correctly set in these three places, majority of applications are affected.

Vladimir-csp avatar Apr 09 '18 09:04 Vladimir-csp

I've ported the example DPI hook from my rerandr3 to autorandr scripts:

postsave: saves current DPI value to "${AUTORANDR_PROFILE_FOLDER}/dpi"

#!/bin/sh
DPI="$(xdpyinfo | grep 'resolution:' | grep -o '[0-9]\+x[0-9]\+' | head -n 1 | cut -d 'x' -f 1)"
[ -n "$DPI" ] && echo "$DPI" > "${AUTORANDR_PROFILE_FOLDER}/dpi"

postswitch: expects DPI value in "${AUTORANDR_PROFILE_FOLDER}/dpi", falls back to calculated DPI of primary monitor, then falls back to default 96.

#!/bin/sh

DEFAULT_DPI=96

## try DPI from profile
printf "%s\n" "Trying to get DPI from \"${AUTORANDR_PROFILE_FOLDER}/dpi\""
DPI="$(cat "${AUTORANDR_PROFILE_FOLDER}/dpi" 2>/dev/null | head -n 1 | grep -o '[0-9]\+')"

## try dpi from primary monitor
if [ -z "$DPI" ]
then
     printf "%s\n%s\n" "No DPI value in profile \"$AUTORANDR_CURRENT_PROFILE\"" "Trying to calculate from primary monitor"
     DPX="$(xrandr -q | grep ' primary ' | grep -o ' [0-9]\+x' | grep -o '[0-9]\+')"
     DMM="$(xrandr -q | grep ' primary ' | grep -o ') [0-9]\+mm' | grep -o '[0-9]\+')"

     if [ -n "$DPX" -a -n "$DMM" ]
     then
          DPI="$(python -c "print( int( $DPX / ( $DMM * 0.039370079 ) ) )" )"
     fi
fi

if [ -z "$DPI" ]
then
     printf "%s\n%s\n" "Could not calculate DPI of primary monitor" "Using default"
     DPI=$DEFAULT_DPI
fi

printf "%s\n" "Resulting DPI: $DPI"

## apply DPI to xrandr
xrandr --dpi "$DPI"


## sync dpi to xrdb
printf "%s\n" "Xft.dpi: $DPI" | xrdb -merge

## sync dpi to fontconfig
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/fontconfig/conf.d"
cat > "${XDG_CONFIG_HOME:-$HOME/.config}/fontconfig/conf.d/90-xrandr-sync-dpi.conf" << EOF
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- Generated by autorandr postswitch script, do not edit. -->
<fontconfig>
  <match target="pattern">
    <edit name="dpi" mode="assign"><double>$DPI</double></edit>
  </match>
</fontconfig>
EOF

Vladimir-csp avatar Apr 09 '18 13:04 Vladimir-csp

Turns out that adding --fb to autorandr is a brilliant idea, I hadn't considered the side effect @Vladimir-csp mentioned in #88. Gives a much smoother user experience on my notebook at least. So let's reconsider adding native DPI support: Anyone willing to implement this?

phillipberndt avatar Apr 15 '18 16:04 phillipberndt

What would it entail to implement it?

Mange avatar Sep 19 '18 08:09 Mange

Using Vladimir's script as a template extract the DPI while storing a profile (using xdpyinfo and the falllback if it's not installed), store it in config files a dpi xyz, (probably extend autorandr to be able to handle such non-output related options at all, IIRC it currently matches everything to an output), and finally extend apply_configuration to set it.

It might actually be a good idea to just store the --fb value to the configuration in general, and only use the calculation function if the key is not present in the configuration.

phillipberndt avatar Sep 20 '18 20:09 phillipberndt

I had a look, but I'm not up to the task. :disappointed:

I'm not a Python developer, but I thought I could find a test and adjust it and then just figure out the code as I went. I wasn't aware that all the code is in a single file without no tests, so I'm just too scared to try it. I also cannot tell where in the code the config file is parsed either.

(Not saying it's bad or anything, just that I personally don't want to go in there and muck around without better understanding of Python. :bowing_man:)

I think that if someone could add support for non-output specific options (like dpi and fb), then a lot of setups could be supported even if detection cannot happen automatically. Maybe that's a simpler goal for someone to take a look at?

Mange avatar Oct 02 '18 20:10 Mange

Pushed a work in progress version with an early attempt to toy around with this to the dpi branch. I don't bother much with obtaining dpi information from the external tool yet, it's mainly an attempt to play around with piggy-backing the options onto the first output. Feedback appreciated.

phillipberndt avatar Oct 03 '18 17:10 phillipberndt

I've tested dpi branch. It seems to get primary output native dpi correctly, save it and apply on restore to xrandr.

Vladimir-csp avatar Oct 04 '18 16:10 Vladimir-csp

Pushed a work in progress version with an early attempt to toy around with this to the dpi branch. I don't bother much with obtaining dpi information from the external tool yet, it's mainly an attempt to play around with piggy-backing the options onto the first output. Feedback appreciated.

Very nice project, thank you. How is DPI handled in the current release (AUR)?

RidaAyed avatar Apr 09 '19 20:04 RidaAyed

How does all of this relate to multihead (multiple monitors) with different resolutions/DPIs?

I have a laptop (3840x2160) and an ultrawide (3440x1440). I've had to settle with running my laptop at 2560x1440 and ultrawide at 3440x1440, with a DPI of 96. This keeps my laptop at reasonable size, but my ultrawide is actually a bit too big. However, I'd prefer to run both at full resolution, but a DPI of 144 for the laptop and 72 for the ultrawide..

MikaelElkiaer avatar Jan 04 '20 13:01 MikaelElkiaer

Sadly X11 only supports a single global DPI. You'll need Wayland for Display-specific DPI settings.

Mange avatar Jan 04 '20 15:01 Mange