Repository: lutris/lutris

Issue:
Add DPI manager to the Wine Runner
By default, Wine uses DPI of 96, which makes all GUI programs look incredibly small on a 4K screen, even when scaling is enabled in the DE.
While the user may choose to change the DPI themselves in Wine Configuration to remedy that, automating this in Lutris should be relatively easy.
Lutris simply needs to get DPI data from somewhere (at least on X11, this can be done with `xrdb -query | grep dpi`), convert it to hex (192 DPI, 2x scaling on a 4K screen, is `000000c0`, while default, 96 DPI, is `00000060`), and specify it in Wine's registry by setting `"LogPixels"` DWORD variables located in `[Software\\Wine\\Fonts]` and `[Control Panel\\Desktop]` to the according value in the format of `"LogPixels"=dword:000000c0`.
For example:
```
[Control Panel\\Desktop]
"LogPixels"=dword:000000c0
```
```
[Software\\Wine\\Fonts]
"LogPixels"=dword:000000c0
```
Specifying these will set DPI to 192.


Discussion:
Does this oneline script work
`wine reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v LogPixels /t REG_DWORD /d 0x60 /f`
or maybe suggestion on changing the value for 192 dpi screens?

i saw [here](https://forum.winehq.org/viewtopic.php?t=34980) a guy used a simple bash script to revert back to the old dpi for users that may want to keep it that way..
```
#!/bin/bash

WINEPREFIX="/opt/Wine64"
NEWDPI="0x90"
OLDDPI=$( wine reg query "HKEY_CURRENT_USER\Control Panel\Desktop" | grep "LogPixels" | awk ' {print $3} ' | sed 's/\r$//' )

if [ "${OLDDPI}" != "${NEWDPI}" ]; then
  wine reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v LogPixels /t REG_DWORD /d ${NEWDPI} /f
fi

wine "plsqldev.exe"

if [ "${OLDDPI}" != "${NEWDPI}" ] && [ ! -z "${OLDDPI}" ]; then
  wine reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v LogPixels /t REG_DWORD /d ${OLDDPI} /f
fi
```
Maybe someone will find it helpful 

Resolving patch:
diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py
--- a/lutris/runners/wine.py
+++ b/lutris/runners/wine.py
@@ -12,7 +12,7 @@
 )
 from lutris.runners.runner import Runner
 from lutris.util import system
-from lutris.util.display import DISPLAY_MANAGER
+from lutris.util.display import DISPLAY_MANAGER, get_default_dpi
 from lutris.util.graphics.vkquery import is_vulkan_supported
 from lutris.util.jobs import thread_safe_call
 from lutris.util.log import logger
@@ -357,6 +357,26 @@ def dxvk_vulkan_callback(widget, option, config):
                 "choices": DISPLAY_MANAGER.get_resolutions,
                 "help": _("The size of the virtual desktop in pixels."),
             },
+            {
+                "option": "Dpi",
+                "label": _("Enable DPI Scaling"),
+                "type": "bool",
+                "default": False,
+                "help": _(
+                    "Enables the Windows application's DPI scaling.\n"
+                    "Otherwise, disables DPI scaling by using 96 DPI.\n"
+                    "This corresponds to Wine's Screen Resolution option."
+                ),
+            },
+            {
+                "option": "ExplicitDpi",
+                "label": _("DPI"),
+                "type": "string",
+                "help": _(
+                    "The DPI to be used if 'Enable DPI Scaling' is turned on.\n"
+                    "If blank or 'auto', Lutris will auto-detect this."
+                ),
+            },
             {
                 "option": "MouseWarpOverride",
                 "label": _("Mouse Warp Override"),
@@ -632,6 +652,7 @@ def run_wineexec(self, *args):
 
     def run_wineconsole(self, *args):
         """Runs wineconsole inside wine prefix."""
+        self.prelaunch()
         self._run_executable("wineconsole")
 
     def run_winecfg(self, *args):
@@ -710,6 +731,25 @@ def set_regedit_keys(self):
 
                 prefix_manager.set_registry_key(path, key, value)
 
+        # We always configure the DPI, because if the user turns off DPI scaling, but it
+        # had been on the only way to implement that is to save 96 DPI into the registry.
+        prefix_manager.set_dpi(self.get_dpi())
+
+    def get_dpi(self):
+        """Return the DPI to be used by Wine; returns 96 to disable scaling,
+        as this is Window's unscaled default DPI."""
+        if bool(self.runner_config.get("Dpi")):
+            explicit_dpi = self.runner_config.get("ExplicitDpi")
+            if explicit_dpi == "auto":
+                explicit_dpi = None
+            try:
+                explicit_dpi = int(explicit_dpi)
+            except ValueError:
+                explicit_dpi = None
+            return explicit_dpi or get_default_dpi()
+
+        return 96
+
     def setup_dlls(self, manager_class, enable, version):
         """Enable or disable DLLs"""
         dll_manager = manager_class(
diff --git a/lutris/util/display.py b/lutris/util/display.py
--- a/lutris/util/display.py
+++ b/lutris/util/display.py
@@ -26,6 +26,16 @@ class NoScreenDetected(Exception):
     """Raise this when unable to detect screens"""
 
 
+def get_default_dpi():
+    """Computes the DPI to use for the primary monitor
+    which we pass to WINE."""
+    display = Gdk.Display.get_default()
+    monitor = display.get_primary_monitor()
+    scale = monitor.get_scale_factor()
+    dpi = 96 * scale
+    return int(dpi)
+
+
 def restore_gamma():
     """Restores gamma to a normal level."""
     xgamma_path = system.find_executable("xgamma")
diff --git a/lutris/util/wine/prefix.py b/lutris/util/wine/prefix.py
--- a/lutris/util/wine/prefix.py
+++ b/lutris/util/wine/prefix.py
@@ -207,6 +207,11 @@ def set_desktop_size(self, desktop_size):
         if desktop_size:
             self.set_registry_key(path, "WineDesktop", desktop_size)
 
+    def set_dpi(self, dpi):
+        """Sets the DPI for WINE to use. 96 DPI is effectively unscaled."""
+        self.set_registry_key(self.hkcu_prefix + "/Software/Wine/Fonts", "LogPixels", dpi)
+        self.set_registry_key(self.hkcu_prefix + "/Control Panel/Desktop", "LogPixels", dpi)
+
     def configure_joypads(self):
         """Disables some joypad devices"""
         key = self.hkcu_prefix + "/Software/Wine/DirectInput/Joysticks"


Test patch: