Исправлено масштабирование Java-приложений для экрана с высоким DPI
Есть некоторые приложения (в основном на основе Java), которые не следуют глобальной шкале 2х, которую я установил в настройках экрана. Так что эти приложения очень маленькие на моем экране с высоким разрешением 3200x1800px.
Как я могу запустить эти приложения в меньшем разрешении экрана?
4 ответа
Основное удобство обновления заключается в использовании фонового сценария, автоматически устанавливающего разрешение для каждого приложения, в то время как вы можете устанавливать разные разрешения для разных (нескольких) приложений одновременно.
Это именно то, что делает скрипт ниже.
Пример разрешения по умолчанию 1680x1050
:
Бег gedit
, автоматически меняется на 640x480
:
Бег gnome-terminal
, автоматически меняется на 1280x1024
:
Когда приложение закрыто, разрешение автоматически возвращается к 1680x1050
Как пользоваться
- Скопируйте приведенный ниже скрипт в пустой файл и сохраните его как
set_resolution.py
В заголовке скрипта установите разрешение по умолчанию в строке:
#--- set the default resolution below default = "1680x1050" #---
В том же каталоге (папке) создайте текстовый файл с точным именем:
procsdata.txt
, В этом текстовом файле задайте желаемое приложение или процесс, затем поставьте пробел и укажите желаемое разрешение. Одно приложение или скрипт на строку, выглядящий так:gedit 640x480 gnome-terminal 1280x1024 java 1280x1024
Запустите скрипт командой:
python3 /path/to/set_resolution.py
Заметка
Использование скрипта pgrep -f <process>
, который ловит все совпадения, включая скрипты. Возможным недостатком является то, что это может вызвать конфликт имен при открытии файла с тем же именем, что и процесс.
Если вы столкнулись с такими проблемами, измените:
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 <process>
для каждого приложения) и устанавливает разрешение при запуске приложения.
когда pgrep -f <process>
не производит вывод ни для одного из перечисленных приложений, он устанавливает разрешение по умолчанию.
Редактировать:
"Динамическая" версия (по запросу)
Хотя вышеприведенная версия работает с несколькими перечисленными приложениями, она одновременно устанавливает разрешение только для одного приложения.
Приведенная ниже версия может обрабатывать разные приложения с разным (требуемым) разрешением, работающие одновременно. Фоновый скрипт будет следить за тем, что является самым передним приложением, и соответственно установит разрешение. Он также отлично работает с Alt+Tab.
Обратите внимание, что это поведение может раздражать, если вы часто переключаетесь между рабочим столом и перечисленными приложениями; частое переключение разрешения может быть слишком большим.
различия в настройке
Настройка почти такая же, исходя из того факта, что этот использует wmctrl
а также xdotool
:
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
Заметки
- Хотя он работает без ошибок в течение нескольких часов, пожалуйста, тщательно протестируйте его. Если ошибка может возникнуть, пожалуйста, оставьте комментарий.
- Скрипт - как он есть - работает на одной настройке монитора.
Проверьте добавление в вашу командную строку Java: -Dsun.java2d.uiScale=2.0
или установите желаемый масштабный коэффициент.
В качестве обходного пути
Я создал сценарий bash, который меняет разрешение на fullHD перед запуском приложения (в этом примере Android Studio) и изменяет его на 3200x1800 при выходе из приложения:
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 см. /questions/287439/masshtabirujte-zagolovki-i-menyu-v-ubuntu-1404-s-pomoschyu-gnome/287449#287449
Для простого включения и выключения зума в Firefox используйте расширение Zoom Menu Elements
Для Linux:
sudo nano /etc/environment
Добавьте следующее:
JAVA_TOOL_OPTIONS=-Dsun.java2d.uiScale=2
... и лучше использовать внешний вид METAL, поскольку GTK+ также следует некоторому масштабированию Gnome.