Skip to content

Commit 3a218ab

Browse files
committedOct 14, 2024
JBR-7504 Use accurate event serial number with the clipboard
1 parent f29c9dd commit 3a218ab

14 files changed

+197
-143
lines changed
 

‎src/java.desktop/unix/classes/sun/awt/wl/WLClipboard.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,19 @@ protected void clearNativeContext() {
135135
protected void setContentsNative(Transferable contents) {
136136
// The server requires "serial number of the event that triggered this request"
137137
// as a proof of the right to copy data.
138-
WLPointerEvent wlPointerEvent = WLToolkit.getInputState().eventWithSerial();
139-
long eventSerial = wlPointerEvent == null ? 0 : wlPointerEvent.getSerial();
138+
139+
// It is not specified which event's serial number the Wayland server expects here,
140+
// so the following is a speculation based on experiments.
141+
// The worst case is that a "wrong" serial will be silently ignored, and our clipboard
142+
// will be out of sync with the real one that Wayland maintains.
143+
long eventSerial = isPrimary
144+
? WLToolkit.getInputState().pointerButtonSerial()
145+
: WLToolkit.getInputState().keySerial();
146+
if (!isPrimary && eventSerial == 0) {
147+
// The "regular" clipboard's content can be changed with either a mouse click
148+
// (like on a menu item) or with the keyboard (Ctrl-C).
149+
eventSerial = WLToolkit.getInputState().pointerButtonSerial();
150+
}
140151
if (log.isLoggable(PlatformLogger.Level.FINE)) {
141152
log.fine("Clipboard: About to offer new contents using Wayland event serial " + eventSerial);
142153
}

‎src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java

+47-14
Original file line numberDiff line numberDiff line change
@@ -765,10 +765,16 @@ public Dimension getMinimumSize() {
765765
return target.getSize();
766766
}
767767

768-
void showWindowMenu(int x, int y) {
768+
void showWindowMenu(long serial, int x, int y) {
769+
// "This request must be used in response to some sort of user action like
770+
// a button press, key press, or touch down event."
771+
// So 'serial' must appertain to such an event.
772+
773+
assert serial != 0;
774+
769775
int xNative = javaUnitsToSurfaceUnits(x);
770776
int yNative = javaUnitsToSurfaceUnits(y);
771-
performLocked(() -> nativeShowWindowMenu(nativePtr, xNative, yNative));
777+
performLocked(() -> nativeShowWindowMenu(serial, nativePtr, xNative, yNative));
772778
}
773779

774780
@Override
@@ -846,7 +852,7 @@ public void updateCursorImmediately() {
846852
}
847853

848854
private void updateCursorImmediately(WLInputState inputState) {
849-
WLComponentPeer peer = inputState.getPeer();
855+
WLComponentPeer peer = inputState.peerForPointerEvents();
850856
if (peer == null) return;
851857
Cursor cursor = peer.getCursor(inputState.getPointerX(), inputState.getPointerY());
852858
setCursor(cursor, getGraphicsDevice() != null ? getGraphicsDevice().getDisplayScale() : 1);
@@ -864,6 +870,14 @@ Cursor getCursor(int x, int y) {
864870
}
865871

866872
private static void setCursor(Cursor c, int scale) {
873+
long serial = WLToolkit.getInputState().pointerEnterSerial();
874+
if (serial == 0) {
875+
if (log.isLoggable(Level.WARNING)) {
876+
log.warning("setCursor aborted due to missing event serial");
877+
}
878+
return; // Wayland will ignore the request anyway
879+
}
880+
867881
Cursor cursor;
868882
if (c.getType() == Cursor.CUSTOM_CURSOR && !(c instanceof WLCustomCursor)) {
869883
cursor = Cursor.getDefaultCursor();
@@ -888,7 +902,7 @@ private static void setCursor(Cursor c, int scale) {
888902
}
889903
AWTAccessor.getCursorAccessor().setPData(cursor, scale, pData);
890904
}
891-
nativeSetCursor(pData, scale);
905+
nativeSetCursor(pData, scale, serial);
892906
});
893907
}
894908

@@ -1013,7 +1027,16 @@ final void requestUnsetFullScreen() {
10131027
}
10141028

10151029
final void activate() {
1016-
performLocked(() -> nativeActivate(nativePtr));
1030+
// "The serial can come from an input or focus event."
1031+
long serial = WLToolkit.getInputState().keyboardEnterSerial();
1032+
long surface = WLToolkit.getInputState().surfaceForKeyboardInput();
1033+
if (serial != 0) {
1034+
performLocked(() -> nativeActivate(serial, nativePtr, surface));
1035+
} else {
1036+
if (log.isLoggable(Level.WARNING)) {
1037+
log.warning("activate() aborted due to missing keyboard enter event serial");
1038+
}
1039+
}
10171040
}
10181041

10191042
private static native void initIDs();
@@ -1036,8 +1059,8 @@ protected native void nativeRepositionWLPopup(long ptr,
10361059
protected native void nativeDisposeFrame(long ptr);
10371060

10381061
private native long getWLSurface(long ptr);
1039-
private native void nativeStartDrag(long ptr);
1040-
private native void nativeStartResize(long ptr, int edges);
1062+
private native void nativeStartDrag(long serial, long ptr);
1063+
private native void nativeStartResize(long serial, long ptr, int edges);
10411064

10421065
private native void nativeSetTitle(long ptr, String title);
10431066
private native void nativeRequestMinimized(long ptr);
@@ -1051,11 +1074,11 @@ protected native void nativeRepositionWLPopup(long ptr,
10511074
private native void nativeSetWindowGeometry(long ptr, int x, int y, int width, int height);
10521075
private native void nativeSetMinimumSize(long ptr, int width, int height);
10531076
private native void nativeSetMaximumSize(long ptr, int width, int height);
1054-
private static native void nativeSetCursor(long pData, int scale);
1077+
private static native void nativeSetCursor(long pData, int scale, long pointerEnterSerial);
10551078
private static native long nativeGetPredefinedCursor(String name, int scale);
10561079
private static native long nativeDestroyPredefinedCursor(long pData);
1057-
private native void nativeShowWindowMenu(long ptr, int x, int y);
1058-
private native void nativeActivate(long ptr);
1080+
private native void nativeShowWindowMenu(long serial, long ptr, int x, int y);
1081+
private native void nativeActivate(long serial, long ptr, long activatingSurfacePtr);
10591082

10601083
static long getNativePtrFor(Component component) {
10611084
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
@@ -1459,12 +1482,22 @@ private static void convertPointerEventToMWEParameters(
14591482
}
14601483

14611484

1462-
void startDrag() {
1463-
performLocked(() -> nativeStartDrag(nativePtr));
1485+
void startDrag(long serial) {
1486+
// "This request must be used in response to some sort of user action like a button press,
1487+
// key press, or touch down event. The passed serial is used to determine the type
1488+
// of interactive move (touch, pointer, etc)."
1489+
assert serial != 0;
1490+
1491+
performLocked(() -> nativeStartDrag(serial, nativePtr));
14641492
}
14651493

1466-
void startResize(int edges) {
1467-
performLocked(() -> nativeStartResize(nativePtr, edges));
1494+
void startResize(long serial, int edges) {
1495+
// "This request must be used in response to some sort of user action like a button press,
1496+
// key press, or touch down event. The passed serial is used to determine the type
1497+
// of interactive resize (touch, pointer, etc)."
1498+
assert serial != 0;
1499+
1500+
performLocked(() -> nativeStartResize(serial, nativePtr, edges));
14681501
}
14691502

14701503
/**

‎src/java.desktop/unix/classes/sun/awt/wl/WLFrameDecoration.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ boolean processMouseEvent(MouseEvent e) {
334334
if (isLMBPressed && peer.isInteractivelyResizable()) {
335335
int resizeSide = getResizeEdges(point.x, point.y);
336336
if (resizeSide != 0) {
337-
peer.startResize(resizeSide);
337+
peer.startResize(WLToolkit.getInputState().pointerButtonSerial(), resizeSide);
338338
// workaround for https://gitlab.gnome.org/GNOME/mutter/-/issues/2523
339339
WLToolkit.resetPointerInputState();
340340
return true;
@@ -344,7 +344,7 @@ boolean processMouseEvent(MouseEvent e) {
344344
if (isUndecorated) return false;
345345

346346
if (isRMBPressed && getBounds().contains(e.getX(), e.getY())) {
347-
peer.showWindowMenu(e.getX(), e.getY());
347+
peer.showWindowMenu(WLToolkit.getInputState().pointerButtonSerial(), e.getX(), e.getY());
348348
return true;
349349
}
350350

@@ -371,7 +371,8 @@ boolean processMouseEvent(MouseEvent e) {
371371
if (e.getID() == MouseEvent.MOUSE_PRESSED) {
372372
pressedLocation = point;
373373
} else if (e.getID() == MouseEvent.MOUSE_DRAGGED && pressedInDragStartArea() && isSignificantDrag(point)) {
374-
peer.startDrag();
374+
peer.startDrag(WLToolkit.getInputState().pointerButtonSerial());
375+
375376
} else if (e.getID() == MouseEvent.MOUSE_CLICKED && e.getClickCount() == 2 && pressedInDragStartArea()
376377
&& peer.isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
377378
toggleMaximizedState();

0 commit comments

Comments
 (0)
Please sign in to comment.