chromiumembedded/java-cef

Scale factor on WIndows not always respected properly

ekpeters opened this issue · 10 comments

Describe the bug
On windows 10.
The viewport for the browser does not match the Java UI itself in dimensions. Querying the device does report the correct dimensions, but a corrective scale factor is not applied.

To Reproduce
Steps to reproduce the behavior:

  1. Have 2+ monitors.
  2. Configure them to different UI scales in the Windows Display control panel. "Scale and layout." -> "Change the size of text, apps, and other items". In my case, I set the primary display to 150% and the second display to 100%. It's important
    It's critical that these be different. If they are the same, the problem will not recreate.
  3. Open a basic JCEF browser (not sure what you example is, and I've spent myself trying to just get your code to compile just to patch this for myself. I can provide SSCCE)
  4. Drag the window between your different monitors.

Expected behavior
Window and browser contents adjust in lock-step as the window is dragged between render contexts that apply different scaling. Or if not in lockstep, that adjust correctly after only a short delay not requiring user action.

Screenshots
WrongScale1
WrongScale2
correctScale

Versions (please complete the following information):

  • OS: Windows 10
  • Java Version: Azul Zulu 11.0.16.1
  • JCEF Version: 87476e9+cef-110.0.25
  • CEF Version: 110.0.25 (Launching using the jcefmaven v110.0.25 dependency)

Additional context
Does the problem reproduce with the JCEF simple or detailed sample application at the same version?
Unknown - assumed so.
Does the problem reproduce with the CEF cefclient or cefsimple sample application at the same version?
Unknown.
Does the problem reproduce with Google Chrome at the same version?
Unknown - assumed not.
Add any other context about the problem here.
CefBrowserWr.java line 74 reads as:
'if (OS.isMacintosh() || OS.isLinux()) doUpdate();'
My read of the behaviors, this class file, and that specific line in context suggests that making that doUpdate() call unconditional is necessary. You need to actively apply the scale factor for Mac, Linux, and Windows, which covers the gamut of OSs identified by org.cef.OS.
I understand why you don't want to call doUpdate() unconditionally, but I don't have lots of good alternative suggestions for fixing this, except maybe suppressing no-change updates (which you might already do at some layer).

While I might be able to pre-seed the scale for jcef, I see no way to actually do that for this, other than the faint hope of the CefDisplayHandler, which appears to be hard coded to null for my situation.

Resizing the window programatically usually fixes the problem, but the resize kludge hasn't been working for me in the context of our application's dialogs. I've some ideas why resizing might fail specifically for dialogs, but I'd honestly prefer the scale problem just be fixed outright.

Simpe code example, using jcefmaven to prepare and and start the browser:

import java.awt.BorderLayout;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.File;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

import org.cef.CefApp;
import org.cef.CefClient;
import org.cef.browser.CefBrowser;
import org.cef.browser.CefMessageRouter;

import me.friwi.jcefmaven.CefAppBuilder;
import me.friwi.jcefmaven.CefInitializationException;
import me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler;

/**

  • This is a simple application with the address bar and JCEF.
    */
    public final class Launcher {

    //private static final String URL = "https://www.whatismybrowser.com";
    private static final String URL="data:text/html,Lorem ipsum "
    + "dolor sit amet, consectetur adipiscing elit. Etiam aliquet"
    + "leo sit amet finibus rutrum. Praesent sagittis urna arcu, sed "
    + "maximus nisl aliquam eget. Vivamus mollis vitae sem vel posuere."
    + " Suspendisse vitae dignissim lectus, vel feugiat erat. In efficitur "
    + "mi ut risus bibendum tempor. Nunc in faucibus nibh. Cras quis velit ex. "
    + "Etiam sed elementum magna. Pellentesque malesuada lacus viverra "
    + "ullamcorper mattis. Fusce interdum maximus turpis, id vehicula augue "
    + "sollicitudin a. Aenean rutrum dui risus, vel sagittis orci pretium non."
    + " Nam metus nibh, sagittis ac tincidunt vel, cursus vitae lorem. Morbi "
    + "ut purus erat. Curabitur sit amet purus posuere, tempor eros at, "
    + "eleifend leo. Mauris maximus aliquam rutrum. ";
    private static final boolean OFFSCREEN = false;
    private static final boolean TRANSPARENT = false;

    public static void main(String[] args) throws java.io.IOException, me.friwi.jcefmaven.UnsupportedPlatformException, InterruptedException, CefInitializationException
    {
    CefAppBuilder builder = new CefAppBuilder();

     builder.setInstallDir(new File("jcef-bundle")); //Default
     builder.setProgressHandler(new ConsoleProgressHandler()); //Default
     builder.getCefSettings().windowless_rendering_enabled = false; //Default - select OSR mode
    
     CefApp app = builder.build();
     if (!CefApp.startup(args)) {
     	System.out.println("Startup initialization failed!");
     	return;
     }
    
     CefClient client = app.createClient();
     client.addMessageRouter(CefMessageRouter.create());
     CefBrowser browser = client.createBrowser(URL, OFFSCREEN, TRANSPARENT);
    
     JFrame frame = new JFrame("DummyWindow");
     frame.setSize(400, 400);
     frame.add(browser.getUIComponent(), BorderLayout.CENTER);
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
     frame.setVisible(true);
    

    }
    }

A comment and an observation...
1- I'm only about 80% certain that invoking the mac/linux fix on windows will fix my issue.
2- You probably want CefBrowserWr.scaleFactor to be volatile, so that when accessed from multiple threads some threads do not get old values for it.

Apparently, my invoking doUpdate() does not work (tried reflectively). Yes - it's picking up the scaleFactor, ... eh, I've burned enough time already trying to get this browser to work usably for this scenario. Re-examining the screenshots, it's possible the scale is correct and the position is wrong.

One of the curious points is the 'grow-browser-by-2-pixels' resize fixes the problem for full-up JFrames, but does not fix it windows opened as modal dialogs (oauth popups).

Not sure it helps, but it is possible on the java side to sus out physical and logical screen dimensions in Java without access to a Graphics2D component, though what I use myself might actually be brittle (the wording on the api descriptions isn't helpful). That doesn't yield a scale-factor directly, but it could be useful regardless.

Does the problem reproduce with the JCEF simple or detailed sample application at the same version?
Unknown - assumed so.

Please test with the JCEF sample apps. They are easy to build/run with the JCEF binary distribution.

If you would like me to use said sample apps, please direct me to them.

I am not psychic, and while I have done some looking for such an app, I have not found any clear indicator that such apps even exists - aside from the request when posting a bug report to try said apps.

While you are at it - could you update the Readme.md to indicate where said apps live, and add a link to them in the bug reporting instructions.

The JCEF main page includes build instructions at https://github.com/chromiumembedded/java-cef/#building-jcef

The jcefmaven project also links to a (different) sample app on their main page.

I am not psychic...

Please keep the conversation constructive.

Initial appearance of the sample app:
image
Dragged to Display 1:
image
Dragged back to Display 0:
image

Monitor specs as derived from java.awt.GraphicsEnvironment:
Screen("\Display0", Relative position: 0.0x0.0, logical size: 1728.0x3072.0, physical size: 2160x3840)
Screen("\Display1", Relative position: 2160.0x504.0, logical size: 1280.0x1024.0, physical size: 1280x1024)

(Edit to fix 2nd image)

Thanks for the updated details.

A similar issue was fixed in #343. It looks like you're using Java 11, so perhaps something more is now required with that version.

Correct, this is Java 11. Moving Java 17 is on the todo-list for us, but buried under a stack of other priorities,