Skip to content

Commit 65a88c6

Browse files
amartya4256fedejeanne
authored andcommitted
Fit tooltip of the tree on a single monitor #62
This commit contributes to handling wmNotify event for tooltip of a Tree regardless of if the Tree object maintains the handle of the tooltip in itemToolTipHandle. If there's a tooltip which is not handled by wmNotifyToolTip, it is completely maintained by windows and hence can span over multiple montiors. Hence, with this PR such tooltips are also positioned inside a single monitor to prevent any infinite loop. Contributes to #62 and #128
1 parent 5cbb48a commit 65a88c6

File tree

1 file changed

+47
-34
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets

1 file changed

+47
-34
lines changed

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

+47-34
Original file line numberDiff line numberDiff line change
@@ -2811,7 +2811,7 @@ boolean findCell (int x, int y, TreeItem [] item, int [] index, RECT [] cellRect
28112811
itemRect [0].top = boundsInPixels.y;
28122812
itemRect [0].bottom = boundsInPixels.y + boundsInPixels.height;
28132813
} else {
2814-
itemRect [0] = item [0].getBounds (order [index [0]], true, false, false, false, false, hDC);
2814+
itemRect [0] = item [0].getBounds (order [index [0]], true, true, false, false, false, hDC);
28152815
}
28162816
if (itemRect [0].right > cellRect [0].right) found = true;
28172817
quit = true;
@@ -7397,6 +7397,8 @@ LRESULT wmNotify (NMHDR hdr, long wParam, long lParam) {
73977397
if (hdr.hwndFrom == itemToolTipHandle && itemToolTipHandle != 0) {
73987398
LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
73997399
if (result != null) return result;
7400+
} else if (hdr.code == OS.TTN_SHOW) {
7401+
return positionTooltip(hdr, wParam, lParam, false);
74007402
}
74017403
if (hdr.hwndFrom == hwndHeader && hwndHeader != 0) {
74027404
LRESULT result = wmNotifyHeader (hdr, wParam, lParam);
@@ -8145,44 +8147,55 @@ LRESULT wmNotifyToolTip (NMHDR hdr, long wParam, long lParam) {
81458147
return wmNotifyToolTip (nmcd, lParam);
81468148
}
81478149
case OS.TTN_SHOW: {
8148-
LRESULT result = super.wmNotify (hdr, wParam, lParam);
8149-
if (result != null) return result;
8150-
int pos = OS.GetMessagePos ();
8151-
POINT pt = new POINT();
8152-
OS.POINTSTOPOINT (pt, pos);
8153-
OS.ScreenToClient (handle, pt);
8154-
int [] index = new int [1];
8155-
TreeItem [] item = new TreeItem [1];
8156-
RECT [] cellRect = new RECT [1], itemRect = new RECT [1];
8157-
if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
8158-
RECT toolRect = toolTipRect (itemRect [0]);
8159-
OS.MapWindowPoints (handle, 0, toolRect, 2);
8160-
int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER | OS.SWP_NOSIZE;
8161-
if (isCustomToolTip ()) flags &= ~OS.SWP_NOSIZE;
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);
8178-
return LRESULT.ONE;
8179-
}
8180-
return result;
8150+
return positionTooltip(hdr, wParam, lParam, true);
81818151
}
81828152
}
81838153
return null;
81848154
}
81858155

8156+
private LRESULT positionTooltip(NMHDR hdr, long wParam, long lParam, boolean managedTooltip) {
8157+
LRESULT result = super.wmNotify (hdr, wParam, lParam);
8158+
if (result != null) return result;
8159+
int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER | OS.SWP_NOSIZE;
8160+
if (isCustomToolTip () || !managedTooltip) flags &= ~OS.SWP_NOSIZE;
8161+
int pos = OS.GetMessagePos ();
8162+
POINT pt = new POINT();
8163+
OS.POINTSTOPOINT (pt, pos);
8164+
OS.ScreenToClient (handle, pt);
8165+
int [] index = new int [1];
8166+
TreeItem [] item = new TreeItem [1];
8167+
RECT [] cellRect = new RECT [1], itemRect = new RECT [1];
8168+
if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
8169+
RECT toolRect = managedTooltip ? toolTipRect(itemRect [0]) : itemRect [0];
8170+
OS.MapWindowPoints (handle, 0, toolRect, 2);
8171+
// Retrieve the monitor containing the cursor position, as tool tip placement
8172+
// must occur on the same monitor to avoid potential infinite loops. When a tool tip
8173+
// appears on a different monitor than the cursor, the operating system may
8174+
// attempt to re-scale it based on that monitor's settings. This re-scaling
8175+
// triggers additional display messages to SWT, creating an infinite loop
8176+
// of positioning and re-scaling events.
8177+
// Refer: https://github.com/eclipse-platform/eclipse.platform.swt/issues/557
8178+
Point cursorLocation = display.getCursorLocation();
8179+
Rectangle monitorBounds = cursorLocation instanceof MonitorAwarePoint monitorAwarePoint
8180+
? getContainingMonitorBoundsInMultiZoomCoordinateSystem(monitorAwarePoint)
8181+
: getContainingMonitorBoundsInSingleZoomCoordinateSystem(cursorLocation);
8182+
if (monitorBounds != null) {
8183+
Rectangle adjustedTooltipBounds = fitTooltipBoundsIntoMonitor(toolRect, monitorBounds);
8184+
OS.SetWindowPos (hdr.hwndFrom, 0, adjustedTooltipBounds.x, adjustedTooltipBounds.y, adjustedTooltipBounds.width, adjustedTooltipBounds.height, flags);
8185+
result = LRESULT.ONE;
8186+
}
8187+
} else if (!managedTooltip) {
8188+
// If managedTooltip is false and the cursor is not over the valid part of the
8189+
// target cell, Windows may still try to display the default tooltip. Since we
8190+
// can't prevent it from showing at this point, we set its bounds to zero to
8191+
// effectively hide it.
8192+
flags |= OS.SWP_NOMOVE;
8193+
OS.SetWindowPos (hdr.hwndFrom, 0, 0, 0, 0, 0, flags);
8194+
result = LRESULT.ONE;
8195+
}
8196+
return result;
8197+
}
8198+
81868199
/**
81878200
* Adjust the tool tip to fit in a single monitor either by shifting its position or by adjusting it's width.
81888201
*/

0 commit comments

Comments
 (0)