Merge pull request #21444 from hrydgard/more-fixes

Add keyboard control for the new adhoc server list
This commit is contained in:
Henrik Rydgård
2026-03-15 15:47:55 +01:00
committed by GitHub
8 changed files with 96 additions and 38 deletions
+30
View File
@@ -1201,6 +1201,36 @@ bool ClickableTextView::Touch(const TouchInput &input) {
return contains;
}
bool ClickableTextView::Key(const KeyInput &key) {
if (!HasFocus() && key.deviceId != DEVICE_ID_MOUSE) {
down_ = false;
return false;
}
// TODO: Replace most of Update with this.
bool ret = false;
if (key.flags & KeyInputFlags::DOWN) {
if (IsAcceptKey(key)) {
down_ = true;
ret = true;
}
}
if (key.flags & KeyInputFlags::UP) {
if (IsAcceptKey(key)) {
if (down_) {
EventParams e{};
e.v = this;
OnClick.Trigger(e);
down_ = false;
ret = true;
}
} else if (down_ && IsEscapeKey(key)) {
down_ = false;
}
}
return ret;
}
TextEdit::TextEdit(std::string_view text, std::string_view title, std::string_view placeholderText, LayoutParams *layoutParams)
: View(layoutParams), text_(text), title_(title), undo_(text), placeholderText_(placeholderText),
textColor_(0xFFFFFFFF), maxLen_(255) {
+2
View File
@@ -1086,6 +1086,8 @@ public:
ClickableTextView(std::string_view text, LayoutParams *layoutParams = 0)
: TextView(text, layoutParams) {}
bool Touch(const TouchInput &input) override;
bool Key(const KeyInput &input) override;
Event OnClick;
private:
+46 -27
View File
@@ -191,6 +191,26 @@ private:
AdhocServerListEntry entry_;
};
void AddDeleteButton(std::string *editValue, ScreenManager *screenManager, UI::ViewGroup *viewGroup, const AdhocServerListEntry &entry) {
using namespace UI;
Choice *deleteButton = viewGroup->Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity::G_VCENTER, Margins(0, 0, 10, 0))));
deleteButton->OnClick.Add([host = entry.host, screenManager, editValue](UI::EventParams &e) {
auto di = GetI18NCategory(I18NCat::DIALOG);
const std::string quotedHost = "\"" + host + "\"";
const std::string message = ApplySafeSubstitutions(di->T("Are you sure you want to delete %1?"), quotedHost);
screenManager->push(new UI::MessagePopupScreen(di->T("Delete"), message, di->T("Delete"), di->T("Cancel"), [host, editValue](bool confirmed) {
if (confirmed) {
RemoveNoCase(g_Config.vCustomAdhocServerList, host);
RemoveNoCase(g_Config.vCustomAdhocServerListWithRelay, host);
if (*editValue == host) {
// Reset to socom.cc, which will always be in a list.
*editValue = DefaultProAdhocServer();
}
}
}));
});
}
AdhocServerRow::AdhocServerRow(std::string *editValue, const AdhocServerListEntry &entry, bool showDeleteButton, ScreenManager *screenManager, UI::LayoutParams *layoutParams)
: UI::LinearLayout(ORIENT_HORIZONTAL, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT, UI::Margins(5.0f, 0.0f))), value_(editValue), entry_(entry) {
using namespace UI;
@@ -203,7 +223,13 @@ AdhocServerRow::AdhocServerRow(std::string *editValue, const AdhocServerListEntr
LinearLayout *lines = Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(Margins(5, 5))));
lines->SetSpacing(0.0f);
lines->Add(new TextView(entry.name));
ClickableTextView *name = lines->Add(new ClickableTextView(entry.name));
name->SetFocusable(true);
name->OnClick.Add([this](UI::EventParams &e) {
EventParams e2;
e2.v = this;
OnSelected.Trigger(e2);
});
std::string secondLine = entry.host;
if (entry.host == "localhost") {
@@ -223,22 +249,7 @@ AdhocServerRow::AdhocServerRow(std::string *editValue, const AdhocServerListEntr
TextView *relay = Add(new TextView("Relay", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity::G_VCENTER, Margins(10.0))));
}
if (showDeleteButton) {
Choice *deleteButton = Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity::G_VCENTER, Margins(0, 0, 10, 0))));
deleteButton->OnClick.Add([host = entry.host, screenManager, editValue](UI::EventParams &e) {
auto di = GetI18NCategory(I18NCat::DIALOG);
const std::string quotedHost = "\"" + host + "\"";
const std::string message = ApplySafeSubstitutions(di->T("Are you sure you want to delete %1?"), quotedHost);
screenManager->push(new UI::MessagePopupScreen(di->T("Delete"), message, di->T("Delete"), di->T("Cancel"), [host, editValue](bool confirmed) {
if (confirmed) {
RemoveNoCase(g_Config.vCustomAdhocServerList, host);
RemoveNoCase(g_Config.vCustomAdhocServerListWithRelay, host);
if (*editValue == host) {
// Reset to socom.cc, which will always be in a list.
*editValue = DefaultProAdhocServer();
}
}
}));
});
AddDeleteButton(editValue, screenManager, this, entry);
}
if (!entry.description.empty()) {
@@ -342,36 +353,44 @@ void AdhocServerScreen::CreatePopupContents(UI::ViewGroup *parent) {
return false;
};
for (const auto &host : g_Config.vCustomAdhocServerListWithRelay) {
for (auto iter = g_Config.vCustomAdhocServerListWithRelay.begin(); iter != g_Config.vCustomAdhocServerListWithRelay.end();) {
// If the host is already in the public list, skip it. We don't want duplicates.
if (hostInEntries(host) || host.empty()) {
if (hostInEntries(*iter) || iter->empty()) {
// Remove things that duplicate the public list, or that are empty (probably added by mistake).
iter = g_Config.vCustomAdhocServerListWithRelay.erase(iter);
recreateParent_ = true;
continue;
}
AdhocServerListEntry entry;
entry.name = host;
entry.host = host;
entry.name = *iter;
entry.host = *iter;
entry.mode = AdhocDataMode::AemuPostoffice;
customEntries.push_back(entry);
if (host == editValue_) {
if (*iter == editValue_) {
currentServerFound = true;
}
iter++;
}
for (const auto &host : g_Config.vCustomAdhocServerList) {
for (auto iter = g_Config.vCustomAdhocServerList.begin(); iter != g_Config.vCustomAdhocServerList.end();) {
// If the host is already in the public list, skip it. We don't want duplicates.
if (hostInEntries(host) || host.empty()) {
if (hostInEntries(*iter) || iter->empty()) {
// Remove things that duplicate the public list, or that are empty (probably added by mistake).
iter = g_Config.vCustomAdhocServerList.erase(iter);
recreateParent_ = true;
continue;
}
AdhocServerListEntry entry;
entry.name = host;
entry.host = host;
entry.name = *iter;
entry.host = *iter;
entry.mode = AdhocDataMode::P2P;
customEntries.push_back(entry);
if (host == editValue_) {
if (*iter == editValue_) {
currentServerFound = true;
}
iter++;
}
ScrollView *scrollView = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
+4
View File
@@ -38,6 +38,10 @@ protected:
void dialogFinished(const Screen *dialog, DialogResult result) override;
std::string_view GetTitle() const override;
ViewLayoutMode LayoutMode() const override {
return ViewLayoutMode::IgnoreBottomInset;
}
private:
void saveArray();
+4 -1
View File
@@ -824,7 +824,8 @@ void InitPadLayout(TouchControlConfig *config, DeviceOrientation orientation, fl
const float scale = globalScale;
const int halfW = xres / 2;
const float screenBottom = orientation == DeviceOrientation::Portrait ? (yres - yres * 0.13f) : yres;
const bool portrait = orientation == DeviceOrientation::Portrait;
const float screenBottom = portrait ? (yres - yres * 0.13f) : yres;
auto initTouchPos = [=](ConfigTouchPos *touch, float x, float y, float extraScale = 1.0f) {
if (touch->x == -1.0f || touch->y == -1.0f) {
@@ -863,6 +864,8 @@ void InitPadLayout(TouchControlConfig *config, DeviceOrientation orientation, fl
int Action_button_center_Y = screenBottom - Action_button_spacing * 2;
if (config->touchRightAnalogStick.show) {
Action_button_center_Y -= 150 * scale;
} else if (portrait) {
Action_button_center_Y -= 120 * scale;
}
initTouchPos(&config->touchActionButtonCenter, Action_button_center_X, Action_button_center_Y);
+3 -1
View File
@@ -41,7 +41,9 @@ protected:
void CreateViews() override;
void update() override;
UI::Margins RootMargins() const override;
ViewLayoutMode LayoutMode() const override {
return ViewLayoutMode::ApplyInsets;
}
// For processing of certain mapped keys.
bool UnsyncKey(const KeyInput &key) override;
void UnsyncAxis(const AxisInput *axes, size_t count) override;
+4 -4
View File
@@ -32,7 +32,7 @@ void UISimpleBaseDialogScreen::CreateViews() {
if (flags_ & SimpleDialogFlags::ContentsCanScroll) {
ScrollView *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f));
LinearLayout *contents = new LinearLayoutList(ORIENT_VERTICAL, new LinearLayoutParams(Margins(0, 0, 8, 0)));
LinearLayout *contents = new LinearLayoutList(ORIENT_VERTICAL, new LinearLayoutParams(Margins(0, 0, portrait ? 0 : 8, 0)));
contents->SetSpacing(0);
CreateDialogViews(contents);
scroll->Add(contents);
@@ -45,7 +45,7 @@ void UISimpleBaseDialogScreen::CreateViews() {
ViewLayoutMode UITwoPaneBaseDialogScreen::LayoutMode() const {
const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait;
if (portrait) {
if (flags_ & TwoPaneFlags::SettingsCanScroll) {
if ((flags_ & TwoPaneFlags::SettingsCanScroll) || (flags_ & TwoPaneFlags::ContentsCanScroll)) {
return ViewLayoutMode::IgnoreBottomInset;
} else {
return ViewLayoutMode::ApplyInsets;
@@ -111,9 +111,9 @@ void UITwoPaneBaseDialogScreen::CreateViews() {
if (!(flags_ & TwoPaneFlags::SettingsInContextMenu)) {
LinearLayout *settingsPane;
if (flags_ & TwoPaneFlags::SettingsCanScroll) {
settingsPane = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
settingsPane = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, Margins(8)));
settingsPane->SetSpacing(0.0f);
ScrollView *settingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f, Margins(8)));
ScrollView *settingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f));
settingsScroll->Add(settingsPane);
root->Add(settingsScroll);
} else {
+3 -5
View File
@@ -29,6 +29,7 @@
#include "UI/JoystickHistoryView.h"
#include "UI/GamepadEmu.h"
#include "UI/TiltAnalogSettingsScreen.h"
#include "UI/MiscViews.h"
const char *g_tiltTypes[] = { "None (Disabled)", "Analog Stick", "D-PAD", "PSP Action Buttons", "L/R Trigger Buttons" };
const size_t g_numTiltTypes = ARRAY_SIZE(g_tiltTypes);
@@ -113,15 +114,12 @@ void TiltAnalogSettingsScreen::CreateSettingsViews(UI::ViewGroup *settings) {
});
typeChoice->SetEnabledPtr(&g_Config.bTiltInputEnabled);
settings->Add(new ItemHeader(co->T("Calibration")));
TextView *calibrationInfo = new TextView(co->T("To Calibrate", "Hold device at your preferred angle and press Calibrate."));
calibrationInfo->SetSmall(true);
calibrationInfo->SetPadding(Margins(5));
calibrationInfo->SetAlign(FLAG_WRAP_TEXT);
settings->Add(calibrationInfo);
Choice *calibrate = new Choice(co->T("Calibrate"));
calibrate->OnClick.Handle(this, &TiltAnalogSettingsScreen::OnCalibrate);
calibrate->SetEnabledPtr(&g_Config.bTiltInputEnabled);
settings->Add(calibrate);
SettingHint *calibrationInfo = new SettingHint(co->T("To Calibrate", "Hold device at your preferred angle and press Calibrate."), calibrate);
settings->Add(calibrationInfo);
settings->Add(new ItemHeader(co->T("Sensitivity")));
if (g_Config.iTiltInputType == 1) {