WorldWindJava icon indicating copy to clipboard operation
WorldWindJava copied to clipboard

Rendering issue: black borders around map when using scaling in 2.2.0

Open nicolas-van opened this issue 5 years ago • 15 comments

Description

Using the version 2.2.0, when using Windows with the scaling graphical parameter activated we can see borders on the top and the right of the WorldWind map:

Annotation 2020-03-31 104113

Steps to Reproduce

On Windows 10, with openjdk 13 or 14 installed, right click your Windows background and choose "Display Settings". Then change the "Scale and Layout" parameter to "125%":

Annotation 2020-03-31 104036

Then launch the WorldWindJava demo application.

You can even switch the "Scale and Layout" display parameter without closing the demo application. The borders will always be present when the setting has a different value than "100%".

Expected behavior: The map displays without the black borders regardless of the "Scale and Layout" display setting.

Actual behavior: There are black borders when the "Scale and Layout" display setting has a value other than "100%".

Reproduces how often: 100% of the time, tested on 3 different computers with different graphic cards (AMD, Nvidia, Intel), all of them with same software configuration (Windows 10, openjdk13, latest commit on develop branch)

Operating System and Version

  • Windows 10 (64 bits of course)
  • openjdk 13 or 14
  • v2.2.0

Additional Information

It's problematic for us because a lot of laptops nowadays have a default scaling parameter set to a value other than 100%. It means that a lot of our user report bugs and we have to explain them how to change their windows configuration as a workaround.

nicolas-van avatar Mar 31 '20 08:03 nicolas-van

Update: I also tested with openjdk 11 and this bug reproduces exactly the same way. I wasn't able to test with jdk 8 as it seems the project doesn't compile easily anymore with that older jdk version.

nicolas-van avatar Mar 31 '20 09:03 nicolas-van

@nicolas-van Thanks for the detailed report. We'll review this issue in our final release testing.

markpet49 avatar Mar 31 '20 20:03 markpet49

we have the same problem but we fixed it with a small workaround. Not the best solution but it works as long as WWJ will be restarted after changing the window scale factor. Then it was running on 4K screens with 125% scaling.

In file WorldWindowGLAutoDrawable.java change:

public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int w, int h) {
        GL2 gl = this.drawable.getGL().getGL2(); // change this as needed
    	double dpiScalingFactor = getScaleFactor();
    	w = (int) (w * dpiScalingFactor);
    	h = (int) (h * dpiScalingFactor);
        gl.glViewport(0, 0, w, h);
        ((Component) glAutoDrawable).setMinimumSize(new Dimension(0, 0));
}

but then the mouse point doesn't fit anymore and we needed to change WorldWindowGLCanvas.java and added the following:

@Override
protected void processMouseEvent(MouseEvent e) {
    	double dpiScalingFactor = (double) (Toolkit.getDefaultToolkit().getScreenResolution() / 96.0);
    	int x = (int) (e.getPoint().x * dpiScalingFactor);
    	int y = (int) (e.getPoint().y * dpiScalingFactor);
    	MouseEvent scaledEvent = new MouseEvent((Component)e.getSource(), e.getID(), e.getWhen(), e.getModifiersEx(), x, y, e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), false,e.getButton());
    	super.processMouseEvent(scaledEvent);
}
protected void processMouseMotionEvent(MouseEvent e) {
    	double dpiScalingFactor = (double) (Toolkit.getDefaultToolkit().getScreenResolution() / 96.0);
    	int x = (int) (e.getPoint().x * dpiScalingFactor);
    	int y = (int) (e.getPoint().y * dpiScalingFactor);
    	MouseEvent scaledEvent = new MouseEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiersEx(),
				x, y, e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), false, e.getButton());
    	super.processMouseMotionEvent(scaledEvent);
}
protected void processMouseWheelEvent(MouseWheelEvent e) {
    	double dpiScalingFactor = (double) (Toolkit.getDefaultToolkit().getScreenResolution() / 96.0);;
    	int x = (int) (e.getPoint().x * dpiScalingFactor);
    	int y = (int) (e.getPoint().y * dpiScalingFactor);
    	MouseWheelEvent scaledEvent = new MouseWheelEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiersEx(), x, y, e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), false, e.getScrollType(),e.getScrollAmount(),e.getWheelRotation());
    	super.processMouseWheelEvent(scaledEvent);
}

I hope it will be fixed in a correct way...

thwe74 avatar Sep 08 '20 07:09 thwe74

@thwe74 : Did you reproduced it with version 2.2.0 or using a random commit on the develop branch like I did ?

nicolas-van avatar Sep 08 '20 07:09 nicolas-van

@nicolas-van: Yes, I tested it with version 2.2.0 and the current develop branch from today. Always the same problem. It looks like the scale factor from the screen is not considered in the JOGL implementation. With the workaround it works

thwe74 avatar Sep 08 '20 10:09 thwe74

I changed the description and title to clearly explain this bug is present in 2.2.0.

nicolas-van avatar Nov 17 '20 13:11 nicolas-van

@thwe74 : I tested your solution, which seems fine, and made a pull request: #218

nicolas-van avatar Nov 17 '20 16:11 nicolas-van

The problem with @thwe74 solution is that it breaks the behavior on MacOS giving wrong scaling factor when has to be 1.0 (actually it's not).

To make it work, you just need to check the OS and do changes with scale factor only on Windows.

Here is some code. We need to know what OS is running on:

src/gov/nasa/worldwind/util/WWUtil.java

public static OS getOS() {
        String osName = System.getProperty("os.name").toLowerCase(Locale.getDefault());
        if (osName.contains("win")) return OS.WINDOWS;
        else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) return OS.LINUX;
        if (osName.contains("mac")) return OS.MAC;
        else return null;
    }

public enum OS {
        WINDOWS,
        LINUX,
        MAC
}

Then use it in our event functions (I showed only one of them):

src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java

@Override
protected void processMouseEvent(MouseEvent e) {
     if (WWUtil.getOS() == WWUtil.OS.WINDOWS) {
         double dpiScalingFactor = (double) (Toolkit.getDefaultToolkit().getScreenResolution() / 96.0);
         int x = (int) (e.getPoint().x * dpiScalingFactor);
         int y = (int) (e.getPoint().y * dpiScalingFactor);
         MouseEvent scaledEvent = new MouseEvent((Component) e.getSource(), e.getID(),
                 e.getWhen(), e.getModifiersEx(), x, y, e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), false, e.getButton());
         super.processMouseEvent(scaledEvent);
     } else super.processMouseEvent(e);
}

yaroslavkulinich avatar Nov 01 '21 17:11 yaroslavkulinich

Elegantly beautiful, like so much from this extraordinary international crew of virtual globe aficionados!

PJHogan avatar Nov 01 '21 22:11 PJHogan

Not as elegant as yaroslavkulinich's code above, but I usually pass an argument to the VM when running WWD on Windows:

-Dsun.java2d.uiScale.enabled=true; -Dide.ui.scale=1.5

This can also be added to a .bat file if folks need to distribute WWD with a launcher:

@echo off
REM Copyright (C) 2012 United States Government as represented by the Administrator of the
REM National Aeronautics and Space Administration.
REM All Rights Reserved.

@echo Running gov.nasa.worldwindx.examples.ApplicationTemplate
java -Dsun.java2d.uiScale.enabled=true -Dide.ui.scale=1.5 -jar "YourWorldWindBuild.jar"

Or you can turn off the scaling factor with VM options, like in this shell script:

# Copyright (C) 2012 United States Government as represented by the Administrator of the
# National Aeronautics and Space Administration.
# All Rights Reserved.

java -Dsun.java2d.uiScale.enabled=false -Xmx1024m -Dsun.java2d.noddraw=true -jar "YourWorldWindBuild.jar"

gknorman avatar Mar 03 '22 21:03 gknorman

Can you fix it and then we can fold that in!

PJHogan avatar Mar 03 '22 21:03 PJHogan

@PJHogan Do you see any reason to support DPI scaling on windows when it's not really supported by Java 8?

If not, this System property can be set in the ApplicationTemplate's start() method instead of calculating the DPI scaling of mouse events ourselves:

if (Configuration.isWindowsOS() && appName != null)
    {
           System.setProperty("sun.java2d.uiScale.enabled", "false");
    }

gknorman avatar Mar 03 '22 22:03 gknorman

NASA, please do your best to HELP make this work! Seems like some basic stuff that dearly needs attention!

PJHogan avatar Mar 04 '22 03:03 PJHogan

@thwe74 @yaroslavkulinich @nicolas-van Thanks for the solutions. I've tried implementing these, and everything seems to work great except dragging the map with the mouse. The modified mouse event doesn't seem to be scaling properly for me and I'm still limited to the "small" map portion when I click and drag the map. Anyone else seeing these issues? I'm using Adoptium JDK 11 if that would matter.

I can't see how the processMouseMotionEvent would be any different than the others.

Edit: Also testing at 200% scaling at 4K resolution

grammesm avatar Dec 21 '22 12:12 grammesm

Is there any chance to solve the remainig issue when changing the scale whith the application running. It is quite annoying, since we sometimes need to change the scaling during presentations of our application. Customers don't like suddenly seeing black borders.

RaimundBarbeln avatar Mar 01 '24 10:03 RaimundBarbeln