Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle DPI settings #33

Open
blueyed opened this issue May 18, 2015 · 19 comments
Open

Handle DPI settings #33

blueyed opened this issue May 18, 2015 · 19 comments

Comments

@blueyed
Copy link
Contributor

blueyed commented May 18, 2015

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))

@phillipberndt
Copy link
Owner

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
Copy link
Owner

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?!

@blueyed
Copy link
Contributor Author

blueyed commented May 18, 2015

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).

@phillipberndt
Copy link
Owner

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?!

@blueyed
Copy link
Contributor Author

blueyed commented May 18, 2015

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.

@phillipberndt
Copy link
Owner

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

@blueyed
Copy link
Contributor Author

blueyed commented May 18, 2015

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

👍

@rriemann
Copy link

rriemann commented Jun 4, 2015

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

@Vladimir-csp
Copy link
Contributor

Vladimir-csp commented Apr 9, 2018

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
Copy link
Contributor

Vladimir-csp commented Apr 9, 2018

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

@phillipberndt
Copy link
Owner

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?

@Mange
Copy link

Mange commented Sep 19, 2018

What would it entail to implement it?

@phillipberndt
Copy link
Owner

phillipberndt commented Sep 20, 2018

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.

@Mange
Copy link

Mange commented Oct 2, 2018

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

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. 🙇‍♂️)

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?

phillipberndt added a commit that referenced this issue Oct 3, 2018
This is an attempt to piggy-back fb and dpi onto the first used output.
Not certain whether this has catastrophic drawbacks yet. In any case,
the dpi information should probably be obtained from the outputs, as
those already have all the necessary information, rather than by parsing
the xrandr output a second time. Maybe it'd be an even better idea to go
with --fbmm instead of dpi.

See #33
@phillipberndt
Copy link
Owner

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.

@Vladimir-csp
Copy link
Contributor

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

@RidaAyed
Copy link

RidaAyed commented Apr 9, 2019

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)?

@MikaelElkiaer
Copy link

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..

@Mange
Copy link

Mange commented Jan 4, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants