Skip to content

Commit

Permalink
Monitor Position Offset for multi zoom level
Browse files Browse the repository at this point in the history
This commit introduces the offsetting of the monitor position to obtain
the absolute and scaled down bounds of the monitor for seamlessly
translating the positioning of the shell at any zoom levels. With this,
we fix several behaviour in multi zoom - multi monitor set up for win32,
such as, proper positioning of the shell and the overlay on dragging,
opening of a new window in the right monitor,etc.

contributes to #62 and #127
  • Loading branch information
amartya4256 committed Jul 17, 2024
1 parent 713f1b0 commit 669160f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1687,7 +1687,8 @@ public Control getCursorControl () {
*/
public Point getCursorLocation () {
checkDevice ();
return DPIUtil.autoScaleDown(getCursorLocationInPixels());
Point pt = getCursorLocationInPixels();
return getLocationInPointWithMonitorOffset(pt.x, pt.y);
}

Point getCursorLocationInPixels () {
Expand All @@ -1696,6 +1697,22 @@ Point getCursorLocationInPixels () {
return new Point (pt.x, pt.y);
}

Point getLocationInPixelsWithMonitorOffset(int x, int y) {
Monitor monitor = getContainingMonitor(x, y);
int zoom = DPIUtil.getZoomForAutoscaleProperty(monitor.zoom);
x = DPIUtil.scaleUp(x - monitor.clientX, zoom) + monitor.clientX;
y = DPIUtil.scaleUp(y - monitor.clientY, zoom) + monitor.clientY;
return new Point(x, y);
}

Point getLocationInPointWithMonitorOffset(int x, int y) {
Monitor monitor = getContainingMonitorInPixelsCoordiate(x, y);
int zoom = DPIUtil.getZoomForAutoscaleProperty(monitor.zoom);
x = DPIUtil.scaleDown(x - monitor.clientX, zoom) + monitor.clientX;
y = DPIUtil.scaleDown(y - monitor.clientY, zoom) + monitor.clientY;
return new Point(x, y);
}

/**
* Returns an array containing the recommended cursor sizes.
*
Expand Down Expand Up @@ -2183,8 +2200,8 @@ Monitor getMonitor (long hmonitor) {
System.err.println("***WARNING: GetDpiForMonitor: SWT could not get valid monitor scaling factor.");
result = 100;
}
monitor.setBounds(DPIUtil.scaleDown(boundsInPixels, autoscaleZoom));
monitor.setClientArea(DPIUtil.scaleDown(clientAreaInPixels, autoscaleZoom));
monitor.setBounds(getBoundsInPointsWithMonitorOffset(boundsInPixels, autoscaleZoom));
monitor.setClientArea(getBoundsInPointsWithMonitorOffset(clientAreaInPixels, autoscaleZoom));
/*
* Always return true monitor zoom value as fetched from native, else will lead
* to scaling issue on OS Win8.1 and above, for more details refer bug 537614.
Expand All @@ -2193,6 +2210,13 @@ Monitor getMonitor (long hmonitor) {
return monitor;
}

private Rectangle getBoundsInPointsWithMonitorOffset(Rectangle boundsInPixels, int zoom) {
Rectangle bounds = DPIUtil.scaleDown(boundsInPixels, zoom);
bounds.x = boundsInPixels.x;
bounds.y = boundsInPixels.y;
return bounds;
}

/**
* Returns an array of monitors attached to the device.
*
Expand Down Expand Up @@ -5262,4 +5286,18 @@ Monitor getContainingMonitor(int x, int y) {
}
return getPrimaryMonitor();
}

Monitor getContainingMonitorInPixelsCoordiate(int xInPixels, int yInPixels) {
Monitor[] monitors = getMonitors();
for (Monitor current : monitors) {
Rectangle clientArea = DPIUtil.scaleUp(current.getClientArea(), DPIUtil.getZoomForAutoscaleProperty(current.zoom));
clientArea.x = current.clientX;
clientArea.y = current.clientY;
if (clientArea.contains(xInPixels, yInPixels)) {
return current;
}
}
return getPrimaryMonitor();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1579,30 +1579,61 @@ private void updateNativeZoomBeforePositionChange(int x, int y) {
}
}

@Override
public Rectangle getBounds() {
Rectangle boundsInPixels = getBoundsInPixels ();
Rectangle bounds = DPIUtil.scaleDown(boundsInPixels, getZoom());
Point pointWithMonitorOffset = display.getLocationInPointWithMonitorOffset(boundsInPixels.x, boundsInPixels.y);
bounds.x = pointWithMonitorOffset.x;
bounds.y = pointWithMonitorOffset.y;
return bounds;
}

@Override
public Point getLocation() {
Point locationInPixels = getLocationInPixels();
Point location = display.getLocationInPointWithMonitorOffset(locationInPixels.x, locationInPixels.y);
return location;
}

@Override
public void setLocation(Point location) {
if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
updateNativeZoomBeforePositionChange(location.x, location.y);
super.setLocation(location);
location = display.getLocationInPixelsWithMonitorOffset(location.x, location.y);
setLocationInPixels(location.x, location.y);
}

@Override
public void setLocation(int x, int y) {
updateNativeZoomBeforePositionChange(x, y);
super.setLocation(x, y);
Point location = display.getLocationInPixelsWithMonitorOffset(x, y);
x = location.x;
y = location.y;
setLocationInPixels(x, y);
}

@Override
public void setBounds(Rectangle rect) {
if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
updateNativeZoomBeforePositionChange(rect.x, rect.y);
super.setBounds(rect);
Rectangle scaledBounds = DPIUtil.scaleUp(rect, getZoom());
Point topLeft = display.getLocationInPixelsWithMonitorOffset(rect.x, rect.y);
scaledBounds.x = topLeft.x;
scaledBounds.y = topLeft.y;
setBoundsInPixels(scaledBounds);
}

@Override
public void setBounds(int x, int y, int width, int height) {
updateNativeZoomBeforePositionChange(x, y);
super.setBounds(x, y, width, height);
int zoom = getZoom();
Point topLeft = display.getLocationInPixelsWithMonitorOffset(x, y);
x = topLeft.x;
y = topLeft.y;
width = DPIUtil.scaleUp(width, zoom);
height = DPIUtil.scaleUp(height, zoom);
setBoundsInPixels(x, y, width, height);
}

@Override
Expand Down

0 comments on commit 669160f

Please sign in to comment.