Improved input event handling

- Added Component.passInputToChildren()
- Input events can now be processed in parallel or recursively
This commit is contained in:
OLEGSHA 2021-12-21 00:31:35 +03:00
parent f350467942
commit 92f9639c4b
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
2 changed files with 20 additions and 11 deletions

View File

@ -562,6 +562,10 @@ public class Component extends Named {
}
}
protected boolean passInputToChildren(InputEvent e) {
return true;
}
InputBus getInputBus() {
return inputBus;
}

View File

@ -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 {
@ -75,9 +76,11 @@ public abstract class GUILayer extends AssembledFlatLayer {
}
/**
* Stack for {@link #handleInput(InputEvent)}.
* Stacks for {@link #handleInput(InputEvent)}.
*/
private StashingStack<EventHandlingFrame> path = new StashingStack<>(64, EventHandlingFrame::new);
private final LowOverheadCache<StashingStack<EventHandlingFrame>> pathCache = new LowOverheadCache<>(
() -> new StashingStack<>(64, EventHandlingFrame::new)
);
/*
* This is essentially a depth-first iteration of the component tree. The
@ -85,10 +88,10 @@ public abstract class GUILayer extends AssembledFlatLayer {
*/
@Override
public void handleInput(InputEvent event) {
StashingStack<EventHandlingFrame> 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,6 +117,8 @@ public abstract class GUILayer extends AssembledFlatLayer {
}
}
pathCache.release(path);
}
private void attemptFocusTransfer(KeyEvent e) {