Skip to content

Commit

Permalink
JBR-6145 [Wayland toolkit] Popup windows aren't focusable
Browse files Browse the repository at this point in the history
A partial solution. Cases not still covered:
* Alt+tab from the app and back should keep popup focused if it was focused initially
* Mouse clicks between popup and owner should transfer focus as expected
  • Loading branch information
JB-Dmitry authored and jbrbot committed Nov 8, 2024
1 parent ba60bfa commit 903231d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 17 deletions.
43 changes: 31 additions & 12 deletions src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java
Original file line number Diff line number Diff line change
Expand Up @@ -206,20 +206,17 @@ public boolean isFocusable() {
public boolean requestFocus(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time,
FocusEvent.Cause cause) {
final Component currentlyFocused = WLKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner();
if (currentlyFocused == null)
final Window currentlyFocusedWindow = WLKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
if (currentlyFocusedWindow == null)
return false;

WLComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(currentlyFocused);
if (peer == null)
return false;

if (this == peer) {
Window targetDecoratedWindow = getNativelyFocusableOwnerOrSelf(target);
if (currentlyFocusedWindow == targetDecoratedWindow) {
WLKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
target,
null,
true,
cause,
WLKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner());
null);
} else {
return false;
}
Expand Down Expand Up @@ -286,9 +283,12 @@ protected void wlSetVisible(boolean v) {
* Returns true if our target should be treated as a popup in Wayland's sense,
* i.e. it has to have a parent to position relative to.
*/
private boolean targetIsWlPopup() {
return target instanceof Window window
&& window.getType() == Window.Type.POPUP
protected boolean targetIsWlPopup() {
return target instanceof Window window && isWlPopup(window);
}

static boolean isWlPopup(Window window) {
return window.getType() == Window.Type.POPUP
&& AWTAccessor.getWindowAccessor().getPopupParent(window) != null;
}

Expand Down Expand Up @@ -1173,4 +1173,23 @@ static void performUnlocked(Runnable task) {
WLToolkit.awtLock();
}
}

private static void startMovingWindowTogetherWithMouse(Window window, int mouseButton)
{
final AWTAccessor.ComponentAccessor acc = AWTAccessor.getComponentAccessor();
ComponentPeer peer = acc.getPeer(window);
if (peer instanceof WLComponentPeer wlComponentPeer) {
wlComponentPeer.startDrag();
} else {
throw new IllegalArgumentException("AWT window must have WLComponentPeer as its peer");
}
}

static Window getNativelyFocusableOwnerOrSelf(Component component) {
Window result = component instanceof Window window ? window : SwingUtilities.getWindowAncestor(component);
while (result != null && isWlPopup(result)) {
result = result.getOwner();
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public Window getCurrentFocusedWindow() {

@Override
public void setCurrentFocusOwner(Component comp) {
if (comp != null && comp != currentFocusedWindow) {
if (comp != null && (!(comp instanceof Window window) ||
WLComponentPeer.getNativelyFocusableOwnerOrSelf(window) != currentFocusedWindow)) {
// In Wayland, only Window can be focused, not any widget in it.
focusLog.severe("Unexpected focus owner set in a Window: " + comp);
}
Expand Down
45 changes: 41 additions & 4 deletions src/java.desktop/unix/classes/sun/awt/wl/WLWindowPeer.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@

import sun.awt.AWTAccessor;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.WindowPeer;

public class WLWindowPeer extends WLComponentPeer implements WindowPeer {
private static Font defaultFont;
private Dialog blocker;

static synchronized Font getDefaultFont() {
if (null == defaultFont) {
Expand All @@ -55,14 +57,29 @@ public WLWindowPeer(Window target) {

@Override
protected void wlSetVisible(boolean v) {
if (v && targetIsWlPopup() && shouldBeFocusedOnShowing()) {
requestWindowFocus();
}
super.wlSetVisible(v);
final AWTAccessor.ComponentAccessor acc = AWTAccessor.getComponentAccessor();
for (Component c : ((Window)target).getComponents()) {
for (Component c : getWindow().getComponents()) {
ComponentPeer cPeer = acc.getPeer(c);
if (cPeer instanceof WLComponentPeer) {
((WLComponentPeer) cPeer).wlSetVisible(v);
}
}
if (!v && targetIsWlPopup() && getWindow().isFocused()) {
Window targetOwner = getWindow().getOwner();
while (targetOwner != null && (targetOwner.getOwner() != null && !targetOwner.isFocusableWindow())) {
targetOwner = targetOwner.getOwner();
}
if (targetOwner != null) {
WLWindowPeer wndpeer = AWTAccessor.getComponentAccessor().getPeer(targetOwner);
if (wndpeer != null) {
wndpeer.requestWindowFocus();
}
}
}
}

@Override
Expand Down Expand Up @@ -109,7 +126,7 @@ public void updateFocusableWindowState() {

@Override
public void setModalBlocked(Dialog blocker, boolean blocked) {

this.blocker = blocked ? blocker : null;
}

@Override
Expand Down Expand Up @@ -153,8 +170,28 @@ public void repositionSecurityWarning() {

@Override
public GraphicsConfiguration getAppropriateGraphicsConfiguration(
GraphicsConfiguration gc)
{
GraphicsConfiguration gc) {
return gc;
}

private Window getWindow() {
return (Window) target;
}

private boolean shouldBeFocusedOnShowing() {
Window window = getWindow();
return window.isFocusableWindow() &&
window.isAutoRequestFocus() &&
blocker == null;
}

// supporting only 'synthetic' focus transfers for now (when natively focused window stays the same)
private void requestWindowFocus() {
Window window = getWindow();
Window nativeFocusTarget = getNativelyFocusableOwnerOrSelf(window);
if (nativeFocusTarget != null &&
WLKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == nativeFocusTarget) {
WLToolkit.postEvent(new WindowEvent(window, WindowEvent.WINDOW_GAINED_FOCUS));
}
}
}

0 comments on commit 903231d

Please sign in to comment.