summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hid_core/resource_manager.cpp88
-rw-r--r--src/hid_core/resource_manager.h9
-rw-r--r--src/hid_core/resources/digitizer/digitizer.cpp4
-rw-r--r--src/hid_core/resources/digitizer/digitizer.h3
-rw-r--r--src/hid_core/resources/npad/npad.cpp18
-rw-r--r--src/hid_core/resources/npad/npad.h1
-rw-r--r--src/hid_core/resources/unique_pad/unique_pad.cpp4
-rw-r--r--src/hid_core/resources/unique_pad/unique_pad.h3
-rw-r--r--src/yuzu/main.cpp7
-rw-r--r--src/yuzu/multiplayer/lobby.cpp13
-rw-r--r--src/yuzu/multiplayer/lobby_p.h25
-rw-r--r--src/yuzu/uisettings.h14
12 files changed, 117 insertions, 72 deletions
diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp
index 68ce2c7ae..245da582e 100644
--- a/src/hid_core/resource_manager.cpp
+++ b/src/hid_core/resource_manager.cpp
@@ -52,9 +52,42 @@ ResourceManager::ResourceManager(Core::System& system_,
52 std::shared_ptr<HidFirmwareSettings> settings) 52 std::shared_ptr<HidFirmwareSettings> settings)
53 : firmware_settings{settings}, system{system_}, service_context{system_, "hid"} { 53 : firmware_settings{settings}, system{system_}, service_context{system_, "hid"} {
54 applet_resource = std::make_shared<AppletResource>(system); 54 applet_resource = std::make_shared<AppletResource>(system);
55
56 // Register update callbacks
57 npad_update_event = Core::Timing::CreateEvent("HID::UpdatePadCallback",
58 [this](s64 time, std::chrono::nanoseconds ns_late)
59 -> std::optional<std::chrono::nanoseconds> {
60 UpdateNpad(ns_late);
61 return std::nullopt;
62 });
63 default_update_event = Core::Timing::CreateEvent(
64 "HID::UpdateDefaultCallback",
65 [this](s64 time,
66 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
67 UpdateControllers(ns_late);
68 return std::nullopt;
69 });
70 mouse_keyboard_update_event = Core::Timing::CreateEvent(
71 "HID::UpdateMouseKeyboardCallback",
72 [this](s64 time,
73 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
74 UpdateMouseKeyboard(ns_late);
75 return std::nullopt;
76 });
77 motion_update_event = Core::Timing::CreateEvent(
78 "HID::UpdateMotionCallback",
79 [this](s64 time,
80 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
81 UpdateMotion(ns_late);
82 return std::nullopt;
83 });
55} 84}
56 85
57ResourceManager::~ResourceManager() { 86ResourceManager::~ResourceManager() {
87 system.CoreTiming().UnscheduleEvent(npad_update_event);
88 system.CoreTiming().UnscheduleEvent(default_update_event);
89 system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event);
90 system.CoreTiming().UnscheduleEvent(motion_update_event);
58 system.CoreTiming().UnscheduleEvent(touch_update_event); 91 system.CoreTiming().UnscheduleEvent(touch_update_event);
59 input_event->Finalize(); 92 input_event->Finalize();
60}; 93};
@@ -201,6 +234,7 @@ void ResourceManager::InitializeHidCommonSampler() {
201 234
202 debug_pad->SetAppletResource(applet_resource, &shared_mutex); 235 debug_pad->SetAppletResource(applet_resource, &shared_mutex);
203 digitizer->SetAppletResource(applet_resource, &shared_mutex); 236 digitizer->SetAppletResource(applet_resource, &shared_mutex);
237 unique_pad->SetAppletResource(applet_resource, &shared_mutex);
204 keyboard->SetAppletResource(applet_resource, &shared_mutex); 238 keyboard->SetAppletResource(applet_resource, &shared_mutex);
205 239
206 const auto settings = 240 const auto settings =
@@ -214,6 +248,14 @@ void ResourceManager::InitializeHidCommonSampler() {
214 home_button->SetAppletResource(applet_resource, &shared_mutex); 248 home_button->SetAppletResource(applet_resource, &shared_mutex);
215 sleep_button->SetAppletResource(applet_resource, &shared_mutex); 249 sleep_button->SetAppletResource(applet_resource, &shared_mutex);
216 capture_button->SetAppletResource(applet_resource, &shared_mutex); 250 capture_button->SetAppletResource(applet_resource, &shared_mutex);
251
252 system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
253 system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
254 default_update_event);
255 system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
256 mouse_keyboard_update_event);
257 system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
258 motion_update_event);
217} 259}
218 260
219void ResourceManager::InitializeTouchScreenSampler() { 261void ResourceManager::InitializeTouchScreenSampler() {
@@ -465,55 +507,9 @@ IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<Resource
465 {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, 507 {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
466 }; 508 };
467 RegisterHandlers(functions); 509 RegisterHandlers(functions);
468
469 // Register update callbacks
470 npad_update_event = Core::Timing::CreateEvent(
471 "HID::UpdatePadCallback",
472 [this, resource](
473 s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
474 const auto guard = LockService();
475 resource->UpdateNpad(ns_late);
476 return std::nullopt;
477 });
478 default_update_event = Core::Timing::CreateEvent(
479 "HID::UpdateDefaultCallback",
480 [this, resource](
481 s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
482 const auto guard = LockService();
483 resource->UpdateControllers(ns_late);
484 return std::nullopt;
485 });
486 mouse_keyboard_update_event = Core::Timing::CreateEvent(
487 "HID::UpdateMouseKeyboardCallback",
488 [this, resource](
489 s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
490 const auto guard = LockService();
491 resource->UpdateMouseKeyboard(ns_late);
492 return std::nullopt;
493 });
494 motion_update_event = Core::Timing::CreateEvent(
495 "HID::UpdateMotionCallback",
496 [this, resource](
497 s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
498 const auto guard = LockService();
499 resource->UpdateMotion(ns_late);
500 return std::nullopt;
501 });
502
503 system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
504 system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
505 default_update_event);
506 system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
507 mouse_keyboard_update_event);
508 system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
509 motion_update_event);
510} 510}
511 511
512IAppletResource::~IAppletResource() { 512IAppletResource::~IAppletResource() {
513 system.CoreTiming().UnscheduleEvent(npad_update_event);
514 system.CoreTiming().UnscheduleEvent(default_update_event);
515 system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event);
516 system.CoreTiming().UnscheduleEvent(motion_update_event);
517 resource_manager->FreeAppletResourceId(aruid); 513 resource_manager->FreeAppletResourceId(aruid);
518} 514}
519 515
diff --git a/src/hid_core/resource_manager.h b/src/hid_core/resource_manager.h
index 0bfe09511..dc3ff01f8 100644
--- a/src/hid_core/resource_manager.h
+++ b/src/hid_core/resource_manager.h
@@ -147,6 +147,10 @@ private:
147 std::shared_ptr<SixAxis> six_axis{nullptr}; 147 std::shared_ptr<SixAxis> six_axis{nullptr};
148 std::shared_ptr<SleepButton> sleep_button{nullptr}; 148 std::shared_ptr<SleepButton> sleep_button{nullptr};
149 std::shared_ptr<UniquePad> unique_pad{nullptr}; 149 std::shared_ptr<UniquePad> unique_pad{nullptr};
150 std::shared_ptr<Core::Timing::EventType> npad_update_event;
151 std::shared_ptr<Core::Timing::EventType> default_update_event;
152 std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
153 std::shared_ptr<Core::Timing::EventType> motion_update_event;
150 154
151 // TODO: Create these resources 155 // TODO: Create these resources
152 // std::shared_ptr<AudioControl> audio_control{nullptr}; 156 // std::shared_ptr<AudioControl> audio_control{nullptr};
@@ -179,11 +183,6 @@ public:
179private: 183private:
180 void GetSharedMemoryHandle(HLERequestContext& ctx); 184 void GetSharedMemoryHandle(HLERequestContext& ctx);
181 185
182 std::shared_ptr<Core::Timing::EventType> npad_update_event{nullptr};
183 std::shared_ptr<Core::Timing::EventType> default_update_event{nullptr};
184 std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event{nullptr};
185 std::shared_ptr<Core::Timing::EventType> motion_update_event{nullptr};
186
187 u64 aruid{}; 186 u64 aruid{};
188 std::shared_ptr<ResourceManager> resource_manager; 187 std::shared_ptr<ResourceManager> resource_manager;
189}; 188};
diff --git a/src/hid_core/resources/digitizer/digitizer.cpp b/src/hid_core/resources/digitizer/digitizer.cpp
index cd72fd6e5..5d7dcadfe 100644
--- a/src/hid_core/resources/digitizer/digitizer.cpp
+++ b/src/hid_core/resources/digitizer/digitizer.cpp
@@ -17,10 +17,6 @@ void Digitizer::OnInit() {}
17void Digitizer::OnRelease() {} 17void Digitizer::OnRelease() {}
18 18
19void Digitizer::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 19void Digitizer::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
20 if (!smart_update) {
21 return;
22 }
23
24 std::scoped_lock shared_lock{*shared_mutex}; 20 std::scoped_lock shared_lock{*shared_mutex};
25 const u64 aruid = applet_resource->GetActiveAruid(); 21 const u64 aruid = applet_resource->GetActiveAruid();
26 auto* data = applet_resource->GetAruidData(aruid); 22 auto* data = applet_resource->GetAruidData(aruid);
diff --git a/src/hid_core/resources/digitizer/digitizer.h b/src/hid_core/resources/digitizer/digitizer.h
index e031a16b0..68b03111c 100644
--- a/src/hid_core/resources/digitizer/digitizer.h
+++ b/src/hid_core/resources/digitizer/digitizer.h
@@ -20,8 +20,5 @@ public:
20 20
21 // When the controller is requesting an update for the shared memory 21 // When the controller is requesting an update for the shared memory
22 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 22 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
23
24private:
25 bool smart_update{};
26}; 23};
27} // namespace Service::HID 24} // namespace Service::HID
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp
index 1a58eff4a..fe3fdc5cd 100644
--- a/src/hid_core/resources/npad/npad.cpp
+++ b/src/hid_core/resources/npad/npad.cpp
@@ -102,6 +102,8 @@ Result NPad::Activate(u64 aruid) {
102 for (std::size_t i = 0; i < 19; ++i) { 102 for (std::size_t i = 0; i < 19; ++i) {
103 WriteEmptyEntry(npad); 103 WriteEmptyEntry(npad);
104 } 104 }
105
106 controller.is_active = true;
105 } 107 }
106 108
107 return ResultSuccess; 109 return ResultSuccess;
@@ -467,6 +469,13 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
467 continue; 469 continue;
468 } 470 }
469 471
472 bool is_set{};
473 npad_resource.IsSupportedNpadStyleSet(is_set, aruid);
474 // Wait until style is defined
475 if (!is_set) {
476 continue;
477 }
478
470 for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { 479 for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
471 auto& controller = controller_data[aruid_index][i]; 480 auto& controller = controller_data[aruid_index][i];
472 controller.shared_memory = 481 controller.shared_memory =
@@ -484,6 +493,10 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
484 continue; 493 continue;
485 } 494 }
486 495
496 if (!controller.is_active) {
497 continue;
498 }
499
487 RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); 500 RequestPadStateUpdate(aruid, controller.device->GetNpadIdType());
488 auto& pad_state = controller.npad_pad_state; 501 auto& pad_state = controller.npad_pad_state;
489 auto& libnx_state = controller.npad_libnx_state; 502 auto& libnx_state = controller.npad_libnx_state;
@@ -592,7 +605,9 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
592 libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw; 605 libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;
593 libnx_state.l_stick = pad_state.l_stick; 606 libnx_state.l_stick = pad_state.l_stick;
594 libnx_state.r_stick = pad_state.r_stick; 607 libnx_state.r_stick = pad_state.r_stick;
595 npad->system_ext_lifo.WriteNextEntry(pad_state); 608 libnx_state.sampling_number =
609 npad->system_ext_lifo.ReadCurrentEntry().state.sampling_number + 1;
610 npad->system_ext_lifo.WriteNextEntry(libnx_state);
596 611
597 press_state |= static_cast<u64>(pad_state.npad_buttons.raw); 612 press_state |= static_cast<u64>(pad_state.npad_buttons.raw);
598 } 613 }
@@ -1060,6 +1075,7 @@ void NPad::UnregisterAppletResourceUserId(u64 aruid) {
1060 // TODO: Remove this once abstract pad is emulated properly 1075 // TODO: Remove this once abstract pad is emulated properly
1061 const auto aruid_index = npad_resource.GetIndexFromAruid(aruid); 1076 const auto aruid_index = npad_resource.GetIndexFromAruid(aruid);
1062 for (auto& controller : controller_data[aruid_index]) { 1077 for (auto& controller : controller_data[aruid_index]) {
1078 controller.is_active = false;
1063 controller.is_connected = false; 1079 controller.is_connected = false;
1064 controller.shared_memory = nullptr; 1080 controller.shared_memory = nullptr;
1065 } 1081 }
diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h
index 4e26ed2e8..c63488346 100644
--- a/src/hid_core/resources/npad/npad.h
+++ b/src/hid_core/resources/npad/npad.h
@@ -164,6 +164,7 @@ private:
164 NpadInternalState* shared_memory = nullptr; 164 NpadInternalState* shared_memory = nullptr;
165 Core::HID::EmulatedController* device = nullptr; 165 Core::HID::EmulatedController* device = nullptr;
166 166
167 bool is_active{};
167 bool is_connected{}; 168 bool is_connected{};
168 169
169 // Dual joycons can have only one side connected 170 // Dual joycons can have only one side connected
diff --git a/src/hid_core/resources/unique_pad/unique_pad.cpp b/src/hid_core/resources/unique_pad/unique_pad.cpp
index 89fc57269..b2db55c5a 100644
--- a/src/hid_core/resources/unique_pad/unique_pad.cpp
+++ b/src/hid_core/resources/unique_pad/unique_pad.cpp
@@ -17,10 +17,6 @@ void UniquePad::OnInit() {}
17void UniquePad::OnRelease() {} 17void UniquePad::OnRelease() {}
18 18
19void UniquePad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 19void UniquePad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
20 if (!smart_update) {
21 return;
22 }
23
24 const u64 aruid = applet_resource->GetActiveAruid(); 20 const u64 aruid = applet_resource->GetActiveAruid();
25 auto* data = applet_resource->GetAruidData(aruid); 21 auto* data = applet_resource->GetAruidData(aruid);
26 22
diff --git a/src/hid_core/resources/unique_pad/unique_pad.h b/src/hid_core/resources/unique_pad/unique_pad.h
index 674ad1691..4873b7f7e 100644
--- a/src/hid_core/resources/unique_pad/unique_pad.h
+++ b/src/hid_core/resources/unique_pad/unique_pad.h
@@ -20,8 +20,5 @@ public:
20 20
21 // When the controller is requesting an update for the shared memory 21 // When the controller is requesting an update for the shared memory
22 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 22 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
23
24private:
25 bool smart_update{};
26}; 23};
27} // namespace Service::HID 24} // namespace Service::HID
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 303d84a1f..13381fea8 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1353,6 +1353,13 @@ void GMainWindow::InitializeHotkeys() {
1353 LinkActionShortcut(ui->action_TAS_Start, QStringLiteral("TAS Start/Stop"), true); 1353 LinkActionShortcut(ui->action_TAS_Start, QStringLiteral("TAS Start/Stop"), true);
1354 LinkActionShortcut(ui->action_TAS_Record, QStringLiteral("TAS Record"), true); 1354 LinkActionShortcut(ui->action_TAS_Record, QStringLiteral("TAS Record"), true);
1355 LinkActionShortcut(ui->action_TAS_Reset, QStringLiteral("TAS Reset"), true); 1355 LinkActionShortcut(ui->action_TAS_Reset, QStringLiteral("TAS Reset"), true);
1356 LinkActionShortcut(ui->action_View_Lobby,
1357 QStringLiteral("Multiplayer Browse Public Game Lobby"));
1358 LinkActionShortcut(ui->action_Start_Room, QStringLiteral("Multiplayer Create Room"));
1359 LinkActionShortcut(ui->action_Connect_To_Room,
1360 QStringLiteral("Multiplayer Direct Connect to Room"));
1361 LinkActionShortcut(ui->action_Show_Room, QStringLiteral("Multiplayer Show Current Room"));
1362 LinkActionShortcut(ui->action_Leave_Room, QStringLiteral("Multiplayer Leave Room"));
1356 1363
1357 static const QString main_window = QStringLiteral("Main Window"); 1364 static const QString main_window = QStringLiteral("Main Window");
1358 const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) { 1365 const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) {
diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp
index 41692c05b..77ac84295 100644
--- a/src/yuzu/multiplayer/lobby.cpp
+++ b/src/yuzu/multiplayer/lobby.cpp
@@ -77,16 +77,23 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
77 77
78 // UI Buttons 78 // UI Buttons
79 connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby); 79 connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby);
80 connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch);
80 connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned); 81 connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned);
81 connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty); 82 connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty);
82 connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull); 83 connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull);
83 connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch);
84 connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom); 84 connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom);
85 connect(ui->room_list, &QTreeView::clicked, this, &Lobby::OnExpandRoom); 85 connect(ui->room_list, &QTreeView::clicked, this, &Lobby::OnExpandRoom);
86 86
87 // Actions 87 // Actions
88 connect(&room_list_watcher, &QFutureWatcher<AnnounceMultiplayerRoom::RoomList>::finished, this, 88 connect(&room_list_watcher, &QFutureWatcher<AnnounceMultiplayerRoom::RoomList>::finished, this,
89 &Lobby::OnRefreshLobby); 89 &Lobby::OnRefreshLobby);
90
91 // Load persistent filters after events are connected to make sure they apply
92 ui->search->setText(
93 QString::fromStdString(UISettings::values.multiplayer_filter_text.GetValue()));
94 ui->games_owned->setChecked(UISettings::values.multiplayer_filter_games_owned.GetValue());
95 ui->hide_empty->setChecked(UISettings::values.multiplayer_filter_hide_empty.GetValue());
96 ui->hide_full->setChecked(UISettings::values.multiplayer_filter_hide_full.GetValue());
90} 97}
91 98
92Lobby::~Lobby() = default; 99Lobby::~Lobby() = default;
@@ -204,6 +211,10 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
204 211
205 // Save settings 212 // Save settings
206 UISettings::values.multiplayer_nickname = ui->nickname->text().toStdString(); 213 UISettings::values.multiplayer_nickname = ui->nickname->text().toStdString();
214 UISettings::values.multiplayer_filter_text = ui->search->text().toStdString();
215 UISettings::values.multiplayer_filter_games_owned = ui->games_owned->isChecked();
216 UISettings::values.multiplayer_filter_hide_empty = ui->hide_empty->isChecked();
217 UISettings::values.multiplayer_filter_hide_full = ui->hide_full->isChecked();
207 UISettings::values.multiplayer_ip = 218 UISettings::values.multiplayer_ip =
208 proxy->data(connection_index, LobbyItemHost::HostIPRole).value<QString>().toStdString(); 219 proxy->data(connection_index, LobbyItemHost::HostIPRole).value<QString>().toStdString();
209 UISettings::values.multiplayer_port = 220 UISettings::values.multiplayer_port =
diff --git a/src/yuzu/multiplayer/lobby_p.h b/src/yuzu/multiplayer/lobby_p.h
index 068c95aca..398833e7a 100644
--- a/src/yuzu/multiplayer/lobby_p.h
+++ b/src/yuzu/multiplayer/lobby_p.h
@@ -193,12 +193,29 @@ public:
193 } 193 }
194 194
195 QVariant data(int role) const override { 195 QVariant data(int role) const override {
196 if (role != Qt::DisplayRole) { 196 switch (role) {
197 case Qt::DisplayRole: {
198 auto members = data(MemberListRole).toList();
199 return QStringLiteral("%1 / %2 ")
200 .arg(QString::number(members.size()), data(MaxPlayerRole).toString());
201 }
202 case Qt::ForegroundRole: {
203 auto members = data(MemberListRole).toList();
204 auto max_players = data(MaxPlayerRole).toInt();
205 if (members.size() >= max_players) {
206 return QBrush(QColor(255, 48, 32));
207 } else if (members.size() == (max_players - 1)) {
208 return QBrush(QColor(255, 140, 32));
209 } else if (members.size() == 0) {
210 return QBrush(QColor(128, 128, 128));
211 }
212 // FIXME: How to return a value that tells Qt not to modify the
213 // text color from the default (as if Qt::ForegroundRole wasn't overridden)?
214 return QBrush(nullptr);
215 }
216 default:
197 return LobbyItem::data(role); 217 return LobbyItem::data(role);
198 } 218 }
199 auto members = data(MemberListRole).toList();
200 return QStringLiteral("%1 / %2 ")
201 .arg(QString::number(members.size()), data(MaxPlayerRole).toString());
202 } 219 }
203 220
204 bool operator<(const QStandardItem& other) const override { 221 bool operator<(const QStandardItem& other) const override {
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index f9906be33..03e42b930 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -169,6 +169,13 @@ struct Values {
169 169
170 // multiplayer settings 170 // multiplayer settings
171 Setting<std::string> multiplayer_nickname{linkage, {}, "nickname", Category::Multiplayer}; 171 Setting<std::string> multiplayer_nickname{linkage, {}, "nickname", Category::Multiplayer};
172 Setting<std::string> multiplayer_filter_text{linkage, {}, "filter_text", Category::Multiplayer};
173 Setting<bool> multiplayer_filter_games_owned{linkage, false, "filter_games_owned",
174 Category::Multiplayer};
175 Setting<bool> multiplayer_filter_hide_empty{linkage, false, "filter_games_hide_empty",
176 Category::Multiplayer};
177 Setting<bool> multiplayer_filter_hide_full{linkage, false, "filter_games_hide_full",
178 Category::Multiplayer};
172 Setting<std::string> multiplayer_ip{linkage, {}, "ip", Category::Multiplayer}; 179 Setting<std::string> multiplayer_ip{linkage, {}, "ip", Category::Multiplayer};
173 Setting<u16, true> multiplayer_port{linkage, 24872, 0, 180 Setting<u16, true> multiplayer_port{linkage, 24872, 0,
174 UINT16_MAX, "port", Category::Multiplayer}; 181 UINT16_MAX, "port", Category::Multiplayer};
@@ -222,7 +229,7 @@ void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig);
222// This must be in alphabetical order according to action name as it must have the same order as 229// This must be in alphabetical order according to action name as it must have the same order as
223// UISetting::values.shortcuts, which is alphabetically ordered. 230// UISetting::values.shortcuts, which is alphabetically ordered.
224// clang-format off 231// clang-format off
225const std::array<Shortcut, 23> default_hotkeys{{ 232const std::array<Shortcut, 28> default_hotkeys{{
226 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}}, 233 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}},
227 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}}, 234 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
228 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}}, 235 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
@@ -236,6 +243,11 @@ const std::array<Shortcut, 23> default_hotkeys{{
236 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}}, 243 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}},
237 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}}, 244 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}},
238 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}}, 245 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
246 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Browse Public Game Lobby")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+B"), std::string(""), Qt::ApplicationShortcut, false}},
247 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Create Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+N"), std::string(""), Qt::ApplicationShortcut, false}},
248 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Direct Connect to Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+C"), std::string(""), Qt::ApplicationShortcut, false}},
249 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Leave Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+L"), std::string(""), Qt::ApplicationShortcut, false}},
250 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Show Current Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+R"), std::string(""), Qt::ApplicationShortcut, false}},
239 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}}, 251 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}},
240 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}}, 252 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}},
241 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}}, 253 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}},