Skip to content

Commit 4c02530

Browse files
committed
Adjust tooltip to fit in one monitor #557
This commit contributes to fixing the infinite looping effect on painting a tooltip over a TreeItem on win32 when a tooltip is 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. contributes to #557
1 parent c2136c9 commit 4c02530

File tree

1 file changed

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

1 file changed

+59
-3
lines changed

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

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8157,11 +8157,23 @@ 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+
Point cursorLocation = display.getCursorLocation();
8169+
Rectangle monitorBounds = cursorLocation instanceof MonitorAwarePoint monitorAwarePoint
8170+
? getContainingMonitorBoundsInMultiZoomCoordinateSystem(monitorAwarePoint)
8171+
: getContainingMonitorBoundsInSingleZoomCoordinateSystem(cursorLocation);
8172+
if (monitorBounds == null) {
8173+
return null;
8174+
}
8175+
Rectangle adjustedTooltip = getAdjustedTooltipIfNeeded(toolRect, monitorBounds);
8176+
OS.SetWindowPos (itemToolTipHandle, 0, adjustedTooltip.x, adjustedTooltip.y, adjustedTooltip.width, adjustedTooltip.height, flags);
81658177
return LRESULT.ONE;
81668178
}
81678179
return result;
@@ -8170,6 +8182,50 @@ LRESULT wmNotifyToolTip (NMHDR hdr, long wParam, long lParam) {
81708182
return null;
81718183
}
81728184

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

0 commit comments

Comments
 (0)