mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Fixed tests failing due to focus timing issues by allowing the test
framework to specify the source of key bindings
This commit is contained in:
parent
3418492a8c
commit
3f62f91a2e
5 changed files with 71 additions and 10 deletions
|
@ -337,7 +337,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||
// Note: there may be a test focus issue here. If this test fails sporadically due to
|
||||
// how the action context is generated (it depends on focus). It is only useful to fail
|
||||
// here in development mode.
|
||||
triggerKey(tool.getToolFrame(), controlEsc);
|
||||
triggerKey(provider.getComponent(), controlEsc);
|
||||
assertProviderIsHidden_InNonBatchMode();
|
||||
}
|
||||
|
||||
|
@ -376,6 +376,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||
provider.addToTool();
|
||||
tool.showComponentProvider(provider, true);
|
||||
waitForSwing();
|
||||
waitForCondition(() -> provider.isVisible());
|
||||
}
|
||||
|
||||
private void hideProvider() {
|
||||
|
@ -546,6 +547,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||
// simulate the user mousing over the toolbar button
|
||||
DockingActionIf closeAction = getAction(tool, provider.getOwner(), "Close Window");
|
||||
assertNotNull("Provider action not installed in toolbar", closeAction);
|
||||
|
||||
DockingWindowManager.setMouseOverAction(closeAction);
|
||||
|
||||
performLaunchKeyStrokeDialogAction();
|
||||
|
@ -554,6 +556,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||
runSwing(() -> dialog.setKeyStroke(ks));
|
||||
|
||||
pressButtonByText(dialog, "OK");
|
||||
waitForSwing();
|
||||
|
||||
assertFalse("Invalid key stroke: " + ks, runSwing(() -> dialog.isVisible()));
|
||||
}
|
||||
|
|
|
@ -77,12 +77,13 @@ public class TableChooserDialogTest extends AbstractGhidraHeadedIntegrationTest
|
|||
tool.setVisible(true);
|
||||
Program program = new ToyProgramBuilder("Test", true).getProgram();
|
||||
Navigatable navigatable = null;
|
||||
dialog = new TableChooserDialog(tool, executor, program, "Title", navigatable);
|
||||
dialog = new TableChooserDialog(tool, executor, program, "Dialog Title", navigatable);
|
||||
|
||||
testAction = new TestAction();
|
||||
dialog.addAction(testAction);
|
||||
|
||||
dialog.show();
|
||||
waitForDialogComponent(TableChooserDialog.class);
|
||||
loadData();
|
||||
}
|
||||
|
||||
|
@ -289,7 +290,8 @@ public class TableChooserDialogTest extends AbstractGhidraHeadedIntegrationTest
|
|||
KeyStroke newKs = KeyStroke.getKeyStroke('A', 0, false);
|
||||
setKeyBindingViaF4Dialog(testAction, newKs);
|
||||
triggerKey(dialog.getComponent(), newKs);
|
||||
assertTrue(testAction.wasInvoked());
|
||||
assertTrue("Action was not invoked from the new key binding: " + newKs,
|
||||
testAction.wasInvoked());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -354,9 +354,9 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the window which contains the specified Provider's component.
|
||||
* Get the window that contains the specified Provider's component
|
||||
* @param provider component provider
|
||||
* @return window or null if component is not visible or not found.
|
||||
* @return window or null if component is not visible or not found
|
||||
*/
|
||||
public Window getProviderWindow(ComponentProvider provider) {
|
||||
ComponentPlaceholder placeholder = getActivePlaceholder(provider);
|
||||
|
@ -366,6 +366,24 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the provider that contains the specified component
|
||||
* @param c the component
|
||||
* @return the provider; null if now containing provider is found
|
||||
*/
|
||||
public ComponentProvider getProvider(Component c) {
|
||||
if (c != null) {
|
||||
DockableComponent dc = getDockableComponent(c);
|
||||
if (dc != null) {
|
||||
ComponentPlaceholder placeholder = dc.getComponentWindowingPlaceholder();
|
||||
if (placeholder != null) {
|
||||
return placeholder.getProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ComponentPlaceholder getActivePlaceholder(ComponentProvider provider) {
|
||||
return placeholderManager.getActivePlaceholder(provider);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.awt.event.KeyListener;
|
|||
import javax.swing.*;
|
||||
import javax.swing.text.JTextComponent;
|
||||
|
||||
import docking.action.MultipleKeyAction;
|
||||
import docking.actions.KeyBindingUtils;
|
||||
import ghidra.util.bean.GGlassPane;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
@ -136,7 +137,7 @@ public class KeyBindingOverrideKeyEventDispatcher implements KeyEventDispatcher
|
|||
return false;
|
||||
}
|
||||
|
||||
KeyBindingPrecedence keyBindingPrecedence = action.getKeyBindingPrecedence();
|
||||
KeyBindingPrecedence keyBindingPrecedence = getValidKeyBindingPrecedence(action);
|
||||
if (keyBindingPrecedence == null) {
|
||||
// Odd Code: we use the precedence as a signal to say that, when it is null, there
|
||||
// are no valid bindings to be processed. We used to have a isValidContext()
|
||||
|
@ -158,6 +159,15 @@ public class KeyBindingOverrideKeyEventDispatcher implements KeyEventDispatcher
|
|||
// @formatter:on
|
||||
}
|
||||
|
||||
private KeyBindingPrecedence getValidKeyBindingPrecedence(DockingKeyBindingAction action) {
|
||||
|
||||
if (action instanceof MultipleKeyAction) {
|
||||
MultipleKeyAction multiAction = (MultipleKeyAction) action;
|
||||
return multiAction.geValidKeyBindingPrecedence(focusProvider.getFocusOwner());
|
||||
}
|
||||
return action.getKeyBindingPrecedence();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given key event should be blocked (i.e., not processed by us or Java).
|
||||
*/
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package docking.action;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.*;
|
||||
|
@ -23,10 +24,11 @@ import javax.swing.*;
|
|||
|
||||
import docking.*;
|
||||
import docking.actions.KeyBindingUtils;
|
||||
import generic.util.WindowUtilities;
|
||||
import ghidra.util.Swing;
|
||||
|
||||
/**
|
||||
* Action that manages multiple PluginActions mapped to this action's key binding.
|
||||
* Action that manages multiple {@link DockingAction}s mapped to a given key binding
|
||||
*/
|
||||
public class MultipleKeyAction extends DockingKeyBindingAction {
|
||||
private List<ActionData> actions = new ArrayList<>();
|
||||
|
@ -228,7 +230,19 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
|
||||
@Override
|
||||
public KeyBindingPrecedence getKeyBindingPrecedence() {
|
||||
List<ExecutableKeyActionAdapter> validActions = getActionsForCurrentContext(null);
|
||||
return geValidKeyBindingPrecedence(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a special version of {@link #getKeyBindingPrecedence()} that allows the internal
|
||||
* key event processing to specify the source component when determining how precedence should
|
||||
* be established for the actions contained herein.
|
||||
* @param source the component; may be null
|
||||
* @return the precedence; may be null
|
||||
*/
|
||||
public KeyBindingPrecedence geValidKeyBindingPrecedence(Component source) {
|
||||
|
||||
List<ExecutableKeyActionAdapter> validActions = getActionsForCurrentContext(source);
|
||||
if (validActions.isEmpty()) {
|
||||
return null; // a signal that no actions are valid for the current context
|
||||
}
|
||||
|
@ -245,7 +259,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
private List<ExecutableKeyActionAdapter> getActionsForCurrentContext(Object eventSource) {
|
||||
|
||||
DockingWindowManager dwm = tool.getWindowManager();
|
||||
Window window = dwm.getActiveWindow();
|
||||
Window window = getWindow(dwm, eventSource);
|
||||
if (window instanceof DockingDialog) {
|
||||
DockingDialog dockingDialog = (DockingDialog) window;
|
||||
DialogComponentProvider provider = dockingDialog.getDialogComponent();
|
||||
|
@ -258,13 +272,27 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
return validActions;
|
||||
}
|
||||
|
||||
ComponentProvider localProvider = dwm.getActiveComponentProvider();
|
||||
ComponentProvider localProvider = getProvider(dwm, eventSource);
|
||||
ActionContext localContext = getLocalContext(localProvider);
|
||||
localContext.setSourceObject(eventSource);
|
||||
List<ExecutableKeyActionAdapter> validActions = getValidContextActions(localContext);
|
||||
return validActions;
|
||||
}
|
||||
|
||||
private ComponentProvider getProvider(DockingWindowManager dwm, Object eventSource) {
|
||||
if (eventSource instanceof Component) {
|
||||
return dwm.getProvider((Component) eventSource);
|
||||
}
|
||||
return dwm.getActiveComponentProvider();
|
||||
}
|
||||
|
||||
private Window getWindow(DockingWindowManager dwm, Object eventSource) {
|
||||
if (eventSource instanceof Component) {
|
||||
return WindowUtilities.windowForComponent((Component) eventSource);
|
||||
}
|
||||
return dwm.getActiveWindow();
|
||||
}
|
||||
|
||||
public List<DockingActionIf> getActions() {
|
||||
List<DockingActionIf> list = new ArrayList<>(actions.size());
|
||||
for (ActionData actionData : actions) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue