diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java index 417c6ea..115594b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -562,6 +562,10 @@ public class Component extends Named { } } + protected boolean passInputToChildren(InputEvent e) { + return true; + } + InputBus getInputBus() { return inputBus; } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java index b808aed..1fa73bf 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java @@ -27,6 +27,7 @@ import ru.windcorp.progressia.client.graphics.flat.RenderTarget; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.bus.InputBus; +import ru.windcorp.progressia.common.util.LowOverheadCache; import ru.windcorp.progressia.common.util.StashingStack; public abstract class GUILayer extends AssembledFlatLayer { @@ -40,7 +41,7 @@ public abstract class GUILayer extends AssembledFlatLayer { public GUILayer(String name, Layout layout) { super(name); - + getRoot().setLayout(layout); getRoot().addInputListener(KeyEvent.class, this::attemptFocusTransfer, InputBus.Option.IGNORE_FOCUS); } @@ -75,20 +76,22 @@ public abstract class GUILayer extends AssembledFlatLayer { } /** - * Stack for {@link #handleInput(InputEvent)}. + * Stacks for {@link #handleInput(InputEvent)}. */ - private StashingStack path = new StashingStack<>(64, EventHandlingFrame::new); - + private final LowOverheadCache> pathCache = new LowOverheadCache<>( + () -> new StashingStack<>(64, EventHandlingFrame::new) + ); + /* * This is essentially a depth-first iteration of the component tree. The * recursive procedure has been unrolled to reduce call stack length. */ @Override public void handleInput(InputEvent event) { + StashingStack path = pathCache.grab(); + if (!path.isEmpty()) { - throw new IllegalStateException( - "path is not empty: " + path + ". Are events being processed concurrently?" - ); + throw new IllegalStateException("path is not empty: " + path); } path.push().init(root); @@ -101,7 +104,7 @@ public abstract class GUILayer extends AssembledFlatLayer { Component c = it.next(); if (c.isEnabled()) { - if (c.getChildren().isEmpty()) { + if (c.getChildren().isEmpty() || !c.passInputToChildren(event)) { c.getInputBus().dispatch(event); } else { path.push().init(c); @@ -114,15 +117,17 @@ public abstract class GUILayer extends AssembledFlatLayer { } } + + pathCache.release(path); } - + private void attemptFocusTransfer(KeyEvent e) { Component focused = getRoot().findFocused(); - + if (focused == null) { return; } - + if (e.getKey() == GLFW.GLFW_KEY_TAB && !e.isRelease()) { e.consume(); if (e.hasShift()) {