Skip to content

Commit 039e666

Browse files
mkartashevjbrbot
authored andcommitted
JBR-6145 Wayland: synthetic focus for popups
1 parent b8c22c8 commit 039e666

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

src/java.desktop/unix/classes/sun/awt/wl/WLKeyboardFocusManagerPeer.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package sun.awt.wl;
22

3+
import sun.awt.AWTAccessor;
34
import sun.awt.KeyboardFocusManagerPeerImpl;
45
import sun.util.logging.PlatformLogger;
56

@@ -35,10 +36,25 @@ public Window getCurrentFocusedWindow() {
3536

3637
@Override
3738
public void setCurrentFocusOwner(Component comp) {
39+
Window cur = getCurrentFocusedWindow();
3840
if (comp != null && (!(comp instanceof Window window) ||
39-
WLComponentPeer.getNativelyFocusableOwnerOrSelf(window) != currentFocusedWindow)) {
41+
WLComponentPeer.getNativelyFocusableOwnerOrSelf(window) != cur)) {
4042
// In Wayland, only Window can be focused, not any widget in it.
4143
focusLog.severe("Unexpected focus owner set in a Window: " + comp);
44+
return;
45+
}
46+
47+
if (comp != null) {
48+
Window nativeFocusable = WLComponentPeer.getNativelyFocusableOwnerOrSelf(comp);
49+
AWTAccessor.ComponentAccessor acc = AWTAccessor.getComponentAccessor();
50+
WLComponentPeer nativeFocusablePeer = acc.getPeer(nativeFocusable);
51+
if (nativeFocusablePeer instanceof WLWindowPeer windowPeer) {
52+
// May have to transfer the keyboard focus to a child popup window
53+
// when this 'windowPeer' receives focus from Wayland again because popups
54+
// aren't natively focusable under Wayland.
55+
Component synthFocusOwner = nativeFocusable != comp ? comp : null;
56+
windowPeer.setSyntheticFocusOwner(synthFocusOwner);
57+
}
4258
}
4359
}
4460

src/java.desktop/unix/classes/sun/awt/wl/WLToolkit.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,19 @@ private static void dispatchKeyboardEnterEvent(long serial, long surfacePtr) {
402402

403403
final WLInputState newInputState = inputState.updatedFromKeyboardEnterEvent(serial, surfacePtr);
404404
final WLWindowPeer peer = peerFromSurface(surfacePtr);
405-
if (peer != null && peer.getTarget() instanceof Window window) {
405+
if (peer != null) {
406+
Window window = (Window) peer.getTarget();
407+
Window winToFocus = window;
408+
409+
Component s = peer.getSyntheticFocusOwner();
410+
if (s instanceof Window synthWindow) {
411+
if (synthWindow.isVisible() && synthWindow.isFocusableWindow()) {
412+
winToFocus = synthWindow;
413+
}
414+
}
415+
406416
WLKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(window);
407-
final WindowEvent windowEnterEvent = new WindowEvent(window, WindowEvent.WINDOW_GAINED_FOCUS);
417+
WindowEvent windowEnterEvent = new WindowEvent(winToFocus, WindowEvent.WINDOW_GAINED_FOCUS);
408418
postPriorityEvent(windowEnterEvent);
409419
}
410420
inputState = newInputState;

src/java.desktop/unix/classes/sun/awt/wl/WLWindowPeer.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,15 @@
4343
import java.awt.geom.Path2D;
4444
import java.awt.peer.ComponentPeer;
4545
import java.awt.peer.WindowPeer;
46+
import java.lang.ref.WeakReference;
4647

4748
public class WLWindowPeer extends WLComponentPeer implements WindowPeer {
4849
private static Font defaultFont;
4950
private Dialog blocker;
5051

52+
// If this window gets focus from Wayland, we need to transfer focus synthFocusOwner, if any
53+
private WeakReference<Component> synthFocusOwner = new WeakReference<>(null);
54+
5155
public static final String WINDOW_CORNER_RADIUS = "apple.awt.windowCornerRadius";
5256

5357
private WLRoundedCornersManager.RoundedCornerKind roundedCornerKind = WLRoundedCornersManager.RoundedCornerKind.DEFAULT; // guarded by stateLock
@@ -224,6 +228,14 @@ private void requestWindowFocus() {
224228
}
225229
}
226230

231+
public Component getSyntheticFocusOwner() {
232+
return synthFocusOwner.get();
233+
}
234+
235+
public void setSyntheticFocusOwner(Component c) {
236+
synthFocusOwner = new WeakReference<>(c);
237+
}
238+
227239
private boolean canPaintRoundedCorners() {
228240
int roundedCornerSize = WLRoundedCornersManager.roundCornerRadiusFor(roundedCornerKind);
229241
// Note: You would normally get a transparency-capable color model when using

0 commit comments

Comments
 (0)