Исправлено масштабирование Java-приложений для экрана с высоким DPI

24

Есть некоторые приложения (в основном на основе Java), которые не следуют глобальной шкале 2х, которую я установил в настройках экрана. Так что эти приложения очень маленькие на моем экране с высоким разрешением 3200x1800px.

Как я могу запустить эти приложения в меньшем разрешении экрана?

rubo77
источник
У Idea / Android Studio есть открытая ошибка и, возможно, решение здесь: code.google.com/p/android/issues/detail?id=68781
Антон,
это точно такая же проблема, но я тоже не нашел там решения.
rubo77
Вы пытались запустить AS / Idea с ключом -Dis.hidpi = true в командной строке? Во всяком случае, это не общее решение, но я надеюсь, что это поможет.
Антон,
Я изменил это в конце data/bin/studio.sh: eval "$JDK/bin/java" $ALL_JVM_ARGS -Djb.restart.code=88 -Dis.hidpi=true $MAIN_CLASS_NAME "$@"- но
безрезультатно
Я добавил «динамическую» версию, меняя разрешение для каждого окна. Это также должно хорошо работать с alt-tab.
Якоб Влейм

Ответы:

15

Основное удобство обновления заключается в использовании фонового скрипта, автоматически устанавливающего разрешение каждого приложения , в то время как вы можете устанавливать разные разрешения для разных (нескольких) приложений одновременно.

Это именно то, что делает скрипт ниже.

Пример разрешения по умолчанию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 <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

Заметки

  • Хотя он работает без ошибок в течение нескольких часов, пожалуйста, тщательно протестируйте его. Если ошибка может возникнуть, пожалуйста, оставьте комментарий.
  • Скрипт - как он есть - работает на одной настройке монитора.
Якоб Влейм
источник
@ rubo77 Сценарий, как он есть, предполагает, что одновременно запускается только одно из приложений. Если запущено несколько перечисленных приложений, выбирается одно, чтобы предотвратить слишком большое количество переключателей разрешения в строке, поскольку переключение на рабочий стол приведет к переключению разрешения. Я могу изменить это однако. Я буду устанавливать как вариант.
Якоб Влейм
Вы можете использовать эту команду для определения имени приложения, которое вы хотите добавить в файл конфигурации: sleep 5 && cat "/proc/$(xdotool getwindowpid "$(xdotool getwindowfocus)")/comm"сфокусируйте приложение в течение 5 секунд, и вы получите желаемое имя (источник: askubuntu.com/a/508539/34298 )
rubo77
Дальнейшее обсуждение на Issetracker в github.com/rubo77/set_resolution.py
rubo77
1
Этот скрипт имеет обновление, которое решает много проблем на github.com/rubo77/set_resolution.py
rubo77
не могли бы вы посмотреть на это и сказать мне, если вы думаете, что это связано? askubuntu.com/questions/742897/…
Малыш
3

Проверьте добавление в командную строку Java: -Dsun.java2d.uiScale=2.0или установите желаемый масштабный коэффициент.

epineda
источник
2

В качестве обходного пути

Я создал сценарий 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 см. Https://askubuntu.com/a/486611/34298


Для простого включения и выключения зума в Firefox используйте расширение Zoom Menu Elements

rubo77
источник