Skip to content
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

Guard monitor.zoom with isRescalingAtRuntime flag #1508

Merged

Conversation

amartya4256
Copy link
Contributor

@amartya4256 amartya4256 commented Oct 7, 2024

This contribution protects the unintended usage of different zoom levels of different monitors in trasnlating the points and rectangles from control to display coordinate system when the isRescalingAtRuntime flag is disabled.

contributes to #62 and #127

How To Test

  • Set your monitor setup like this:

Left Monitor: 200% Zoom, Right Monitor : 100% Zoom (Primary Monitor)

  • Create this Snippet:
public class TestSnippet {

	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText("Snippet Lol");
		Text text = new Text(shell, SWT.BORDER);
		text.setBounds(20, 20, 500, 30);
		Button button = new Button(shell, SWT.PUSH);
		button.setBounds(100, 80, 100, 30);
		button.setText("Relocate");
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				Point location = shell.getLocation();
				location.x = Integer.parseInt(text.getText());
				shell.setLocation(location);
			}
		});
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}
  • Checkout the master branch
  • Disable rescaling
  • Let's say your 200% monitor has pixels from -2000 to 0. Enter the value of x more than the half, i.e. > -1000 and < 0.
  • You will see the shell placed in the other monitor (100% monitor in the right) and not in the one expected, because 200 is used as the scaling factor and not the primary monitor zoom.
  • Now Enable rescaling.
  • Try it again, you'll see the placement to be in the 200% monitor.
  • Now, switch to the branch guard_monitor_zoom_usage and try the whole scenario with rescaling disabled. It should use the primary monitor zoom (100%) and the shell should be positioned in the 200% monitor when you set the x >-1000 and < 0.
  • If you enable the flag, the behavior should be identical to the behavior on master.

Note: The placement of the shell for x > -1000 is done wrt to the zoom of primary monitor in case it is outside the scaled down bounds. However, when the bounds of the monitor are set in setClientArea method, they are not scaled down according to their zoom level when autoScaleOnRuntime is disabled hence, the code considers -2000 to 0 to be under 200% monitor in th scaled down variant and scales it up by 200% when asked to translate the point. We cannot store the zoom differently to comply with the usage of monitor in other places since it is the part of common widgets. hence, we need to make sure we don't use the monitor zoom while mapping the coordinates when the flag is disabled but rather use the default zoom.

Copy link
Contributor

github-actions bot commented Oct 7, 2024

Test Results

   486 files  ±0     486 suites  ±0   7m 24s ⏱️ -14s
 4 154 tests ±0   4 146 ✅ ±0   8 💤 ±0  0 ❌ ±0 
16 370 runs  ±0  16 278 ✅ ±0  92 💤 ±0  0 ❌ ±0 

Results for commit d491442. ± Comparison against base commit 8fe0fb0.

♻️ This comment has been updated with latest results.

@@ -3193,7 +3193,7 @@ private Rectangle translateRectangleInPixelsInDisplayCoordinateSystem(int x, int

private Rectangle translateRectangleInPixelsInDisplayCoordinateSystem(int x, int y, int width, int height, Monitor monitorOfLocation, Monitor monitorOfArea) {
Point topLeft = getPixelsFromPoint(monitorOfLocation, x, y);
int zoom = DPIUtil.getZoomForAutoscaleProperty(monitorOfArea.zoom);
int zoom = isRescalingAtRuntime() ? DPIUtil.getZoomForAutoscaleProperty(monitorOfArea.zoom) : getDeviceZoom();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two remarks from my side:
1.) getDeviceZoom() is the native zoom, so don't we need to do DPIUtil.getZoomForAutoscaleProperty(getDeviceZoom()) as well?
2.) As the zoom calculation got a bit more complex and it is used at five places, doesn't it make sense to extract that into a private method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For 2, its a one-liner. Would you really want to move it to a method?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a one liner, because of the special notation we can use. here. But this logic must be applied the same on all places and it is some kind of logic, so I would vote for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@amartya4256 amartya4256 force-pushed the guard_monitor_zoom_usage branch 2 times, most recently from 7746231 to b492f42 Compare October 10, 2024 11:39
@fedejeanne
Copy link
Contributor

@amartya4256 it's not clear to me what the error was (i.e. what does this PR fix?).

I tested with this snippet:

/*******************************************************************************
 * Copyright (c) 2024 Yatta Solutions
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Yatta Solutions - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.snippets;

import java.util.concurrent.*;

import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;

public class Snippet384 {

	public static void main(String[] args) throws InterruptedException {
		Display display = new Display();

		// Open a shell where the mouse currently is
		Shell shell = new Shell(display);
		shell.setSize(100, 50);
		shell.setLocation(180, 220);
		shell.open();

		// Move slowly to the left
		for (int i = 0; i < 15; i++) {
			TimeUnit.SECONDS.sleep(1);
			Point location = shell.getLocation();
			location.x -= 20; // to the left
			System.out.println("Moving to position: (" + location.x + ", " + location.y + ")");
			shell.setLocation(location);
		}

		display.dispose();
	}

}

Both without any VM-arguments and also with -Dswt.autoScale.updateOnRuntime=false

The result before and after this PR what the same:

  1. No visual differences
  2. Console output was:
Moving to position: (160, 220)
Moving to position: (140, 220)
Moving to position: (120, 220)
Moving to position: (100, 220)
Moving to position: (80, 220)
Moving to position: (-1753, 220)
Moving to position: (-1773, 220)
Moving to position: (-1793, 220)
Moving to position: (-1813, 220)
Moving to position: (-1833, 220)
Moving to position: (-1853, 220)
Moving to position: (-1873, 220)
Moving to position: (-1893, 220)
Moving to position: (-1913, 220)
Moving to position: (-1933, 220)

Am I testing this wrong?

Could you please add more details to the description of this PR?

@HeikoKlare
Copy link
Contributor

I tested with this snippet:

Did you use monitors with different zoom values? From my understanding the issue only occurs in such a setup. But an extended description of the actualy issue and how to reproduce it would be helpful.

In addition, the issue sounds as if it could be covered with a proper regression test rather easily, can't it? Providing one would be the best way of documenting the issue and for preventing regressions.

@fedejeanne
Copy link
Contributor

Did you use monitors with different zoom values?

Yes: 100% on the left and 200% on the right.

Copy link
Contributor

@fedejeanne fedejeanne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it and it works as expected. No regressions either.

Copy link
Contributor

@HeikoKlare HeikoKlare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've not tested this, but code looks sound and should (based on code semantics) definitely improve/fix the regression w.r.t. existing behavior.

This contribution protects the unintended usage of different zoom levels
of different monitors in trasnlating the points and rectangles from
control to display coordinate system when the isRescalingAtRuntime flag
is disabled.

contributes to eclipse-platform#62 and eclipse-platform#127
@HeikoKlare
Copy link
Contributor

Reported API issues on Jenkins are incorrect / not related to this PR. An only reference build (759) is taken:
{D8E536B3-2411-4E2C-B606-68E18E8F8E22}

The current master build (762) has the same issues as this PR: https://ci.eclipse.org/releng/job/eclipse.platform.swt/job/master/762/
{CA2BF2AC-85D0-4B7E-A896-DA7DCD6547C4}

@HeikoKlare HeikoKlare merged commit 7a04f7a into eclipse-platform:master Oct 14, 2024
11 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants