Skip to content

Commit

Permalink
JBR-6391 Wayland: memory indicator tooltip flickers
Browse files Browse the repository at this point in the history
  • Loading branch information
mkartashev authored and jbrbot committed Nov 8, 2024
1 parent fa7844d commit e84bddb
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 30 deletions.
45 changes: 44 additions & 1 deletion src/java.desktop/share/classes/javax/swing/ToolTipManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,14 @@ void showTipWindow() {
location.y);
popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);

if (isTooltipPositionedRelatively() && tipWindow.getComponent() != null) {
// When only relative positioning is available, we cannot know if
// the mouse is still over the "hot spot" area where tooltip needs
// to be shown. Instead, we allow the tooltip to remain visible
// as long as the mouse is over the tooltip window. To implement that,
// we want to know when the mouse enters that window.
tipWindow.getComponent().addMouseListener(this);
}
tipWindow.show();

Window componentWindow = SwingUtilities.windowForComponent(
Expand All @@ -391,6 +399,9 @@ void hideTipWindow() {
window.removeMouseListener(this);
window = null;
}
if (isTooltipPositionedRelatively() && tipWindow.getComponent() != null) {
tipWindow.getComponent().removeMouseListener(this);
}
tipWindow.hide();
tipWindow = null;
tipShowing = false;
Expand Down Expand Up @@ -465,6 +476,11 @@ public void unregisterComponent(JComponent component) {
* @param event the event in question
*/
public void mouseEntered(MouseEvent event) {
if (isTooltipPositionedRelatively()) {
var source = event.getSource();
var tooltipComp = tipWindow != null ? tipWindow.getComponent() : null;
tooltipWindowEntered = source == tooltipComp;
}
initiateToolTip(event);
}

Expand Down Expand Up @@ -529,6 +545,8 @@ private void initiateToolTip(MouseEvent event) {
*/
public void mouseExited(MouseEvent event) {
boolean shouldHide = true;
boolean shouldHideImmediately = false;

if (insideComponent == null) {
// Drag exit
}
Expand Down Expand Up @@ -576,9 +594,21 @@ public void mouseExited(MouseEvent event) {
shouldHide = true;
}
}
} else if (isTooltipPositionedRelatively()) {
boolean hasExitedTooltipWindow = tipWindow != null && tipWindow.getComponent() == event.getSource();
if (hasExitedTooltipWindow) {
tooltipWindowEntered = false;
shouldHideImmediately = true;
}
}

if (shouldHide) {
if (shouldHide && !shouldHideImmediately && isTooltipPositionedRelatively()) {
// Let's wait for the tooltip window to get a chance to generate
// the "mouse enter" event. It usually doesn't take long;
// in fact, that event is probably in the queue already.
hideAttemptsCounter = 3;
SwingUtilities.invokeLater(this::maybeHideTipWindow);
} else if (shouldHide) {
enterTimer.stop();
if (insideComponent != null) {
insideComponent.removeMouseMotionListener(this);
Expand All @@ -591,6 +621,19 @@ public void mouseExited(MouseEvent event) {
}
}

private int hideAttemptsCounter = 0;
private boolean tooltipWindowEntered = false;
private void maybeHideTipWindow() {
if (tooltipWindowEntered) {
// Don't hide as the mouse is within the tooltip bounds
hideAttemptsCounter = 0;
} else if (hideAttemptsCounter-- > 0) {
SwingUtilities.invokeLater(this::maybeHideTipWindow);
} else {
hideTipWindow();
}
}

// implements java.awt.event.MouseListener
/**
* Called when the mouse is pressed.
Expand Down
17 changes: 3 additions & 14 deletions src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,6 @@ protected void wlSetVisible(boolean v) {
if (isWlPopup) {
Window popup = (Window) target;
final Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup);
final int parentWidth = popupParent.getWidth();
final int parentHeight = popupParent.getHeight();
final Window toplevel = getToplevelFor(popupParent);
// We need to provide popup "parent" location relative to
// the surface it is painted upon:
Expand All @@ -269,10 +267,9 @@ protected void wlSetVisible(boolean v) {
popupLog.fine("\toffset from anchor: " + offsetFromParent);
}

nativeCreateWLPopup(nativePtr,
getParentNativePtr(target), parentX, parentY, parentWidth, parentHeight,
nativeCreateWLPopup(nativePtr, getParentNativePtr(target),
thisWidth, thisHeight,
offsetX, offsetY);
parentX + offsetX, parentY + offsetY);
} else {
nativeCreateWLSurface(nativePtr,
getParentNativePtr(target),
Expand Down Expand Up @@ -456,8 +453,6 @@ private void repositionWlPopup(int newX, int newY) {
performLocked(() -> {
Window popup = (Window) target;
final Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup);
final int parentWidth = popupParent.getWidth();
final int parentHeight = popupParent.getHeight();
final Window toplevel = getToplevelFor(popupParent);
// We need to provide popup "parent" location relative to
// the surface it is painted upon:
Expand All @@ -473,9 +468,7 @@ private void repositionWlPopup(int newX, int newY) {
popupLog.fine("\toffset of anchor from toplevel: " + toplevelLocation);
popupLog.fine("\toffset from anchor: " + newX + ", " + newY);
}
nativeRepositionWLPopup(nativePtr, parentX, parentY, parentWidth, parentHeight,
thisWidth, thisHeight,
newX, newY);
nativeRepositionWLPopup(nativePtr, thisWidth, thisHeight, parentX + newX, parentY + newY);
} );
}

Expand Down Expand Up @@ -940,14 +933,10 @@ protected native void nativeCreateWLSurface(long ptr, long parentPtr,
String title, String appID);

protected native void nativeCreateWLPopup(long ptr, long parentPtr,
int parentX, int parentY,
int parentWidth, int parentHeight,
int width, int height,
int offsetX, int offsetY);

protected native void nativeRepositionWLPopup(long ptr,
int parentX, int parentY,
int parentWidth, int parentHeight,
int width, int height,
int offsetX, int offsetY);
protected native void nativeHideFrame(long ptr);
Expand Down
25 changes: 10 additions & 15 deletions src/java.desktop/unix/native/libawt_wlawt/WLComponentPeer.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,7 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLSurface

static struct xdg_positioner *
newPositioner
(jint parentX, jint parentY, jint parentWidth, jint parentHeight,
jint width, jint height, jint offsetX, jint offsetY)
(jint width, jint height, jint offsetX, jint offsetY)
{
struct xdg_positioner *xdg_positioner = xdg_wm_base_create_positioner(xdg_wm_base);
CHECK_NULL_RETURN(xdg_positioner, NULL);
Expand All @@ -492,20 +491,20 @@ newPositioner
// a non-zero size set by set_size, and a non-zero anchor rectangle
// set by set_anchor_rect."
xdg_positioner_set_size(xdg_positioner, width, height);
xdg_positioner_set_anchor_rect(xdg_positioner, parentX, parentY, parentWidth, parentHeight);
xdg_positioner_set_offset(xdg_positioner, offsetX, offsetY);
xdg_positioner_set_anchor(xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
xdg_positioner_set_anchor_rect(xdg_positioner, offsetX, offsetY, 1, 1);
xdg_positioner_set_offset(xdg_positioner, 0, 0);
xdg_positioner_set_anchor(xdg_positioner, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT);
xdg_positioner_set_gravity(xdg_positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
xdg_positioner_set_constraint_adjustment(xdg_positioner, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X |
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
xdg_positioner_set_constraint_adjustment(xdg_positioner,
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y
| XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X
| XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
return xdg_positioner;
}

JNIEXPORT void JNICALL
Java_sun_awt_wl_WLComponentPeer_nativeCreateWLPopup
(JNIEnv *env, jobject obj, jlong ptr, jlong parentPtr,
jint parentX, jint parentY,
jint parentWidth, jint parentHeight,
jint width, jint height,
jint offsetX, jint offsetY)
{
Expand All @@ -522,8 +521,7 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLPopup
frame->toplevel = JNI_FALSE;

assert(parentFrame);
struct xdg_positioner *xdg_positioner = newPositioner(parentX, parentY, parentWidth, parentHeight,
width, height, offsetX, offsetY);
struct xdg_positioner *xdg_positioner = newPositioner(width, height, offsetX, offsetY);
CHECK_NULL(xdg_positioner);
frame->xdg_popup = xdg_surface_get_popup(frame->xdg_surface, parentFrame->xdg_surface, xdg_positioner);
CHECK_NULL(frame->xdg_popup);
Expand All @@ -540,17 +538,14 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLPopup
JNIEXPORT void JNICALL
Java_sun_awt_wl_WLComponentPeer_nativeRepositionWLPopup
(JNIEnv *env, jobject obj, jlong ptr,
jint parentX, jint parentY,
jint parentWidth, jint parentHeight,
jint width, jint height,
jint offsetX, jint offsetY)
{
struct WLFrame *frame = jlong_to_ptr(ptr);
assert (!frame->toplevel);

if (wl_proxy_get_version((struct wl_proxy *)xdg_wm_base) >= 3) {
struct xdg_positioner *xdg_positioner = newPositioner(parentX, parentY, parentWidth, parentHeight,
width, height, offsetX, offsetY);
struct xdg_positioner *xdg_positioner = newPositioner(width, height, offsetX, offsetY);
CHECK_NULL(xdg_positioner);
static int token = 42; // This will be received by xdg_popup_repositioned(); unused for now.
xdg_popup_reposition(frame->xdg_popup, xdg_positioner, token++);
Expand Down

0 comments on commit e84bddb

Please sign in to comment.