netbeans
netbeans copied to clipboard
Editor with Keyboard focus is not active TopComponent (undo/redo don't work while editing)
Apache NetBeans version
Apache NetBeans 14
What happened
I encountered this problem with the output window detached from the main NetBeans Window
and focus-follows-mouse is set in the linux the window manager. While editing, I moved the mouse from editor to detached window, when the detached window gets focus the undo/redo buttons go inactive, move the mouse back to the editor and the buttons remain inactive although I can edit/save as usual.
How to reproduce
As described in What happened
Did this work correctly in an earlier version?
No / Don't know
Operating System
Linux harmony 5.18.10-76051810-generic #202207071639~1657252310~22.04~7d5e891 SMP PREEMPT_DYNAMIC Fri J x86_64 x86_64 x86_64 GNU/Linux
JDK
8,11,17
Apache NetBeans packaging
Own source build
Anything else
As a workaround, in a JEditorPane
's focusListener.focusGained
, I've essentially got:
TopComponent tc = NbEditorUtilities.getOuterTopComponent(getEditor());
if(tc != TopComponent.getRegistry().getActivated())
tc.requestActive();
where getEditor() is like FocusEvent.getComponent()
.
For NetBeans, perhaps something like this
Mode m = WindowManager.getDefault().findMode(tc);
if(m != null)
central.setActiveMode(m);
in MainWindow's windowListener (but without proper exerience in core.windows, I'd be hesitant to make changes in this area) or maybe a focus listener with something like the workaround I'm using above in an editor's TopComponent
.
Relevant stack when moving mouse to detached window
at org.netbeans.core.windows.WindowManagerImpl.notifyRegistryTopComponentActivated(WindowManagerImpl.java:1199)
at org.netbeans.core.windows.Central.setActiveMode(Central.java:233)
at org.netbeans.core.windows.Central.userActivatedModeWindow(Central.java:1883)
at org.netbeans.core.windows.view.DefaultView.userActivatedModeWindow(DefaultView.java:654)
at org.netbeans.core.windows.view.ui.DefaultSeparateContainer$SharedModeUIBaseImpl$1.windowActivated(DefaultSeparateContainer.java:455)
at java.awt.AWTEventMulticaster.windowActivated(AWTEventMulticaster.java:398)
Are you willing to submit a pull request?
No
Code of Conduct
Yes
i am not sure that this is a bug. Since other windows can have their own undo history. For example, even the ctrl+f combo box has a history.
Whatever has focus should listen to the undo events.
Not sure this is about just undo, or specifically focus on hover. Try detaching a source editor tab into a separate window and Alt-TABing between. The cursor moves from one editor to the other, but the window system active tab doesn't change - undo/redo is wrong, navigator is wrong, and wrong tab is coloured as focused. Typing goes in the right place, though.
Not sure this is about just undo, or specifically focus on hover
Right, the key is that the editor is not the active TopComponent. The description is just to point out that there's an issue, without getting into the weeds. Maybe: Editor with Keyboard focus is not active TopComponent is a good description. I didn't think to say that Ctrl-Z,Ctrl-Y stop working in the editor, that's probably better than talking about the buttons (but I never use those shortcuts).
An editor shortcut, "ActivateMe", could be used with the workaround code I showed.
There are a lot of exceptions that come through org.netbeans.core.windows.FloatingWindowTransparencyManager
, I don't know how general, platform independent, this exception issue is; it may not have anything to do with this problem report.
INFO [org.netbeans.core.nativeaccess.NativeWindowSystemImpl]
java.lang.UnsatisfiedLinkError: libjawt.so: cannot open shared object file: No such file or directory
at com.sun.jna.Native.getWindowHandle0(Native Method)
at com.sun.jna.Native$AWT.getComponentID(Native.java:2383)
at com.sun.jna.Native.getComponentID(Native.java:326)
at com.sun.jna.platform.WindowUtils$X11WindowUtils.getDrawable(WindowUtils.java:1747)
at com.sun.jna.platform.WindowUtils$X11WindowUtils.access$900(WindowUtils.java:1564)
at com.sun.jna.platform.WindowUtils$X11WindowUtils$2.run(WindowUtils.java:1769)
at com.sun.jna.platform.WindowUtils$NativeWindowUtils.whenDisplayable(WindowUtils.java:398)
at com.sun.jna.platform.WindowUtils$X11WindowUtils.setWindowAlpha(WindowUtils.java:1791)
at com.sun.jna.platform.WindowUtils.setWindowAlpha(WindowUtils.java:1992)
[catch] at org.netbeans.core.nativeaccess.NativeWindowSystemImpl.setWindowAlpha(NativeWindowSystemImpl.java:91)
at org.netbeans.core.windows.FloatingWindowTransparencyManager.turnTransparencyOff(FloatingWindowTransparencyManager.java:155)
at org.netbeans.core.windows.FloatingWindowTransparencyManager.toggleFloatingWindowTransparency(FloatingWindowTransparencyManager.java:141)
at org.netbeans.core.windows.FloatingWindowTransparencyManager.update(FloatingWindowTransparencyManager.java:96)
...
@errael are you using Wayland? I think that might be separate issue.
Maybe: Editor with Keyboard focus is not active TopComponent is a good description.
Yes, probably better. That definitely seems like a valid issue to me.
@neilcsmith-net
$ echo $XDG_SESSION_TYPE
x11
Not wayland; current System76/PopOS; gtk3 (Thought I'd already sent this)
@errael I should have paid more attention - have seen issues with component ID on Wayland in the past, but the key thing is the UnsatisfiedLinkError
. That's almost certainly caused by the issue fixed in https://github.com/java-native-access/jna/pull/1422 I assume you might be running with distribution JDK? If so, it's definitely a separate issue.
editor shortcut, "ActivateMe"
Ctrl-0
(SwitchToRecentDocumentAction
) is a shortcut that does it. The code doesn't look right for a generic solution; which should probably be based on Listening to KeyboardFocusManager.
@neilcsmith-net Thanks, (but I don't understand how the pieces fit together)
the key thing is the UnsatisfiedLinkError ... I assume you might be running with distribution JDK?
Statement implies the fix goes into JDK; any idea which, if any, openjdk release has, or will have, it? Probably not important, but I'm curious if I'll see difference.
But wait, I see the jna jars in NetBeans...
Could NetBeans include jna with the fix? It's not in NB-15.
5.9.0
seems to be a year old. The fix you mentioned is in 5.11.0
, end of March. The latest release, 5.12.1
, is end of June.
$ jar -tvf netbeans-15-rc1-bin.zip | grep jna-
433 Wed Jul 20 09:10:34 PDT 2022 netbeans/platform/config/Modules/org-netbeans-libs-jna-platform.xml
1729586 Wed Jul 20 09:10:34 PDT 2022 netbeans/platform/modules/ext/jna-5.9.0.jar
1343236 Wed Jul 20 09:10:34 PDT 2022 netbeans/platform/modules/ext/jna-platform-5.9.0.jar
59224 Wed Jul 20 09:10:34 PDT 2022 netbeans/platform/modules/org-netbeans-libs-jna-platform.jar
481 Wed Jul 20 09:10:34 PDT 2022 netbeans/platform/update_tracking/org-netbeans-libs-jna-platform.xml
It's due to compilation and linking options used in certain JDK builds, particularly from various Linux distros, that cause older versions of JNA not to find libjawt. If you run on another JDK like Azul or Adoptium, you shouldn't see that error. Can you open another issue for that, though, including the stack trace? It's not triggering the main issue.
Can you open another issue for that
Opened #4441
When a mouse click is used to activate the top component, the stack is
at org.netbeans.core.windows.WindowManagerImpl.notifyRegistryTopComponentActivated(WindowManagerImpl.java:1199)
at org.netbeans.core.windows.Central.setActiveMode(Central.java:233)
at org.netbeans.core.windows.Central.userActivatedMode(Central.java:1876)
at org.netbeans.core.windows.view.DefaultView.userActivatedModeView(DefaultView.java:643)
at org.netbeans.core.windows.view.ui.TabbedHandler$ActivationManager.handleActivation(TabbedHandler.java:524)
at org.netbeans.core.windows.view.ui.TabbedHandler$ActivationManager.eventDispatched(TabbedHandler.java:471)
at java.awt.Toolkit$SelectiveAWTEventListener.eventDispatched(Toolkit.java:2194)
I'm guessing a safe approach would be to use this same path when the activation should be done due to a focus change. The following change to org.netbeans.core.windows.view.ui.TabbedHandler
seems to work in some extremely limited testing. Invoking handleActivation
through the KeyboardFocusManager
activates whatever TopComponenet gets keyboard focus; it should only occur when needed. For example, note that in the regular case of a mouse press that there is not a 2nd activation, the conditional test avoids invocation.
The change adds a KeyboardFocusManager propertyChangeListener to ActivationManager
.
if (activationManager == null) {
activationManager = new ActivationManager();
Toolkit.getDefaultToolkit().addAWTEventListener(
activationManager, AWTEvent.MOUSE_EVENT_MASK);
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("focusOwner", activationManager);
}
...
private static class ActivationManager implements AWTEventListener, PropertyChangeListener {
@Override
public void eventDispatched(AWTEvent e) {
if(e.getID() == MouseEvent.MOUSE_PRESSED) {
System.err.println("ActivationManager: mouse: " + (e.getSource() == null ? null : e.getSource().getClass().getSimpleName()));
handleActivation(e.getSource());
}
}
@Override
public void propertyChange(PropertyChangeEvent e) {
Frame mainWindowNB = WindowManagerImpl.getInstance().getMainWindow();
Window activeWindowKB = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
TopComponent currentTC = TopComponent.getRegistry().getActivated();
if(mainWindowNB == activeWindowKB
&& mainWindowNB != SwingUtilities.getRoot(currentTC)) {
System.err.println("ActivationManager: focus: " + (e.getNewValue() == null ? null : e.getNewValue().getClass().getSimpleName()));
handleActivation(e.getNewValue());
}
}
...
private void handleActivation(Object evtObject) {
if (!(evtObject instanceof Component)) {
return;
}
Component comp = (Component) evtObject;
...
#4603 fixes this AFAICT.
I was going to close this since #4603 is merged. But until it's released...
What's best practice for closing an issue?
Fixed in NB16-RC1