mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-09 10:01:41 +01:00
JBR-6145 [Wayland toolkit] Popup windows aren't focusable
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
(cherry picked from commit 903231dc50)
This commit is contained in:
@@ -206,20 +206,17 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
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;
|
||||
}
|
||||
@@ -286,9 +283,12 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -1173,4 +1173,23 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,8 @@ public class WLKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@@ -26,11 +26,13 @@ package sun.awt.wl;
|
||||
|
||||
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) {
|
||||
@@ -55,14 +57,29 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer {
|
||||
|
||||
@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
|
||||
@@ -109,7 +126,7 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer {
|
||||
|
||||
@Override
|
||||
public void setModalBlocked(Dialog blocker, boolean blocked) {
|
||||
|
||||
this.blocker = blocked ? blocker : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,8 +165,28 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer {
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user