Split the functions up, so you don't have to care about the Unsync ones at all in most cases while still getting synced behavior.

This commit is contained in:
Henrik Rydgård 2023-05-26 11:49:50 +02:00
parent cca613e785
commit 3715b1ffa1
8 changed files with 97 additions and 42 deletions

View File

@ -204,8 +204,8 @@ bool IsScrollKey(const KeyInput &input) {
}
}
bool KeyEvent(const KeyInput &key, ViewGroup *root) {
bool retval = false;
KeyEventResult UnsyncKeyEvent(const KeyInput &key, ViewGroup *root) {
KeyEventResult retval = KeyEventResult::PASS_THROUGH;
// Ignore repeats for focus moves.
if ((key.flags & (KEY_DOWN | KEY_IS_REPEAT)) == KEY_DOWN) {
if (IsDPadKey(key) || IsScrollKey(key)) {
@ -218,13 +218,13 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root) {
// Check if the key is already held. If it is, ignore it. This is to avoid
// multiple key repeat mechanisms colliding.
if (heldKeys.find(hk) != heldKeys.end()) {
return false;
return KeyEventResult::IGNORE_KEY;
}
heldKeys.insert(hk);
std::lock_guard<std::mutex> lock(focusLock);
focusMoves.push_back(key.keyCode);
retval = true;
retval = KeyEventResult::ACCEPT;
}
}
if (key.flags & KEY_UP) {
@ -236,27 +236,28 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root) {
hk.triggerTime = 0.0; // irrelevant
if (heldKeys.find(hk) != heldKeys.end()) {
heldKeys.erase(hk);
retval = true;
retval = KeyEventResult::ACCEPT;
}
}
}
retval = root->Key(key);
// Ignore volume keys and stuff here. Not elegant but need to propagate bools through the view hierarchy as well...
switch (key.keyCode) {
case NKCODE_VOLUME_DOWN:
case NKCODE_VOLUME_UP:
case NKCODE_VOLUME_MUTE:
retval = false;
retval = KeyEventResult::PASS_THROUGH;
break;
default:
break;
}
return retval;
}
void KeyEvent(const KeyInput &key, ViewGroup *root) {
root->Key(key);
}
static void ProcessHeldKeys(ViewGroup *root) {
double now = time_now_d();
@ -283,16 +284,15 @@ restart:
}
}
bool TouchEvent(const TouchInput &touch, ViewGroup *root) {
void TouchEvent(const TouchInput &touch, ViewGroup *root) {
focusForced = false;
root->Touch(touch);
if ((touch.flags & TOUCH_DOWN) && !focusForced) {
EnableFocusMovement(false);
}
return true;
}
bool AxisEvent(const AxisInput &axis, ViewGroup *root) {
void AxisEvent(const AxisInput &axis, ViewGroup *root) {
enum class DirState {
NONE = 0,
POS = 1,
@ -376,10 +376,11 @@ bool AxisEvent(const AxisInput &axis, ViewGroup *root) {
}
break;
}
default:
break;
}
root->Axis(axis);
return true;
}
void UpdateViewHierarchy(ViewGroup *root) {

View File

@ -23,10 +23,19 @@ class ViewGroup;
void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root, bool ignoreInsets);
void UpdateViewHierarchy(ViewGroup *root);
enum class KeyEventResult {
IGNORE_KEY, // Don't let it be processed.
PASS_THROUGH, // Let it be processed, but return false.
ACCEPT, // Let it be processed, but return true.
};
// Hooks arrow keys for navigation
bool KeyEvent(const KeyInput &key, ViewGroup *root);
bool TouchEvent(const TouchInput &touch, ViewGroup *root);
bool AxisEvent(const AxisInput &axis, ViewGroup *root);
KeyEventResult UnsyncKeyEvent(const KeyInput &key, ViewGroup *root);
void KeyEvent(const KeyInput &key, ViewGroup *root);
void TouchEvent(const TouchInput &touch, ViewGroup *root);
void AxisEvent(const AxisInput &axis, ViewGroup *root);
enum class UISound {
SELECT = 0,

View File

@ -82,11 +82,11 @@ void ScreenManager::touch(const TouchInput &touch) {
if (touch.flags & TOUCH_RELEASE_ALL) {
for (auto &layer : stack_) {
Screen *screen = layer.screen;
layer.screen->touch(screen->transformTouch(touch));
layer.screen->UnsyncTouch(screen->transformTouch(touch));
}
} else if (!stack_.empty()) {
Screen *screen = stack_.back().screen;
stack_.back().screen->touch(screen->transformTouch(touch));
stack_.back().screen->UnsyncTouch(screen->transformTouch(touch));
}
}
@ -96,10 +96,10 @@ bool ScreenManager::key(const KeyInput &key) {
// Send key up to every screen layer, to avoid stuck keys.
if (key.flags & KEY_UP) {
for (auto &layer : stack_) {
result = layer.screen->key(key);
result = layer.screen->UnsyncKey(key);
}
} else if (!stack_.empty()) {
result = stack_.back().screen->key(key);
result = stack_.back().screen->UnsyncKey(key);
}
return result;
}
@ -120,10 +120,10 @@ void ScreenManager::axis(const AxisInput &axis) {
// Send center axis to every screen layer.
if (axis.value == 0) {
for (auto &layer : stack_) {
layer.screen->axis(axis);
layer.screen->UnsyncAxis(axis);
}
} else if (!stack_.empty()) {
stack_.back().screen->axis(axis);
stack_.back().screen->UnsyncAxis(axis);
}
}

View File

@ -55,13 +55,14 @@ public:
virtual void postRender() {}
virtual void resized() {}
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
virtual void touch(const TouchInput &touch) {}
virtual bool key(const KeyInput &key) { return false; }
virtual void axis(const AxisInput &touch) {}
virtual void sendMessage(const char *msg, const char *value) {}
virtual void deviceLost() {}
virtual void deviceRestored() {}
virtual void UnsyncTouch(const TouchInput &touch) {}
virtual bool UnsyncKey(const KeyInput &touch) { return false; }
virtual void UnsyncAxis(const AxisInput &touch) {}
virtual void RecreateViews() {}
ScreenManager *screenManager() { return screenManager_; }

View File

@ -61,6 +61,27 @@ void UIScreen::DoRecreateViews() {
}
void UIScreen::touch(const TouchInput &touch) {
if (!ignoreInput_) {
UI::TouchEvent(touch, root_);
}
}
void UIScreen::axis(const AxisInput &axis) {
if (!ignoreInput_) {
UI::AxisEvent(axis, root_);
}
}
bool UIScreen::key(const KeyInput &key) {
if (!ignoreInput_) {
UI::KeyEvent(key, root_);
return false;
} else {
return false;
}
}
void UIScreen::UnsyncTouch(const TouchInput &touch) {
if (root_) {
if (ClickDebug && (touch.flags & TOUCH_DOWN)) {
INFO_LOG(SYSTEM, "Touch down!");
@ -79,7 +100,7 @@ void UIScreen::touch(const TouchInput &touch) {
eventQueue_.push_back(ev);
}
void UIScreen::axis(const AxisInput &axis) {
void UIScreen::UnsyncAxis(const AxisInput &axis) {
std::lock_guard<std::mutex> guard(eventQueueLock_);
QueuedEvent ev{};
ev.type = QueuedEventType::AXIS;
@ -87,12 +108,28 @@ void UIScreen::axis(const AxisInput &axis) {
eventQueue_.push_back(ev);
}
bool UIScreen::key(const KeyInput &key) {
if (root_ && !ignoreInput_) {
bool UIScreen::UnsyncKey(const KeyInput &key) {
bool retval = false;
if (root_) {
// TODO: Make key events async too. The return value is troublesome, though.
return UI::KeyEvent(key, root_);
switch (UI::UnsyncKeyEvent(key, root_)) {
case UI::KeyEventResult::ACCEPT:
retval = true;
break;
case UI::KeyEventResult::PASS_THROUGH:
retval = false;
break;
case UI::KeyEventResult::IGNORE_KEY:
return false;
}
}
return false;
std::lock_guard<std::mutex> guard(eventQueueLock_);
QueuedEvent ev{};
ev.type = QueuedEventType::KEY;
ev.key = key;
eventQueue_.push_back(ev);
return true;
}
void UIScreen::update() {
@ -122,6 +159,7 @@ void UIScreen::update() {
}
switch (ev.type) {
case QueuedEventType::KEY:
key(ev.key);
break;
case QueuedEventType::TOUCH:
if (ClickDebug && (ev.touch.flags & TOUCH_DOWN)) {
@ -132,10 +170,10 @@ void UIScreen::update() {
INFO_LOG(SYSTEM, "%s", view->DescribeLog().c_str());
}
}
UI::TouchEvent(ev.touch, root_);
touch(ev.touch);
break;
case QueuedEventType::AXIS:
UI::AxisEvent(ev.axis, root_);
axis(ev.axis);
break;
}
}

View File

@ -42,9 +42,13 @@ public:
void deviceLost() override;
void deviceRestored() override;
void touch(const TouchInput &touch) override;
bool key(const KeyInput &touch) override;
void axis(const AxisInput &touch) override;
virtual void touch(const TouchInput &touch);
virtual bool key(const KeyInput &touch);
virtual void axis(const AxisInput &touch);
void UnsyncTouch(const TouchInput &touch) override;
bool UnsyncKey(const KeyInput &touch) override;
void UnsyncAxis(const AxisInput &touch) override;
TouchInput transformTouch(const TouchInput &touch) override;

View File

@ -538,7 +538,7 @@ void EmuScreen::sendMessage(const char *message, const char *value) {
}
}
void EmuScreen::touch(const TouchInput &touch) {
void EmuScreen::UnsyncTouch(const TouchInput &touch) {
Core_NotifyActivity();
if (chatMenu_ && chatMenu_->GetVisibility() == UI::V_VISIBLE) {
@ -802,11 +802,11 @@ void EmuScreen::onVKeyAnalog(int virtualKeyCode, float value) {
limitMode = PSP_CoreParameter().analogFpsLimit == 60 ? FPSLimit::NORMAL : FPSLimit::ANALOG;
}
bool EmuScreen::key(const KeyInput &key) {
bool EmuScreen::UnsyncKey(const KeyInput &key) {
Core_NotifyActivity();
if (UI::IsFocusMovementEnabled()) {
if (UIScreen::key(key)) {
if (UIScreen::UnsyncKey(key)) {
return true;
} else if ((key.flags & KEY_DOWN) != 0 && UI::IsEscapeKey(key)) {
if (chatMenu_)
@ -821,7 +821,7 @@ bool EmuScreen::key(const KeyInput &key) {
return controlMapper_.Key(key, &pauseTrigger_);
}
void EmuScreen::axis(const AxisInput &axis) {
void EmuScreen::UnsyncAxis(const AxisInput &axis) {
Core_NotifyActivity();
return controlMapper_.Axis(axis);

View File

@ -50,9 +50,11 @@ public:
void sendMessage(const char *msg, const char *value) override;
void resized() override;
void touch(const TouchInput &touch) override;
bool key(const KeyInput &key) override;
void axis(const AxisInput &axis) override;
// Note: Unlike your average boring UIScreen, here we override the Unsync* functions
// to get minimal latency and full control. We forward to UIScreen when needed.
void UnsyncTouch(const TouchInput &touch) override;
bool UnsyncKey(const KeyInput &key) override;
void UnsyncAxis(const AxisInput &axis) override;
private:
void CreateViews() override;