summaryrefslogtreecommitdiff
path: root/src/core/hid/emulated_devices.cpp
diff options
context:
space:
mode:
authorGravatar Narr the Reg2024-01-04 20:37:43 -0600
committerGravatar Narr the Reg2024-01-05 11:41:15 -0600
commitee847f8ff0b1b0aec39c1b78c010bc0c08a0a613 (patch)
tree3b95cbb74be05f0ce7a007353f1f9f95e1ed3901 /src/core/hid/emulated_devices.cpp
parentMerge pull request #12437 from ameerj/gl-amd-fixes (diff)
downloadyuzu-ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613.tar.gz
yuzu-ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613.tar.xz
yuzu-ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613.zip
hid_core: Move hid to it's own subproject
Diffstat (limited to 'src/core/hid/emulated_devices.cpp')
-rw-r--r--src/core/hid/emulated_devices.cpp483
1 files changed, 0 insertions, 483 deletions
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
deleted file mode 100644
index 8e165dded..000000000
--- a/src/core/hid/emulated_devices.cpp
+++ /dev/null
@@ -1,483 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <algorithm>
5#include <fmt/format.h>
6
7#include "core/hid/emulated_devices.h"
8#include "core/hid/input_converter.h"
9
10namespace Core::HID {
11
12EmulatedDevices::EmulatedDevices() = default;
13
14EmulatedDevices::~EmulatedDevices() = default;
15
16void EmulatedDevices::ReloadFromSettings() {
17 ReloadInput();
18}
19
20void EmulatedDevices::ReloadInput() {
21 // If you load any device here add the equivalent to the UnloadInput() function
22
23 // Native Mouse is mapped on port 1, pad 0
24 const Common::ParamPackage mouse_params{"engine:mouse,port:1,pad:0"};
25
26 // Keyboard keys is mapped on port 1, pad 0 for normal keys, pad 1 for moddifier keys
27 const Common::ParamPackage keyboard_params{"engine:keyboard,port:1"};
28
29 std::size_t key_index = 0;
30 for (auto& mouse_device : mouse_button_devices) {
31 Common::ParamPackage mouse_button_params = mouse_params;
32 mouse_button_params.Set("button", static_cast<int>(key_index));
33 mouse_device = Common::Input::CreateInputDevice(mouse_button_params);
34 key_index++;
35 }
36
37 Common::ParamPackage mouse_position_params = mouse_params;
38 mouse_position_params.Set("axis_x", 0);
39 mouse_position_params.Set("axis_y", 1);
40 mouse_position_params.Set("deadzone", 0.0f);
41 mouse_position_params.Set("range", 1.0f);
42 mouse_position_params.Set("threshold", 0.0f);
43 mouse_stick_device = Common::Input::CreateInputDevice(mouse_position_params);
44
45 // First two axis are reserved for mouse position
46 key_index = 2;
47 for (auto& mouse_device : mouse_wheel_devices) {
48 Common::ParamPackage mouse_wheel_params = mouse_params;
49 mouse_wheel_params.Set("axis", static_cast<int>(key_index));
50 mouse_device = Common::Input::CreateInputDevice(mouse_wheel_params);
51 key_index++;
52 }
53
54 key_index = 0;
55 for (auto& keyboard_device : keyboard_devices) {
56 Common::ParamPackage keyboard_key_params = keyboard_params;
57 keyboard_key_params.Set("button", static_cast<int>(key_index));
58 keyboard_key_params.Set("pad", 0);
59 keyboard_device = Common::Input::CreateInputDevice(keyboard_key_params);
60 key_index++;
61 }
62
63 key_index = 0;
64 for (auto& keyboard_device : keyboard_modifier_devices) {
65 Common::ParamPackage keyboard_moddifier_params = keyboard_params;
66 keyboard_moddifier_params.Set("button", static_cast<int>(key_index));
67 keyboard_moddifier_params.Set("pad", 1);
68 keyboard_device = Common::Input::CreateInputDevice(keyboard_moddifier_params);
69 key_index++;
70 }
71
72 for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
73 if (!mouse_button_devices[index]) {
74 continue;
75 }
76 mouse_button_devices[index]->SetCallback({
77 .on_change =
78 [this, index](const Common::Input::CallbackStatus& callback) {
79 SetMouseButton(callback, index);
80 },
81 });
82 }
83
84 for (std::size_t index = 0; index < mouse_wheel_devices.size(); ++index) {
85 if (!mouse_wheel_devices[index]) {
86 continue;
87 }
88 mouse_wheel_devices[index]->SetCallback({
89 .on_change =
90 [this, index](const Common::Input::CallbackStatus& callback) {
91 SetMouseWheel(callback, index);
92 },
93 });
94 }
95
96 if (mouse_stick_device) {
97 mouse_stick_device->SetCallback({
98 .on_change =
99 [this](const Common::Input::CallbackStatus& callback) {
100 SetMousePosition(callback);
101 },
102 });
103 }
104
105 for (std::size_t index = 0; index < keyboard_devices.size(); ++index) {
106 if (!keyboard_devices[index]) {
107 continue;
108 }
109 keyboard_devices[index]->SetCallback({
110 .on_change =
111 [this, index](const Common::Input::CallbackStatus& callback) {
112 SetKeyboardButton(callback, index);
113 },
114 });
115 }
116
117 for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) {
118 if (!keyboard_modifier_devices[index]) {
119 continue;
120 }
121 keyboard_modifier_devices[index]->SetCallback({
122 .on_change =
123 [this, index](const Common::Input::CallbackStatus& callback) {
124 SetKeyboardModifier(callback, index);
125 },
126 });
127 }
128}
129
130void EmulatedDevices::UnloadInput() {
131 for (auto& button : mouse_button_devices) {
132 button.reset();
133 }
134 for (auto& analog : mouse_wheel_devices) {
135 analog.reset();
136 }
137 mouse_stick_device.reset();
138 for (auto& button : keyboard_devices) {
139 button.reset();
140 }
141 for (auto& button : keyboard_modifier_devices) {
142 button.reset();
143 }
144}
145
146void EmulatedDevices::EnableConfiguration() {
147 is_configuring = true;
148 SaveCurrentConfig();
149}
150
151void EmulatedDevices::DisableConfiguration() {
152 is_configuring = false;
153}
154
155bool EmulatedDevices::IsConfiguring() const {
156 return is_configuring;
157}
158
159void EmulatedDevices::SaveCurrentConfig() {
160 if (!is_configuring) {
161 return;
162 }
163}
164
165void EmulatedDevices::RestoreConfig() {
166 if (!is_configuring) {
167 return;
168 }
169 ReloadFromSettings();
170}
171
172void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& callback,
173 std::size_t index) {
174 if (index >= device_status.keyboard_values.size()) {
175 return;
176 }
177 std::unique_lock lock{mutex};
178 bool value_changed = false;
179 const auto new_status = TransformToButton(callback);
180 auto& current_status = device_status.keyboard_values[index];
181 current_status.toggle = new_status.toggle;
182
183 // Update button status with current status
184 if (!current_status.toggle) {
185 current_status.locked = false;
186 if (current_status.value != new_status.value) {
187 current_status.value = new_status.value;
188 value_changed = true;
189 }
190 } else {
191 // Toggle button and lock status
192 if (new_status.value && !current_status.locked) {
193 current_status.locked = true;
194 current_status.value = !current_status.value;
195 value_changed = true;
196 }
197
198 // Unlock button, ready for next press
199 if (!new_status.value && current_status.locked) {
200 current_status.locked = false;
201 }
202 }
203
204 if (!value_changed) {
205 return;
206 }
207
208 if (is_configuring) {
209 lock.unlock();
210 TriggerOnChange(DeviceTriggerType::Keyboard);
211 return;
212 }
213
214 // Index should be converted from NativeKeyboard to KeyboardKeyIndex
215 UpdateKey(index, current_status.value);
216
217 lock.unlock();
218 TriggerOnChange(DeviceTriggerType::Keyboard);
219}
220
221void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
222 constexpr std::size_t KEYS_PER_BYTE = 8;
223 auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE];
224 const u8 mask = static_cast<u8>(1 << (key_index % KEYS_PER_BYTE));
225 if (status) {
226 entry = entry | mask;
227 } else {
228 entry = static_cast<u8>(entry & ~mask);
229 }
230}
231
232void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& callback,
233 std::size_t index) {
234 if (index >= device_status.keyboard_moddifier_values.size()) {
235 return;
236 }
237 std::unique_lock lock{mutex};
238 bool value_changed = false;
239 const auto new_status = TransformToButton(callback);
240 auto& current_status = device_status.keyboard_moddifier_values[index];
241 current_status.toggle = new_status.toggle;
242
243 // Update button status with current
244 if (!current_status.toggle) {
245 current_status.locked = false;
246 if (current_status.value != new_status.value) {
247 current_status.value = new_status.value;
248 value_changed = true;
249 }
250 } else {
251 // Toggle button and lock status
252 if (new_status.value && !current_status.locked) {
253 current_status.locked = true;
254 current_status.value = !current_status.value;
255 value_changed = true;
256 }
257
258 // Unlock button ready for next press
259 if (!new_status.value && current_status.locked) {
260 current_status.locked = false;
261 }
262 }
263
264 if (!value_changed) {
265 return;
266 }
267
268 if (is_configuring) {
269 lock.unlock();
270 TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
271 return;
272 }
273
274 switch (index) {
275 case Settings::NativeKeyboard::LeftControl:
276 case Settings::NativeKeyboard::RightControl:
277 device_status.keyboard_moddifier_state.control.Assign(current_status.value);
278 break;
279 case Settings::NativeKeyboard::LeftShift:
280 case Settings::NativeKeyboard::RightShift:
281 device_status.keyboard_moddifier_state.shift.Assign(current_status.value);
282 break;
283 case Settings::NativeKeyboard::LeftAlt:
284 device_status.keyboard_moddifier_state.left_alt.Assign(current_status.value);
285 break;
286 case Settings::NativeKeyboard::RightAlt:
287 device_status.keyboard_moddifier_state.right_alt.Assign(current_status.value);
288 break;
289 case Settings::NativeKeyboard::CapsLock:
290 device_status.keyboard_moddifier_state.caps_lock.Assign(current_status.value);
291 break;
292 case Settings::NativeKeyboard::ScrollLock:
293 device_status.keyboard_moddifier_state.scroll_lock.Assign(current_status.value);
294 break;
295 case Settings::NativeKeyboard::NumLock:
296 device_status.keyboard_moddifier_state.num_lock.Assign(current_status.value);
297 break;
298 }
299
300 lock.unlock();
301 TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
302}
303
304void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callback,
305 std::size_t index) {
306 if (index >= device_status.mouse_button_values.size()) {
307 return;
308 }
309 std::unique_lock lock{mutex};
310 bool value_changed = false;
311 const auto new_status = TransformToButton(callback);
312 auto& current_status = device_status.mouse_button_values[index];
313 current_status.toggle = new_status.toggle;
314
315 // Update button status with current
316 if (!current_status.toggle) {
317 current_status.locked = false;
318 if (current_status.value != new_status.value) {
319 current_status.value = new_status.value;
320 value_changed = true;
321 }
322 } else {
323 // Toggle button and lock status
324 if (new_status.value && !current_status.locked) {
325 current_status.locked = true;
326 current_status.value = !current_status.value;
327 value_changed = true;
328 }
329
330 // Unlock button ready for next press
331 if (!new_status.value && current_status.locked) {
332 current_status.locked = false;
333 }
334 }
335
336 if (!value_changed) {
337 return;
338 }
339
340 if (is_configuring) {
341 lock.unlock();
342 TriggerOnChange(DeviceTriggerType::Mouse);
343 return;
344 }
345
346 switch (index) {
347 case Settings::NativeMouseButton::Left:
348 device_status.mouse_button_state.left.Assign(current_status.value);
349 break;
350 case Settings::NativeMouseButton::Right:
351 device_status.mouse_button_state.right.Assign(current_status.value);
352 break;
353 case Settings::NativeMouseButton::Middle:
354 device_status.mouse_button_state.middle.Assign(current_status.value);
355 break;
356 case Settings::NativeMouseButton::Forward:
357 device_status.mouse_button_state.forward.Assign(current_status.value);
358 break;
359 case Settings::NativeMouseButton::Back:
360 device_status.mouse_button_state.back.Assign(current_status.value);
361 break;
362 }
363
364 lock.unlock();
365 TriggerOnChange(DeviceTriggerType::Mouse);
366}
367
368void EmulatedDevices::SetMouseWheel(const Common::Input::CallbackStatus& callback,
369 std::size_t index) {
370 if (index >= device_status.mouse_wheel_values.size()) {
371 return;
372 }
373 std::unique_lock lock{mutex};
374 const auto analog_value = TransformToAnalog(callback);
375
376 device_status.mouse_wheel_values[index] = analog_value;
377
378 if (is_configuring) {
379 device_status.mouse_wheel_state = {};
380 lock.unlock();
381 TriggerOnChange(DeviceTriggerType::Mouse);
382 return;
383 }
384
385 switch (index) {
386 case Settings::NativeMouseWheel::X:
387 device_status.mouse_wheel_state.x = static_cast<s32>(analog_value.value);
388 break;
389 case Settings::NativeMouseWheel::Y:
390 device_status.mouse_wheel_state.y = static_cast<s32>(analog_value.value);
391 break;
392 }
393
394 lock.unlock();
395 TriggerOnChange(DeviceTriggerType::Mouse);
396}
397
398void EmulatedDevices::SetMousePosition(const Common::Input::CallbackStatus& callback) {
399 std::unique_lock lock{mutex};
400 const auto touch_value = TransformToTouch(callback);
401
402 device_status.mouse_stick_value = touch_value;
403
404 if (is_configuring) {
405 device_status.mouse_position_state = {};
406 lock.unlock();
407 TriggerOnChange(DeviceTriggerType::Mouse);
408 return;
409 }
410
411 device_status.mouse_position_state.x = touch_value.x.value;
412 device_status.mouse_position_state.y = touch_value.y.value;
413
414 lock.unlock();
415 TriggerOnChange(DeviceTriggerType::Mouse);
416}
417
418KeyboardValues EmulatedDevices::GetKeyboardValues() const {
419 std::scoped_lock lock{mutex};
420 return device_status.keyboard_values;
421}
422
423KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const {
424 std::scoped_lock lock{mutex};
425 return device_status.keyboard_moddifier_values;
426}
427
428MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const {
429 std::scoped_lock lock{mutex};
430 return device_status.mouse_button_values;
431}
432
433KeyboardKey EmulatedDevices::GetKeyboard() const {
434 std::scoped_lock lock{mutex};
435 return device_status.keyboard_state;
436}
437
438KeyboardModifier EmulatedDevices::GetKeyboardModifier() const {
439 std::scoped_lock lock{mutex};
440 return device_status.keyboard_moddifier_state;
441}
442
443MouseButton EmulatedDevices::GetMouseButtons() const {
444 std::scoped_lock lock{mutex};
445 return device_status.mouse_button_state;
446}
447
448MousePosition EmulatedDevices::GetMousePosition() const {
449 std::scoped_lock lock{mutex};
450 return device_status.mouse_position_state;
451}
452
453AnalogStickState EmulatedDevices::GetMouseWheel() const {
454 std::scoped_lock lock{mutex};
455 return device_status.mouse_wheel_state;
456}
457
458void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
459 std::scoped_lock lock{callback_mutex};
460 for (const auto& poller_pair : callback_list) {
461 const InterfaceUpdateCallback& poller = poller_pair.second;
462 if (poller.on_change) {
463 poller.on_change(type);
464 }
465 }
466}
467
468int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) {
469 std::scoped_lock lock{callback_mutex};
470 callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
471 return last_callback_key++;
472}
473
474void EmulatedDevices::DeleteCallback(int key) {
475 std::scoped_lock lock{callback_mutex};
476 const auto& iterator = callback_list.find(key);
477 if (iterator == callback_list.end()) {
478 LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
479 return;
480 }
481 callback_list.erase(iterator);
482}
483} // namespace Core::HID