Skip to content

Fit tooltip of the tree on a single monitor #62 #2142

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

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2811,7 +2811,7 @@ boolean findCell (int x, int y, TreeItem [] item, int [] index, RECT [] cellRect
itemRect [0].top = boundsInPixels.y;
itemRect [0].bottom = boundsInPixels.y + boundsInPixels.height;
} else {
itemRect [0] = item [0].getBounds (order [index [0]], true, false, false, false, false, hDC);
itemRect [0] = item [0].getBounds (order [index [0]], true, true, false, false, false, hDC);
}
if (itemRect [0].right > cellRect [0].right) found = true;
quit = true;
Expand Down Expand Up @@ -7397,6 +7397,8 @@ LRESULT wmNotify (NMHDR hdr, long wParam, long lParam) {
if (hdr.hwndFrom == itemToolTipHandle && itemToolTipHandle != 0) {
LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
if (result != null) return result;
} else if (hdr.code == OS.TTN_SHOW) {
return positionTooltip(hdr, wParam, lParam, false);
}
if (hdr.hwndFrom == hwndHeader && hwndHeader != 0) {
LRESULT result = wmNotifyHeader (hdr, wParam, lParam);
Expand Down Expand Up @@ -8145,44 +8147,55 @@ LRESULT wmNotifyToolTip (NMHDR hdr, long wParam, long lParam) {
return wmNotifyToolTip (nmcd, lParam);
}
case OS.TTN_SHOW: {
LRESULT result = super.wmNotify (hdr, wParam, lParam);
if (result != null) return result;
int pos = OS.GetMessagePos ();
POINT pt = new POINT();
OS.POINTSTOPOINT (pt, pos);
OS.ScreenToClient (handle, pt);
int [] index = new int [1];
TreeItem [] item = new TreeItem [1];
RECT [] cellRect = new RECT [1], itemRect = new RECT [1];
if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
RECT toolRect = toolTipRect (itemRect [0]);
OS.MapWindowPoints (handle, 0, toolRect, 2);
int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER | OS.SWP_NOSIZE;
if (isCustomToolTip ()) flags &= ~OS.SWP_NOSIZE;
// Retrieve the monitor containing the cursor position, as tool tip placement
// must occur on the same monitor to avoid potential infinite loops. When a tool tip
// appears on a different monitor than the cursor, the operating system may
// attempt to re-scale it based on that monitor's settings. This re-scaling
// triggers additional display messages to SWT, creating an infinite loop
// of positioning and re-scaling events.
// Refer: https://github.com/eclipse-platform/eclipse.platform.swt/issues/557
Point cursorLocation = display.getCursorLocation();
Rectangle monitorBounds = cursorLocation instanceof MonitorAwarePoint monitorAwarePoint
? getContainingMonitorBoundsInMultiZoomCoordinateSystem(monitorAwarePoint)
: getContainingMonitorBoundsInSingleZoomCoordinateSystem(cursorLocation);
if (monitorBounds == null) {
return null;
}
Rectangle adjustedTooltipBounds = fitTooltipBoundsIntoMonitor(toolRect, monitorBounds);
OS.SetWindowPos (itemToolTipHandle, 0, adjustedTooltipBounds.x, adjustedTooltipBounds.y, adjustedTooltipBounds.width, adjustedTooltipBounds.height, flags);
return LRESULT.ONE;
}
return result;
return positionTooltip(hdr, wParam, lParam, true);
}
}
return null;
}

private LRESULT positionTooltip(NMHDR hdr, long wParam, long lParam, boolean managedTooltip) {
LRESULT result = super.wmNotify (hdr, wParam, lParam);
if (result != null) return result;
int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER | OS.SWP_NOSIZE;
if (isCustomToolTip () || !managedTooltip) flags &= ~OS.SWP_NOSIZE;
int pos = OS.GetMessagePos ();
POINT pt = new POINT();
OS.POINTSTOPOINT (pt, pos);
OS.ScreenToClient (handle, pt);
int [] index = new int [1];
TreeItem [] item = new TreeItem [1];
RECT [] cellRect = new RECT [1], itemRect = new RECT [1];
if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
RECT toolRect = managedTooltip ? toolTipRect(itemRect [0]) : itemRect [0];
OS.MapWindowPoints (handle, 0, toolRect, 2);
// Retrieve the monitor containing the cursor position, as tool tip placement
// must occur on the same monitor to avoid potential infinite loops. When a tool tip
// appears on a different monitor than the cursor, the operating system may
// attempt to re-scale it based on that monitor's settings. This re-scaling
// triggers additional display messages to SWT, creating an infinite loop
// of positioning and re-scaling events.
// Refer: https://github.com/eclipse-platform/eclipse.platform.swt/issues/557
Point cursorLocation = display.getCursorLocation();
Rectangle monitorBounds = cursorLocation instanceof MonitorAwarePoint monitorAwarePoint
? getContainingMonitorBoundsInMultiZoomCoordinateSystem(monitorAwarePoint)
: getContainingMonitorBoundsInSingleZoomCoordinateSystem(cursorLocation);
if (monitorBounds != null) {
Rectangle adjustedTooltipBounds = fitTooltipBoundsIntoMonitor(toolRect, monitorBounds);
OS.SetWindowPos (hdr.hwndFrom, 0, adjustedTooltipBounds.x, adjustedTooltipBounds.y, adjustedTooltipBounds.width, adjustedTooltipBounds.height, flags);
result = LRESULT.ONE;
}
} else if (!managedTooltip) {
// If managedTooltip is false and the cursor is not over the valid part of the
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not understand this comment: how is managedTooltip relevant here? I don't see that it's checked for this condition branch at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think there should be a check here so that we don't affect anything for custom tooltips.
This else should only execute when managedTooltip == false. I'll make the change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although this has no effect on custom tooltips visually, it's better to have that check.

Copy link
Contributor

@fedejeanne fedejeanne May 14, 2025

Choose a reason for hiding this comment

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

I tested and I can confirm that the extra check if (!managedTooltip) doesn't change the functionality. Furthermore, the whole else block has been added by this PR, which also adds the call to the method positionTooltip(..., false) meaning that this extra check further ensures that the previous use case (which is now the call to positionTooltip(..., true); in line 8150) is not affected.

All in all, I think this change is OK.

// target cell, Windows may still try to display the default tooltip. Since we
// can't prevent it from showing at this point, we set its bounds to zero to
// effectively hide it.
flags |= OS.SWP_NOMOVE;
OS.SetWindowPos (hdr.hwndFrom, 0, 0, 0, 0, 0, flags);
result = LRESULT.ONE;
}
return result;
}

/**
* Adjust the tool tip to fit in a single monitor either by shifting its position or by adjusting it's width.
*/
Expand Down
Loading