Skip to content

Commit 00c6aef

Browse files
amartya4256HeikoKlare
authored andcommitted
[Win32] Adjust tooltip to fit in one monitor eclipse-platform#557
This commit contributes to fixing the infinite looping effect on painting a tooltip over a TreeItem on win32 when a tooltip spans over two monitors having more area on the other monitor than the one on which the cursor is placed. The fix makes sure that the tooltip is not drawn on the other monitors by shifting or adjusting the width. Fixes eclipse-platform#557
1 parent e63c07d commit 00c6aef

File tree

1 file changed

+55
-3
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets

1 file changed

+55
-3
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8157,11 +8157,24 @@ LRESULT wmNotifyToolTip (NMHDR hdr, long wParam, long lParam) {
81578157
if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
81588158
RECT toolRect = toolTipRect (itemRect [0]);
81598159
OS.MapWindowPoints (handle, 0, toolRect, 2);
8160-
int width = toolRect.right - toolRect.left;
8161-
int height = toolRect.bottom - toolRect.top;
81628160
int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER | OS.SWP_NOSIZE;
81638161
if (isCustomToolTip ()) flags &= ~OS.SWP_NOSIZE;
8164-
OS.SetWindowPos (itemToolTipHandle, 0, toolRect.left, toolRect.top, width, height, flags);
8162+
// Retrieve the monitor containing the cursor position, as tool tip placement
8163+
// must occur on the same monitor to avoid potential infinite loops. When a tool tip
8164+
// appears on a different monitor than the cursor, the operating system may
8165+
// attempt to re-scale it based on that monitor's settings. This re-scaling
8166+
// triggers additional display messages to SWT, creating an infinite loop
8167+
// of positioning and re-scaling events.
8168+
// Refer: https://github.com/eclipse-platform/eclipse.platform.swt/issues/557
8169+
Point cursorLocation = display.getCursorLocation();
8170+
Rectangle monitorBounds = cursorLocation instanceof MonitorAwarePoint monitorAwarePoint
8171+
? getContainingMonitorBoundsInMultiZoomCoordinateSystem(monitorAwarePoint)
8172+
: getContainingMonitorBoundsInSingleZoomCoordinateSystem(cursorLocation);
8173+
if (monitorBounds == null) {
8174+
return null;
8175+
}
8176+
Rectangle adjustedTooltipBounds = fitTooltipBoundsIntoMonitor(toolRect, monitorBounds);
8177+
OS.SetWindowPos (itemToolTipHandle, 0, adjustedTooltipBounds.x, adjustedTooltipBounds.y, adjustedTooltipBounds.width, adjustedTooltipBounds.height, flags);
81658178
return LRESULT.ONE;
81668179
}
81678180
return result;
@@ -8170,6 +8183,45 @@ LRESULT wmNotifyToolTip (NMHDR hdr, long wParam, long lParam) {
81708183
return null;
81718184
}
81728185

8186+
/**
8187+
* Adjust the tool tip to fit in a single monitor either by shifting its position or by adjusting it's width.
8188+
*/
8189+
private Rectangle fitTooltipBoundsIntoMonitor(RECT tooltipBounds, Rectangle monitorBounds) {
8190+
int tooltipWidth = tooltipBounds.right - tooltipBounds.left;
8191+
int tooltipHeight = tooltipBounds.bottom - tooltipBounds.top;
8192+
if (tooltipBounds.left < monitorBounds.x) {
8193+
tooltipBounds.left = monitorBounds.x;
8194+
}
8195+
int monitorBoundsRightEnd = monitorBounds.x + monitorBounds.width;
8196+
if (tooltipBounds.right > monitorBoundsRightEnd) {
8197+
if (tooltipWidth <= monitorBounds.width) {
8198+
tooltipBounds.left = monitorBoundsRightEnd - tooltipWidth;
8199+
} else {
8200+
tooltipBounds.left = monitorBounds.x;
8201+
}
8202+
tooltipWidth = monitorBoundsRightEnd - tooltipBounds.left;
8203+
}
8204+
return new Rectangle(tooltipBounds.left, tooltipBounds.top, tooltipWidth, tooltipHeight);
8205+
}
8206+
8207+
private Rectangle getContainingMonitorBoundsInSingleZoomCoordinateSystem(Point point) {
8208+
int zoom = getZoom();
8209+
point = DPIUtil.scaleUp(point, zoom);
8210+
for (Monitor monitor : display.getMonitors()) {
8211+
Rectangle monitorBounds = DPIUtil.scaleUp(monitor.getBounds(), zoom);
8212+
if (monitorBounds.contains(point)) {
8213+
return monitorBounds;
8214+
}
8215+
}
8216+
return null;
8217+
}
8218+
8219+
private Rectangle getContainingMonitorBoundsInMultiZoomCoordinateSystem(MonitorAwarePoint point) {
8220+
Monitor monitor = point.getMonitor();
8221+
return new Rectangle(monitor.x, monitor.y, DPIUtil.scaleUp(monitor.width, monitor.zoom),
8222+
DPIUtil.scaleUp(monitor.height, monitor.zoom));
8223+
}
8224+
81738225
LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW nmcd, long lParam) {
81748226
switch (nmcd.dwDrawStage) {
81758227
case OS.CDDS_PREPAINT: {

0 commit comments

Comments
 (0)