-
-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Set default pixel density to the display's density. #952
Set default pixel density to the display's density. #952
Conversation
This is aimed at achieving a High DPI by default for displays that support it.
Thank you, @yehiarasheed , for this PR! What platforms have you tested this on? I suspect platform specific behavior might add some wrinkles. I'd be happy to be wrong about this. Perhaps I have been traumatized by too many MacOS issues. :( Can you make the visibility of the new method |
As it turns out, you're actually correct. After a bit more research, I've discovered that the main issue is actually with windows systems as some of them by default return a DPI of 96 instead of the actual DPI whenever the DPI is high as could be seen here. On another note, I've discovered a fault in the logic of the getDisplayDPI() method implementation that I will correct and add to the PR description so that it is visible for anyone debugging any problems later on. I am testing it on a Windows machine currently on IntelliJ as instructed. Please review and get back to me. My implementation should cover most displays although, upon research, I've discovered that using JavaFX is generally more accurate than using the |
- Added check for Windows systems where Toolkit.getScreenResolution() incorrectly reports 96 DPI on high-DPI screens. - Force 2x scaling for Windows if DPI is 96 to ensure correct display scaling. - Maintain normal 2x scaling for DPI >= 144, fallback to 1x for lower DPI.
Is there a risk this might need to change in the future as monitors & technology evolve?
What other approaches are available here? JavaFX is nice but does that require extra JavaFX jars and libraries to be available? I do like JavaFX though, good for you to look into that. Is there a way to get the pixel density info by making a call directly to the OS? Trying to infer the pixel density from the DPI feels like a less certain approach. We can write native code for each OS to do this. |
There is definitely a risk that this might need to change in the future since we’re relying on a specific number. A better approach would be us checking if the DPI is just greater than 96, so that we don’t specifically check for numbers greater than 144 (hardcoding) and we can include any display with a DPI higher than the standard 96 as high-DPI. Although, most OSes do tend to standardize scaling factors so the number 144 should work fine in most cases.
As for the JavaFX approach, it’s generally more accurate than using the Note Upon revision, if we decided to go with implementing platform-specific methods to get the correct pixel density, we could reuse the methods already implemented in the |
Hi @hx2A , I’m adding support for detecting pixel density across platforms (Windows, macOS, Linux, Wayland). Since Thanks! |
Let's pursue this avenue and see where we can go with it.
I'm not familiar with https://processing.org/reference/libraries/io/index.html Not everyone will be using that library though. In core.jar you will find a For Windows there is a executable called I'm not sure about what to do for Linux. Generally Linux is better behaved about these kinds of things though. |
- Added the getScaleFactor method to different.m to retrieve the display scale factor on macOS. - Updated ThinkDifferent.java to include the native method declaration for getScaleFactor. - Ensured the Makefile compiles different.m correctly for both x86_64 and ARM architectures and creates a universal library. - Implemented getScaleFactor in PImage to call native OS methods based on the platform. This commit prepares the code for compilation and testing on a macOS machine.
- Enhanced `getScaleFactor` to include native OS calls for Windows DPI using `Fenster.exe`. - Adjusted scale factor rounding to use 1.5 as the threshold for high DPI detection. - Added debug print statements to assist with troubleshooting, which can be easily enabled if needed. - Included error handling for potential issues with executing `Fenster.exe`.
- Implement `getScaleFactor()` and `getScaleFactor(String method)` to determine the scale factor based on the operating system. - Add `roundScaleFactor(String roundingMethod, float scaleFactor)` to apply different rounding methods to the scale factor. - Introduce `setDefaultDPIRoundingMethod(String method)` and `getDefaultDPIRoundingMethod()` to manage the default DPI rounding method. - Update error message for running the required executable to be more user-friendly.
- Implemented DPI scaling for Linux using `xdpyinfo` for X11 and `wlr-randr` for Wayland. - Added error handling for potential IOExceptions. - Added logging to indicate the DPI scaling method used. Note: This implementation is pending testing on an AWS instance.
- Added handling for NumberFormatException in the Linux X11 DPI scaling logic. - Tested the changes on a Linux X11 machine.
Hey @yehiarasheed, just wondering—doesn’t |
Hello @SableRaf, I get that adding more code can seem excessive, but here's my reasoning: We still need native methods:AWT has been around for a long time, but leveraging native methods — directly calling system APIs — can provide better performance and platform-specific optimizations. This is especially important for systems where AWT is disabled or unavailable, as methods like Reusing Code and Adding Native Methods:I've already reused existing code, such as Exploring DPI Scaling Further:While AWT can handle pixel density, I found that Qt's approach to DPI scaling offers valuable insights. Qt also recommends using integer scaling values ( The Challenge with Scaling Factors:The key challenge is how to round floating-point scale factors (e.g., 1.25) to determine DPI. Should we round normally, round up to make visuals sharper, or round down to avoid assuming a high-DPI on low-density displays? Should we round in a way that biases displays with DPI greater than 1.75 to be considered equal to 2, while assuming lower values to be equal to 1? More on that here. The Solution: Let the User Decide:Rather than making assumptions, we could let the user choose their preferred rounding method. A default option (normal rounding) could be provided, with the flexibility for users to adjust it via methods or preferences. This would allow users to resolve any "ugly results" on their own. Fallback Mechanism for
|
Hi @yehiarasheed. I appreciate the effort you’ve put into this! Our long-term plan is to move from JOGL and AWT to LWJGL, and when that happens, we’ll handle DPI detection within LWJGL rather than introducing new platform-specific implementations now. To keep things simple in the meantime, we’d like to rely on We won’t be moving forward with this approach, but if you’re interested in contributing a minimal implementation based on Thanks again for your work! |
Hey @SableRaf, Thanks for the feedback! I get the plan to move to LWJGL. I’ll put together a minimal implementation based on displayDensity() and send over a PR soon. |
And @yehiarasheed , it seems the help I was providing before was not as helpful as I would have liked it to be. I do apologize for that. |
No worries @hx2A |
Description
This PR closes issue #950. The aim of this PR is to change the default value of the
pixelDensity
variable, represented by thepixelDensity()
method to the display's density (DPI). The purpose of this change is to provide sharper rendering by default to displays that support High DPI.Implementation
This Section is regarding the implementation itself, I'll leave it here in case it is needed later for debugging. The DPI feature is computed as follows, we are making use of the
Toolkit
class found in thejava.awt
package. I've decided to implement the DPI Computation in a separate method for modularity and easier maintenance later on as could be seen below.I've used the
Toolkit.getDefaultToolkit()
method to acquire the Default Toolkit, on which I invoke the instance methodgetScreenResolution()
which returns the DPI of the display if it could be computed. This introduced a tricky case, on some windows machines, whenever the DPI of the Display is high sometimes windows defaults to a DPI of 96 sometimes as could be seen in this case. Leading us to check if the DPI is equal to 96 and the system is Windows, then assume a High DPI, else just check the DPI value. We assume a High DPI value to be greater than or equal to 144 to cover Windows and Retina macOS displays effectively.Additionally, I've updated the PImage Constructors that make use of the init method, which sets the pixelDensity variable, to use the getDisplayDPI method instead of the default value 1.
As well as the init method itself that has three parameters to use the getDisplayDPI method too.
Any feedback is welcomed.