rolve/gui

Scaling problem

Closed this issue · 6 comments

I am using the library on a Windows machine with a display resolution 3840 x 2400 and the recommended scaling of 250%.
I then executed the following program:

package ch.fhnw.graphs;
import gui.Window;

public class Sample {
    public static void main(String[] args) {
        Window window = new Window("Graph", 800, 600);
        window.open();
        window.setColor(255,0,0);

        while (window.isOpen()) {
            var x = window.getMouseX();
            var y = window.getMouseY();
            System.out.println(x + "/" + y);
            window.fillCircle(x, y, 10);
            window.refreshAndClear(20);
        }
    }
}

When the program is started and the cursor is moved, a red circle follows the mouse, and in the console the coordinates of the mouse are printed (in the range (0,0) to (799,599) as expected).

If however the mouse button is pressed (left or right one), then on my machine the rectangle in which the mouse can be moved is restricted to the rectangle (0,0) to (266, 199), i.e. to a third of the defined size (266 == 800/3, 199 == 600/3) in each direction.

On my machine, the screen resulution is 240 and the scaling factor computed in class Window with the assignment

private final int pixelScale = (int) round(getDefaultToolkit().getScreenResolution() / 96.0);

returns the value pixelScale == 3, and I think that the reason for the misbehaviour is this pixelScale factor, but it seems that it is only applied if the mouse button is pressed.

In addition, it seems that this scaling factor is computed for the primary screen. If I move the application window on a second display which has another scaling factor, then the red circle is no longer below the mouse, i.e. the mouse then moves faster than the red circle.

rolve commented

Working with multiple displays is a known (remembered) issue. I didn't know it was that bad, though… Indeed, this can probably not be solved using our manual scaling approach.

I checked out @danielkroeni's version. It seems to work “better”, i.e., it does not cause any problems when working with multiple displays. However, there is another (more minor) problem when letting Java do the scaling.

Since the client code draws outside the UI thread, we have our own image buffering going on: The commands draw on a BufferedImage that is painted on the JPanel later (and possibly multiple times). If we let Java do the scaling, the result will be pixelated for scales greater than 100%, as the buffer has a lower resolution than the window. See the following examples.

125%, Java's scaling:
java-scaling-125%

125%, custom scaling (in this case no scaling happens, as we round down to int):
manual-scaling-125%

200%, Java's scaling:
java-scaling-200%

200%, custom scaling:
manual-scaling-200%

To avoid this pixelation, the buffering needs to be implemented differently. I can look into that at some point.

For now, I merged @danielkroeni's changes back into master, bumping the project version along the way. It would be good if both of you could try out this new version 1.2.0-SNAPSHOT on the machines that had issues and let me know if those are fixed with this version. Of course, this may cause the pixelation issues shown above. One can always go back to using 1.1.0-SNAPSHOT to get the old behavior.

I'll leave this issue open until we have a solution that scales correctly without pixelation.

rolve commented

So I couldn't let it go and invested some time to implement a new buffering strategy, see 558ff59. The pixelation issue above should be solved now. Feel free to try out the new version 1.3.0-SNAPSHOT and let me know if there are any issues with it.

I just tested the library (version 1.3.0-SNAPSHOT) with the program shown above in this issue on my laptop where the primary screen is scaled at 250% and the secondary screen is scaled at 125%, and it works fine. It even works if the windows is displayed on both screens at the same time, i.e. half on one screen, half on the other screen; and there are no updating issues when the window is moved from one screen to the other screen.

Hi @rolve, thank you for your effort. I just tested our OOP1 game using the new version 1.3.0-SNAPSHOT. Everything works as expected but there seems to be a difference regarding the background color of the window.

With later versions the background of the window was pure white, like the background of our duke picture:
original

With version 1.3.0 it looks more like grey.
1 3 0

I have attached an archive containing the source code.

I see the same difference regarding the background color in version 1.3.0-SNAPSHOT compared to versions 1.2.0-SNAPSHOT and 1.1.0-SNAPSHOT, even if the screen is not scaled (i.e. with a scaling factor of 100%).

rolve commented

Thank you so much for testing this. So it looks like the issue is solved. The thing with the background was a small oversight and is fixed now. I didn't create a new version for this; after 24h, when you do mvn compile or the equivalent with Gradle, you should get the fixed 1.3.0-SNAPSHOT version. (You can force the update with -U for Maven or --refresh-dependencies for Gradle, I think.)