From d1ee4119e7c582e5a59727aa9f0c1d610a881e04 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 19 Aug 2024 16:21:24 -0400 Subject: [PATCH] GP-4857 - Fix for Structure Editors not always taking focus --- .../src/main/java/docking/ComponentNode.java | 14 ++++---- .../java/docking/ComponentPlaceholder.java | 33 ++++++++++++------- .../java/docking/DockingWindowManager.java | 18 +++------- .../src/main/java/docking/RootNode.java | 6 ++-- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ComponentNode.java b/Ghidra/Framework/Docking/src/main/java/docking/ComponentNode.java index 720e04c394..6f54bc3046 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ComponentNode.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ComponentNode.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,7 +26,8 @@ import org.jdom.Element; import docking.actions.KeyBindingUtils; import docking.widgets.OptionDialog; import docking.widgets.tabbedpane.DockingTabRenderer; -import ghidra.util.*; +import ghidra.util.HelpLocation; +import ghidra.util.Msg; import ghidra.util.exception.AssertException; import help.HelpService; import utilities.util.reflection.ReflectionUtilities; @@ -108,12 +109,9 @@ class ComponentNode extends Node { return; } ComponentPlaceholder placeholder = getPlaceHolderForComponent(component); - if (placeholder == null) { - return; + if (placeholder != null) { + placeholder.requestFocusWhenReady(); } - Swing.runLater(() -> { - placeholder.requestFocus(); - }); } private boolean containsPlaceholder(ComponentPlaceholder placeholder) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ComponentPlaceholder.java b/Ghidra/Framework/Docking/src/main/java/docking/ComponentPlaceholder.java index 1fff84ea1a..4e8bf2aaf6 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ComponentPlaceholder.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ComponentPlaceholder.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,9 +15,10 @@ */ package docking; -import java.awt.Frame; -import java.awt.Window; -import java.util.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import javax.swing.*; @@ -25,8 +26,8 @@ import org.apache.commons.lang3.StringUtils; import docking.action.DockingAction; import docking.action.DockingActionIf; +import generic.timer.ExpiringSwingTimer; import ghidra.util.Msg; -import ghidra.util.Swing; import ghidra.util.exception.AssertException; import utilities.util.reflection.ReflectionUtilities; @@ -275,7 +276,7 @@ public class ComponentPlaceholder { /** * Requests focus for the component associated with this placeholder. */ - void requestFocus() { + void requestFocusWhenReady() { DockableComponent tmp = comp;// put in temp variable in case another thread deletes it if (tmp == null) { return; @@ -285,14 +286,22 @@ public class ComponentPlaceholder { activateWindow(); // make sure the tab has time to become active before trying to request focus - tmp.requestFocus(); - - Swing.runLater(() -> { - tmp.requestFocus(); - contextChanged(); + ExpiringSwingTimer.runWhen(this::isShowing, 750, () -> { + doRequestFocus(tmp); }); } + private void doRequestFocus(DockableComponent dockableComponent) { + KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + Window activeWindow = kfm.getActiveWindow(); + if (activeWindow == null) { + return; // our application isn't focused--don't do anything + } + + dockableComponent.requestFocus(); + contextChanged(); + } + // makes sure that the given window is not in an iconified state private void activateWindow() { DetachedWindowNode windowNode = getDetachedWindowNode(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index 950f784cd0..e5e6e011c2 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -1383,19 +1383,9 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder } private void updateFocus(ComponentPlaceholder placeholder) { - if (placeholder == null) { - return; + if (placeholder != null) { + placeholder.requestFocusWhenReady(); } - - Swing.runLater(() -> { - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Window activeWindow = kfm.getActiveWindow(); - if (activeWindow == null) { - // our application isn't focused--don't do anything - return; - } - placeholder.requestFocus(); - }); } void restoreFocusOwner(String focusOwner, String focusName) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/RootNode.java b/Ghidra/Framework/Docking/src/main/java/docking/RootNode.java index 67173151e6..7d960cb544 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/RootNode.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/RootNode.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -234,7 +234,7 @@ class RootNode extends WindowNode { } detachedWindows.add(windowNode); info.getNode().add(info); - info.requestFocus(); + info.requestFocusWhenReady(); notifyWindowAdded(windowNode); }