36

There are some applications (mainly java based) that don't follow the global 2x scale I set in the screen-settings. So these apps are really tiny on my high DPI screen with 3200x1800px.

How can I get these apps running in a smaller screen resolution?

Pablo Bianchi
  • 15,657
rubo77
  • 32,486
  • Idea/Android Studio have a bug opened and possibly a solution here: https://code.google.com/p/android/issues/detail?id=68781 – Anton Apr 27 '15 at 08:09
  • that is exact the same issue, but II didn't find a solution there either. – rubo77 Apr 27 '15 at 09:14
  • Have you tried running AS/Idea with -Dis.hidpi=true key in command line? It's not general solution, anyway, but I hope it'll help. – Anton Apr 27 '15 at 09:28
  • I changed this at the end in data/bin/studio.sh: eval "$JDK/bin/java" $ALL_JVM_ARGS -Djb.restart.code=88 -Dis.hidpi=true $MAIN_CLASS_NAME "$@" - but no effect – rubo77 Apr 27 '15 at 09:35
  • I added a "dynamic" version, changing resolution per window. It also should work fine with alt-tab. – Jacob Vlijm Apr 30 '15 at 14:57
  • hello @all + is this so-called bug not simply a non-seen wrong definition between all sorts of java-files about screen-resolutions ?! like to be seen to in different homepages about xml html xmlns xls and else file-formats containing java and javascript + simply that there still was no "universal" html or xml header - file ?! – dschinn1001 May 01 '15 at 19:39

4 Answers4

19

Test adding to your java command line: -Dsun.java2d.uiScale=2.0, or set it to a scale factor you want.

epineda
  • 309
  • 3
  • 6
  • 1
    I recommend trying this first before the other two answer. This answer is perfect: 1. works changing the scale/zoom. 2. doesn't affect global scale/zoom. 4. doesn't affect the screen resolution. 3. simple. – izzulmakin Nov 24 '20 at 09:07
  • Works with some Java applications, but leads to system crashes with others at my hands. Use with caution. – LUser Nov 14 '22 at 06:25
14

A major convenience upgrade would be to use a background script, automatically setting the resolution per application, while you can set different resolutions for different (multiple) applications at once.

That is exactly what the script below does.

An example of a default resolution of 1680x1050:

enter image description here

Running gedit, automatically changing to 640x480:

enter image description here

Running gnome-terminal, automatically changing to 1280x1024:

enter image description here

When the application is closed, the resolution is automatically set back to 1680x1050

How to use

  1. Copy the script below into an empty file, save it as set_resolution.py
  2. In the head of the script, set your default resolution, in the line:

    #--- set the default resolution below
    default = "1680x1050"
    #---
    
  3. In the very same directory (folder), create a textfile, exactly named: procsdata.txt. In this textfile, set the desired application or process, followed by a space, followed by the desired resolution. One application or script per line, looking like:

    gedit 640x480
    gnome-terminal 1280x1024
    java 1280x1024
    

    enter image description here

  4. Run the script by the command:

    python3 /path/to/set_resolution.py
    

Note

The script use pgrep -f <process>, which catches all matches, including scripts. The possible downside is that it can cause name clashes when opening a file with the same name as the process.
If you run into issues like that, change:

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

into:

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

The script

#!/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)

Explanation

When the script starts, it reads the file in which you defined your applications and their corresponding desired screen resolutions.

It then keeps an eye on the running processes (running pgrep -f <process> for each of the applications) and sets the resolution if the application starts up.

When pgrep -f <process> does not produce output for any of the listed applications, it sets the resolution to "default".


Edit:

"Dynamic" version (as requested)

While the version above works with multiple listed applications, it only sets the resolution for one application at a time.

The version below can handle different applications with a different (required) resolution, running at the same time. The background script will keep track of what is the front most application, and will set the resolution accordingly. It also works fine with Alt+Tab.

Note that this behaviour might be annoying if you switch a lot between the desktop and listed applications; the frequent resolution switch might be too much.

differences in how to setup

The setup is pretty much the same, appart from the fact that this one uses wmctrl and xdotool:

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

The script

#!/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

Notes

  • Although I have it running for several hours without an error now, please test it thoroughly. If an error might occur, please leave a comment.
  • The script -as it is- works on a single monitor setup.
Jacob Vlijm
  • 83,767
  • @rubo77 The script, as it is, assumes only one of the applications runs at a time. If multiple listed applications run, it picks one, to prevent too many resolution switches at a row, since also switching to the desktop would cause a resolution switch then. I can change that however. I will set as as an option. – Jacob Vlijm Apr 29 '15 at 12:09
  • You can use this command to figure out the name of an app you want to add to the config file: sleep 5 && cat "/proc/$(xdotool getwindowpid "$(xdotool getwindowfocus)")/comm" focus the app within 5 seconds and you get the desired name (source: http://askubuntu.com/a/508539/34298) – rubo77 May 02 '15 at 22:26
  • further Discussion at the issuetracker in https://github.com/rubo77/set_resolution.py – rubo77 May 04 '15 at 12:49
  • 1
    This script has an update, that solves a lot issues at https://github.com/rubo77/set_resolution.py – rubo77 Aug 30 '15 at 20:44
  • could you please look at this and tell me if you think its related? https://askubuntu.com/questions/742897/chrome-resolution-changes-when-monitor-is-turned-off – Kalamalka Kid May 02 '16 at 19:02
  • This leaves so many holes. Ubuntu needs to make a concerted effort to consolidate these issues into a proper option for the display settings. – jowan sebastian Sep 14 '16 at 13:22
  • @JacobVlijm How do you set the resolution per application, even manual? Could you please explain the script? It's the work of randr or something else? – Ho1 Nov 20 '16 at 13:33
  • any issue with running this at startup, and what would be the best way to do that? – Chad Wright Sep 22 '17 at 00:39
2

For Linux:

sudo nano /etc/environment

Add the following:

JAVA_TOOL_OPTIONS=-Dsun.java2d.uiScale=2

... and is better to use METAL look & feel as GTK+ follows some scaling by Gnome also.

Artur Meinild
  • 26,018
falken
  • 31
  • 1
  • needed to say that over WAYLAND, this tweak is not needed - even GTK+ look & feel responses correctly to default desktop scaling changes (the same as other no java app - "hardinfo", for example) – falken Mar 14 '21 at 17:18
1

As a workaround

I created a bash script that changes the resolution to fullHD before it starts the application (in this examle Android Studio) and changes it back to 3200x1800 when the application quits:

sudo nano /usr/local/bin/studio

Enter this script:

#!/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

and give it executeable rights:

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

Then you can start it with Alt+F1 studio


For other resize-factors that 2.0 see https://askubuntu.com/a/486611/34298


For easy switching zoom on and off in Firefox use the extension Zoom Menu Elements

rubo77
  • 32,486