修复基于java的应用程序在高DPI屏幕上的缩放

有些应用程序(主要是基于Java的)不遵循我在屏幕设置中设置的全局2x比例 。 所以这些应用程序在我的高DPI屏幕上非常 ,3200x1800px。

如何以较小的屏幕分辨率运行这些应用程序?

一个主要的便利升级是使用后台脚本,自动设置每个应用程序的分辨率,同时可以一次为不同(多个)应用程序设置不同的分辨率。

这正是下面的脚本所做的。

默认分辨率为1680x1050的示例:

在此处输入图像描述

运行gedit ,自动更改为640x480

在此处输入图像描述

运行gnome-terminal ,自动更改为1280x1024

在此处输入图像描述

关闭应用程序后,分辨率将自动设置为1680x1050

如何使用

  1. 将下面的脚本复制到一个空文件中,将其另存为set_resolution.py
  2. 在脚本的开头,在行中设置默认分辨率:

     #--- set the default resolution below default = "1680x1050" #--- 
  3. 同一目录 (文件夹)中,创建一个文本文件,名称为: procsdata.txt 。 在此文本文件中,设置所需的应用程序或进程,后跟空格,然后是所需的分辨率。 每行一个应用程序或脚本,如下所示:

     gedit 640x480 gnome-terminal 1280x1024 java 1280x1024 

    在此处输入图像描述

  4. 通过以下命令运行脚本:

     python3 /path/to/set_resolution.py 

注意

该脚本使用pgrep -f ,它捕获所有匹配项,包括脚本。 可能的缺点是,在打开与进程同名的文件时,它可能会导致名称冲突。
如果您遇到类似的问题,请更改:

 matches.append([p, subprocess.check_output(["pgrep", "-f", p]).decode("utf-8")]) 

成:

 matches.append([p, subprocess.check_output(["pgrep", p]).decode("utf-8")]) 

剧本

 #!/usr/bin/env python3 import subprocess import os import time #--- set the default resolution below default = "1680x1050" #--- # read the datafile curr_dir = os.path.dirname(os.path.abspath(__file__)) datafile = curr_dir+"/procsdata.txt" procs_data = [l.split() for l in open(datafile).read().splitlines() if not l == "\n"] procs = [pdata[0] for pdata in procs_data] def check_matches(): # function to find possible running (listed) applications matches = [] for p in procs: try: matches.append([p, subprocess.check_output(["pgrep", "-f", p]).decode("utf-8")]) except subprocess.CalledProcessError: pass match = matches[-1][0] if len(matches) != 0 else None return match matches1 = check_matches() while True: time.sleep(2) matches2 = check_matches() if matches2 == matches1: pass else: if matches2 != None: # a listed application started up since two seconds ago resdata = [("x").join(item[1].split("x")) for item in \ procs_data if item[0] == matches2][0] elif matches2 == None: # none of the listed applications is running any more resdata = default subprocess.Popen(["xrandr", "-s", resdata]) matches1 = matches2 time.sleep(1) 

说明

脚本启动时,它会读取您在其中定义应用程序的文件及其相应的所需屏幕分辨率。

然后,它会密切关注正在运行的进程(为每个应用程序运行pgrep -f ),并在应用程序启动时设置分辨率。

pgrep -f 不为任何列出的应用程序生成输出时,它会将分辨率设置为“default”。


编辑:

“动态”版本(根据要求)

虽然上述版本适用于多个列出的应用程序,但它一次只能为一个应用程序设置分辨率。

下面的版本可以处理具有不同(必需)分辨率的不同应用程序,同时运行。 后台脚本将跟踪最前面的应用程序,并相应地设置分辨率。 它也适用于Alt + Tab

请注意,如果您在桌面和列出的应用程序之间切换很多,这种行为可能会很烦人; 频繁的分辨率切换可能太多了。

如何设置的差异

设置几乎相同,这是因为这个使用了wmctrlxdotool

 sudo apt-get install wmctrl sudo apt-get install xdotool 

剧本

 #!/usr/bin/env python3 import subprocess import os import sys import time #--- set default resolution below resolution = "1680x1050" #--- curr_dir = os.path.dirname(os.path.abspath(__file__)) datafile = curr_dir+"/procsdata.txt" applist = [l.split() for l in open(datafile).read().splitlines()] apps = [item[0] for item in applist] def get(cmd): try: return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8") except subprocess.CalledProcessError: pass def get_pids(): # returns pids of listed applications; seems ok runs = [] for item in apps: pid = get("pgrep -f "+item) if pid != None: runs.append((item, pid.strip())) return runs def check_frontmost(): # returns data on the frontmost window; seems ok frontmost = str(hex(int(get("xdotool getwindowfocus").strip()))) frontmost = frontmost[:2]+"0"+frontmost[2:] try: wlist = get("wmctrl -lpG").splitlines() return [l for l in wlist if frontmost in l] except subprocess.CalledProcessError: pass def front_pid(): # returns the frontmost pid, seems ok return check_frontmost()[0].split()[2] def matching(): # nakijken running = get_pids(); frontmost = check_frontmost() if all([frontmost != None, len(running) != 0]): matches = [item[0] for item in running if item[1] == frontmost[0].split()[2]] if len(matches) != 0: return matches[0] else: pass trigger1 = matching() while True: time.sleep(1) trigger2 = matching() if trigger2 != trigger1: if trigger2 == None: command = "xrandr -s "+resolution else: command = "xrandr -s "+[it[1] for it in applist if it[0] == trigger2][0] subprocess.Popen(["/bin/bash", "-c", command]) print(trigger2, command) trigger1 = trigger2 

笔记

  • 虽然我现在已经运行了几个小时没有错误,但请仔细测试。 如果可能发生错误,请发表评论。
  • 脚本 – 它在单个监视器设置上工作。

作为一种解决方法

我创建了一个bash脚本,在启动应用程序之前将分辨率更改为fullHD(在此测试Android Studio中),并在应用程序退出时将其更改回3200×1800:

 sudo nano /usr/local/bin/studio 

输入此脚本:

 #!/bin/bash # set scaling to x1.0 gsettings set org.gnome.desktop.interface scaling-factor 1 gsettings set com.ubuntu.user-interface scale-factor "{'HDMI1': 8, 'eDP1': 8}" xrandr -s 1920x1080 # call your program /usr/share/android-studio/data/bin/studio.sh # set scaling to x2.0 gsettings set org.gnome.desktop.interface scaling-factor 2 gsettings set com.ubuntu.user-interface scale-factor "{'HDMI1': 8, 'eDP1': 16}" xrandr -s 3200x1800 

并赋予其可执行权利:

 sudo chmod +x /usr/local/bin/studio 

然后你可以用Alt + F1 studio开始它


对于2.0的其他resize因素,请参阅https://askubuntu.com/a/486611/34298


要在Firefox中轻松切换打开和关闭缩放,请使用扩展缩放菜单元素