Doesn't yet work

This commit is contained in:
Henrik Rydgård
2026-06-24 23:04:17 +02:00
parent 729f11ecbe
commit 72ee82844d
16 changed files with 133 additions and 151 deletions
+3 -3
View File
@@ -51,11 +51,11 @@ PopupScreen::PopupScreen(std::string_view title, std::string_view button1, std::
alpha_ = 0.0f; // inherited
}
void PopupScreen::touch(const TouchInput &touch) {
bool PopupScreen::touch(const TouchInput &touch) {
if (!box_ || (touch.flags & TouchInputFlags::DOWN) == 0) {
// Handle down-presses here.
UIDialogScreen::touch(touch);
return;
return false;
}
// Extra bounds to avoid closing the dialog while trying to aim for something
@@ -65,7 +65,7 @@ void PopupScreen::touch(const TouchInput &touch) {
TriggerFinish(DR_CANCEL);
}
UIDialogScreen::touch(touch);
return UIDialogScreen::touch(touch);
}
bool PopupScreen::key(const KeyInput &key) {
+1 -1
View File
@@ -25,7 +25,7 @@ public:
virtual void CreatePopupContents(UI::ViewGroup *parent) = 0;
void CreateViews() override;
bool isTransparent() const override { return true; }
void touch(const TouchInput &touch) override;
bool touch(const TouchInput &touch) override;
bool key(const KeyInput &key) override;
void TriggerFinish(DialogResult result) override;
+77 -31
View File
@@ -108,7 +108,6 @@ void ScreenManager::cancelScreensAbove(Screen *screen) {
void ScreenManager::update() {
std::lock_guard<std::recursive_mutex> guard(inputLock_);
if (cancelScreensAbove_) {
bool found = false;
for (int i = (int)stack_.size() - 1; i >= 0; i--) {
@@ -136,6 +135,67 @@ void ScreenManager::update() {
stack_.back().screen->update();
passInputToMapper_ = stack_.back().screen->PassInputToMapper();
}
// Process queued events.
std::lock_guard<std::mutex> eventGuard(eventQueueLock_);
for (const QueuedEvent &ev : eventQueue_) {
switch (ev.type) {
case QueuedEventType::TOUCH:
{
const TouchInput &touch = ev.touch;
// Send release all events to every screen layer.
if (touch.flags & TouchInputFlags::RELEASE_ALL) {
for (auto &layer : stack_) {
Screen *screen = layer.screen;
layer.screen->touch(screen->transformTouch(touch));
}
} else if (!stack_.empty()) {
// Let the overlay know about touch-downs, to be able to dismiss popups.
bool skip = false;
if (overlayScreen_ && (touch.flags & TouchInputFlags::DOWN)) {
skip = overlayScreen_->touch(overlayScreen_->transformTouch(touch));
}
if (!skip) {
Screen *screen = stack_.back().screen;
stack_.back().screen->touch(screen->transformTouch(touch));
}
}
break;
}
case QueuedEventType::KEY:
{
const KeyInput &key = ev.key;
std::lock_guard<std::recursive_mutex> guard(inputLock_);
// Send key up to every screen layer, to avoid stuck keys.
if (key.flags & KeyInputFlags::UP) {
for (auto &layer : stack_) {
layer.screen->key(key);
}
} else if (!stack_.empty()) {
stack_.back().screen->key(key);
}
break;
}
case QueuedEventType::AXIS:
{
const AxisInput &axis = ev.axis;
std::lock_guard<std::recursive_mutex> guard(inputLock_);
if (!stack_.empty()) {
stack_.back().screen->axis(axis);
}
break;
}
default:
ERROR_LOG(Log::UI, "Unknown queued event type: %d", (int)ev.type);
break;
}
}
}
void ScreenManager::switchToNext() {
@@ -163,42 +223,28 @@ void ScreenManager::switchToNext() {
}
void ScreenManager::touch(const TouchInput &touch) {
std::lock_guard<std::recursive_mutex> guard(inputLock_);
// Send release all events to every screen layer.
if (touch.flags & TouchInputFlags::RELEASE_ALL) {
for (auto &layer : stack_) {
Screen *screen = layer.screen;
layer.screen->UnsyncTouch(screen->transformTouch(touch));
}
} else if (!stack_.empty()) {
// Let the overlay know about touch-downs, to be able to dismiss popups.
bool skip = false;
if (overlayScreen_ && (touch.flags & TouchInputFlags::DOWN)) {
skip = overlayScreen_->UnsyncTouch(overlayScreen_->transformTouch(touch));
}
if (!skip) {
Screen *screen = stack_.back().screen;
stack_.back().screen->UnsyncTouch(screen->transformTouch(touch));
}
}
QueuedEvent ev{};
ev.type = QueuedEventType::TOUCH;
ev.touch = touch;
std::lock_guard<std::mutex> guard(eventQueueLock_);
eventQueue_.push_back(ev);
}
void ScreenManager::key(const KeyInput &key) {
std::lock_guard<std::recursive_mutex> guard(inputLock_);
// Send key up to every screen layer, to avoid stuck keys.
if (key.flags & KeyInputFlags::UP) {
for (auto &layer : stack_) {
layer.screen->UnsyncKey(key);
}
} else if (!stack_.empty()) {
stack_.back().screen->UnsyncKey(key);
}
QueuedEvent ev{};
ev.type = QueuedEventType::KEY;
ev.key = key;
std::lock_guard<std::mutex> guard(eventQueueLock_);
eventQueue_.push_back(ev);
}
void ScreenManager::axis(const AxisInput *axes, size_t count) {
std::lock_guard<std::recursive_mutex> guard(inputLock_);
if (!stack_.empty()) {
stack_.back().screen->UnsyncAxis(axes, count);
QueuedEvent ev{};
ev.type = QueuedEventType::AXIS;
std::lock_guard<std::mutex> guard(eventQueueLock_);
for (size_t i = 0; i < count; i++) {
ev.axis = axes[i];
eventQueue_.push_back(ev);
}
}
+22 -6
View File
@@ -16,6 +16,7 @@
#include <cstdint>
#include <mutex>
#include <string>
#include <deque>
#include <unordered_map>
#include <vector>
@@ -84,6 +85,21 @@ enum class InputMode {
};
ENUM_CLASS_BITOPS(InputMode);
enum class QueuedEventType : u8 {
KEY,
AXIS,
TOUCH,
};
struct QueuedEvent {
QueuedEventType type;
union {
TouchInput touch;
KeyInput key;
AxisInput axis;
};
};
class Screen {
public:
Screen() = default;
@@ -103,11 +119,9 @@ public:
virtual void focusChanged(ScreenFocusChange focusChange);
// Return value of UnsyncTouch is only used to let the overlay screen block touches.
virtual bool UnsyncTouch(const TouchInput &touch) = 0;
// Return value of UnsyncKey is used to not block certain system keys like volume when unhandled, on Android.
virtual void UnsyncKey(const KeyInput &touch) = 0;
virtual void UnsyncAxis(const AxisInput *axes, size_t count) = 0;
virtual bool touch(const TouchInput &touch) = 0;
virtual bool key(const KeyInput &key) = 0;
virtual void axis(const AxisInput &axis) = 0;
virtual void RecreateViews() {}
@@ -208,7 +222,6 @@ public:
InputMode PassInputToMapper() const {
return passInputToMapper_;
}
std::recursive_mutex inputLock_;
private:
@@ -243,5 +256,8 @@ private:
std::unordered_map<int64_t, int> lastAxis_;
std::mutex eventQueueLock_;
std::deque<QueuedEvent> eventQueue_;
InputMode passInputToMapper_ = InputMode::None;
};
+2 -63
View File
@@ -66,7 +66,7 @@ void UIScreen::DoRecreateViews() {
WipeRequesterToken();
}
void UIScreen::touch(const TouchInput &touch) {
bool UIScreen::touch(const TouchInput &touch) {
if (ClickDebug && root_ && (touch.flags & TouchInputFlags::DOWN)) {
INFO_LOG(Log::System, "Touch down!");
std::vector<UI::View *> views;
@@ -79,6 +79,7 @@ void UIScreen::touch(const TouchInput &touch) {
if (!ignoreInput_ && root_) {
UI::TouchEvent(touch, root_);
}
return true;
}
void UIScreen::axis(const AxisInput &axis) {
@@ -95,33 +96,6 @@ bool UIScreen::key(const KeyInput &key) {
}
}
bool UIScreen::UnsyncTouch(const TouchInput &touch) {
QueuedEvent ev{};
ev.type = QueuedEventType::TOUCH;
ev.touch = touch;
std::lock_guard<std::mutex> guard(eventQueueLock_);
eventQueue_.push_back(ev);
return false;
}
void UIScreen::UnsyncAxis(const AxisInput *axes, size_t count) {
QueuedEvent ev{};
ev.type = QueuedEventType::AXIS;
std::lock_guard<std::mutex> guard(eventQueueLock_);
for (size_t i = 0; i < count; i++) {
ev.axis = axes[i];
eventQueue_.push_back(ev);
}
}
void UIScreen::UnsyncKey(const KeyInput &key) {
QueuedEvent ev{};
ev.type = QueuedEventType::KEY;
ev.key = key;
std::lock_guard<std::mutex> guard(eventQueueLock_);
eventQueue_.push_back(ev);
}
void UIScreen::update() {
DeviceOrientation orientation = GetDeviceOrientation();
if (orientation != lastOrientation_) {
@@ -131,41 +105,6 @@ void UIScreen::update() {
DoRecreateViews();
while (true) {
QueuedEvent ev{};
{
std::lock_guard<std::mutex> guard(eventQueueLock_);
if (!eventQueue_.empty()) {
ev = eventQueue_.front();
eventQueue_.pop_front();
} else {
break;
}
}
if (ignoreInput_) {
continue;
}
switch (ev.type) {
case QueuedEventType::KEY:
key(ev.key);
break;
case QueuedEventType::TOUCH:
if (ClickDebug && (ev.touch.flags & TouchInputFlags::DOWN)) {
INFO_LOG(Log::System, "Touch down!");
std::vector<UI::View *> views;
root_->Query(ev.touch.x, ev.touch.y, views);
for (auto view : views) {
INFO_LOG(Log::System, "%s", view->DescribeLog().c_str());
}
}
touch(ev.touch);
break;
case QueuedEventType::AXIS:
axis(ev.axis);
break;
}
}
if (root_) {
DialogResult result = UpdateViewHierarchy(root_);
if (result != DR_NONE) {
+3 -26
View File
@@ -17,21 +17,6 @@ namespace Draw {
class DrawContext;
}
enum class QueuedEventType : u8 {
KEY,
AXIS,
TOUCH,
};
struct QueuedEvent {
QueuedEventType type;
union {
TouchInput touch;
KeyInput key;
AxisInput axis;
};
};
class UIScreen : public Screen {
public:
UIScreen();
@@ -42,13 +27,9 @@ public:
void deviceLost() override;
void deviceRestored(Draw::DrawContext *draw) override;
virtual void touch(const TouchInput &touch);
virtual bool key(const KeyInput &key);
virtual void axis(const AxisInput &axis);
bool UnsyncTouch(const TouchInput &touch) override;
void UnsyncKey(const KeyInput &key) override;
void UnsyncAxis(const AxisInput *axes, size_t count) override;
bool touch(const TouchInput &touch) override;
bool key(const KeyInput &key) override;
void axis(const AxisInput &axis) override;
TouchInput transformTouch(const TouchInput &touch) override;
@@ -92,10 +73,6 @@ protected:
bool recreateViews_ = true;
DeviceOrientation lastOrientation_ = DeviceOrientation::Landscape;
private:
std::mutex eventQueueLock_;
std::deque<QueuedEvent> eventQueue_;
};
class UIDialogScreen : public UIScreen {
+1 -1
View File
@@ -615,7 +615,7 @@ static void load_integration_callback(int result, const char *error_message, rc_
}
case RC_MISSING_VALUE:
// This is fine, proceeding to login.
g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("RAIntegration is enabled, but %1 was not found."));
g_OSD.Show(OSDType::MESSAGE_WARNING, ApplySafeSubstitutions(ac->T("RAIntegration is enabled, but %1 was not found."), RAINTEGRATION_FILENAME));
break;
case RC_ABORTED:
// This is fine(-ish), proceeding to login.
+2 -1
View File
@@ -629,7 +629,7 @@ void FrameDumpTestScreen::update() {
}
}
void TouchTestScreen::touch(const TouchInput &touch) {
bool TouchTestScreen::touch(const TouchInput &touch) {
UIBaseDialogScreen::touch(touch);
if (touch.flags & TouchInputFlags::DOWN) {
bool found = false;
@@ -678,6 +678,7 @@ void TouchTestScreen::touch(const TouchInput &touch) {
WARN_LOG(Log::System, "Touch release without touch down");
}
}
return true;
}
// TODO: Move this screen out into its own file.
+1 -1
View File
@@ -169,7 +169,7 @@ public:
}
}
void touch(const TouchInput &touch) override;
bool touch(const TouchInput &touch) override;
void DrawForeground(UIContext &dc) override;
bool key(const KeyInput &key) override;
+4 -3
View File
@@ -1212,7 +1212,7 @@ bool EmuScreen::key(const KeyInput &key) {
return retval;
}
void EmuScreen::touch(const TouchInput &touch) {
bool EmuScreen::touch(const TouchInput &touch) {
System_Notify(SystemNotification::ACTIVITY);
bool ignoreGamepad = false;
@@ -1234,7 +1234,7 @@ void EmuScreen::touch(const TouchInput &touch) {
if (g_Config.bShowImDebugger && imguiInited_) {
ImGui_ImplPlatform_TouchEvent(touch);
if (!ImGui::GetIO().WantCaptureMouse) {
UIScreen::touch(touch);
return UIScreen::touch(touch);
}
} else if (g_Config.bMouseControl && !(touch.flags & TouchInputFlags::UP) && (touch.flags & TouchInputFlags::MOUSE)) {
// don't do anything as the mouse pointer is hidden in this case.
@@ -1252,8 +1252,9 @@ void EmuScreen::touch(const TouchInput &touch) {
}
}
}
UIScreen::touch(touch);
return UIScreen::touch(touch);
}
return false;
}
// TODO: Shouldn't actually need bounds for this, Anchor can center too.
+1 -1
View File
@@ -56,7 +56,7 @@ public:
// We also need to do some special handling of queued UI events to handle closing the chat window.
bool key(const KeyInput &key) override;
void touch(const TouchInput &key) override;
bool touch(const TouchInput &key) override;
void deviceLost() override;
void deviceRestored(Draw::DrawContext *draw) override;
+3 -1
View File
@@ -419,10 +419,12 @@ bool LogoScreen::key(const KeyInput &key) {
return false;
}
void LogoScreen::touch(const TouchInput &touch) {
bool LogoScreen::touch(const TouchInput &touch) {
if (touch.flags & TouchInputFlags::DOWN) {
Next();
return true;
}
return false;
}
void LogoScreen::DrawForeground(UIContext &dc) {
+1 -1
View File
@@ -101,7 +101,7 @@ public:
LogoScreen(AfterLogoScreen afterLogoScreen = AfterLogoScreen::DEFAULT);
bool key(const KeyInput &key) override;
void touch(const TouchInput &touch) override;
bool touch(const TouchInput &touch) override;
void update() override;
void DrawForeground(UIContext &ui) override;
void sendMessage(UIMessage message, const char *value) override;
+10 -10
View File
@@ -1478,6 +1478,16 @@ bool NativeKey(const KeyInput &key) {
g_controlMapper.Key(key);
}
// Ignore volume keys and stuff here - though we do send them through to the control mapper, so they can be mapped to PSP buttons.
switch (key.keyCode) {
case NKCODE_VOLUME_DOWN:
case NKCODE_VOLUME_UP:
case NKCODE_VOLUME_MUTE:
return false;
default:
break;
}
// Track modifier keys.
if (key.flags & KeyInputFlags::DOWN) {
switch (key.keyCode) {
@@ -1526,16 +1536,6 @@ bool NativeKey(const KeyInput &key) {
KeyInput modKey = key;
modKey.flags |= modifierFlags;
// 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:
return false;
default:
break;
}
bool retval = false;
UI::KeyEventResult kev = UI::KeyEventToFocusMoves(key);
+1 -1
View File
@@ -389,7 +389,7 @@ bool OnScreenMessagesView::Dismiss(float x, float y) {
return dismissed;
}
bool OSDOverlayScreen::UnsyncTouch(const TouchInput &touch) {
bool OSDOverlayScreen::touch(const TouchInput &touch) {
// Don't really need to forward.
// UIScreen::UnsyncTouch(touch);
if ((touch.flags & TouchInputFlags::DOWN) && osmView_) {
+1 -1
View File
@@ -38,7 +38,7 @@ class OSDOverlayScreen : public UIScreen {
public:
const char *tag() const override { return "OSDOverlayScreen"; }
bool UnsyncTouch(const TouchInput &touch) override;
bool touch(const TouchInput &touch) override;
void CreateViews() override;
void DrawForeground(UIContext &ui) override;