yuzu-fork/src/yuzu/hotkeys.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

215 lines
7 KiB
C++
Raw Normal View History

chore: make yuzu REUSE compliant [REUSE] is a specification that aims at making file copyright information consistent, so that it can be both human and machine readable. It basically requires that all files have a header containing copyright and licensing information. When this isn't possible, like when dealing with binary assets, generated files or embedded third-party dependencies, it is permitted to insert copyright information in the `.reuse/dep5` file. Oh, and it also requires that all the licenses used in the project are present in the `LICENSES` folder, that's why the diff is so huge. This can be done automatically with `reuse download --all`. The `reuse` tool also contains a handy subcommand that analyzes the project and tells whether or not the project is (still) compliant, `reuse lint`. Following REUSE has a few advantages over the current approach: - Copyright information is easy to access for users / downstream - Files like `dist/license.md` do not need to exist anymore, as `.reuse/dep5` is used instead - `reuse lint` makes it easy to ensure that copyright information of files like binary assets / images is always accurate and up to date To add copyright information of files that didn't have it I looked up who committed what and when, for each file. As yuzu contributors do not have to sign a CLA or similar I couldn't assume that copyright ownership was of the "yuzu Emulator Project", so I used the name and/or email of the commit author instead. [REUSE]: https://reuse.software Follow-up to 01cf05bc75b1e47beb08937439f3ed9339e7b254
2022-05-15 01:06:02 +01:00
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
2021-11-15 23:57:41 +00:00
#include <sstream>
2015-06-21 14:58:59 +01:00
#include <QShortcut>
#include <QTreeWidgetItem>
#include <QtGlobal>
2021-11-15 23:57:41 +00:00
#include "hid_core/frontend/emulated_controller.h"
#include "yuzu/hotkeys.h"
#include "yuzu/uisettings.h"
2014-04-01 03:26:50 +01:00
HotkeyRegistry::HotkeyRegistry() = default;
HotkeyRegistry::~HotkeyRegistry() = default;
2014-04-01 03:26:50 +01:00
void HotkeyRegistry::SaveHotkeys() {
UISettings::values.shortcuts.clear();
for (const auto& group : hotkey_groups) {
for (const auto& hotkey : group.second) {
UISettings::values.shortcuts.push_back(
{hotkey.first, group.first,
UISettings::ContextualShortcut({hotkey.second.keyseq.toString().toStdString(),
2021-11-15 23:57:41 +00:00
hotkey.second.controller_keyseq,
2023-01-18 14:49:47 +00:00
hotkey.second.context, hotkey.second.repeat})});
}
2014-04-01 03:26:50 +01:00
}
}
void HotkeyRegistry::LoadHotkeys() {
// Make sure NOT to use a reference here because it would become invalid once we call
// beginGroup()
for (auto shortcut : UISettings::values.shortcuts) {
Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name];
if (!shortcut.shortcut.keyseq.empty()) {
hk.keyseq = QKeySequence::fromString(QString::fromStdString(shortcut.shortcut.keyseq),
QKeySequence::NativeText);
2021-11-15 23:57:41 +00:00
hk.context = static_cast<Qt::ShortcutContext>(shortcut.shortcut.context);
}
if (!shortcut.shortcut.controller_keyseq.empty()) {
2021-11-15 23:57:41 +00:00
hk.controller_keyseq = shortcut.shortcut.controller_keyseq;
}
if (hk.shortcut) {
hk.shortcut->disconnect();
hk.shortcut->setKey(hk.keyseq);
}
2021-11-15 23:57:41 +00:00
if (hk.controller_shortcut) {
hk.controller_shortcut->disconnect();
hk.controller_shortcut->SetKey(hk.controller_keyseq);
}
hk.repeat = shortcut.shortcut.repeat;
}
}
QShortcut* HotkeyRegistry::GetHotkey(const std::string& group, const std::string& action,
QWidget* widget) {
2014-04-01 03:26:50 +01:00
Hotkey& hk = hotkey_groups[group][action];
2021-11-15 23:57:41 +00:00
if (!hk.shortcut) {
2014-12-03 18:57:57 +00:00
hk.shortcut = new QShortcut(hk.keyseq, widget, nullptr, nullptr, hk.context);
2021-11-15 23:57:41 +00:00
}
2014-04-01 03:26:50 +01:00
hk.shortcut->setAutoRepeat(hk.repeat);
2014-04-01 03:26:50 +01:00
return hk.shortcut;
}
ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const std::string& group,
const std::string& action,
2021-11-15 23:57:41 +00:00
Core::HID::EmulatedController* controller) {
Hotkey& hk = hotkey_groups[group][action];
if (!hk.controller_shortcut) {
hk.controller_shortcut = new ControllerShortcut(controller);
hk.controller_shortcut->SetKey(hk.controller_keyseq);
}
return hk.controller_shortcut;
}
QKeySequence HotkeyRegistry::GetKeySequence(const std::string& group, const std::string& action) {
return hotkey_groups[group][action].keyseq;
}
2014-04-01 03:26:50 +01:00
Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const std::string& group,
const std::string& action) {
return hotkey_groups[group][action].context;
2014-04-01 03:26:50 +01:00
}
2021-11-15 23:57:41 +00:00
ControllerShortcut::ControllerShortcut(Core::HID::EmulatedController* controller) {
emulated_controller = controller;
Core::HID::ControllerUpdateCallback engine_callback{
.on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdateEvent(type); },
.is_npad_service = false,
};
callback_key = emulated_controller->SetCallback(engine_callback);
is_enabled = true;
}
ControllerShortcut::~ControllerShortcut() {
emulated_controller->DeleteCallback(callback_key);
}
void ControllerShortcut::SetKey(const ControllerButtonSequence& buttons) {
button_sequence = buttons;
}
void ControllerShortcut::SetKey(const std::string& buttons_shortcut) {
2021-11-15 23:57:41 +00:00
ControllerButtonSequence sequence{};
name = buttons_shortcut;
std::istringstream command_line(buttons_shortcut);
2021-11-15 23:57:41 +00:00
std::string line;
while (std::getline(command_line, line, '+')) {
if (line.empty()) {
continue;
}
if (line == "A") {
sequence.npad.a.Assign(1);
}
if (line == "B") {
sequence.npad.b.Assign(1);
}
if (line == "X") {
sequence.npad.x.Assign(1);
}
if (line == "Y") {
sequence.npad.y.Assign(1);
}
if (line == "L") {
sequence.npad.l.Assign(1);
}
if (line == "R") {
sequence.npad.r.Assign(1);
}
if (line == "ZL") {
sequence.npad.zl.Assign(1);
}
if (line == "ZR") {
sequence.npad.zr.Assign(1);
}
if (line == "Dpad_Left") {
sequence.npad.left.Assign(1);
}
if (line == "Dpad_Right") {
sequence.npad.right.Assign(1);
}
if (line == "Dpad_Up") {
sequence.npad.up.Assign(1);
}
if (line == "Dpad_Down") {
sequence.npad.down.Assign(1);
}
if (line == "Left_Stick") {
sequence.npad.stick_l.Assign(1);
}
if (line == "Right_Stick") {
sequence.npad.stick_r.Assign(1);
}
if (line == "Minus") {
sequence.npad.minus.Assign(1);
}
if (line == "Plus") {
sequence.npad.plus.Assign(1);
}
if (line == "Home") {
sequence.home.home.Assign(1);
}
if (line == "Screenshot") {
sequence.capture.capture.Assign(1);
}
}
button_sequence = sequence;
}
ControllerButtonSequence ControllerShortcut::ButtonSequence() const {
return button_sequence;
}
void ControllerShortcut::SetEnabled(bool enable) {
is_enabled = enable;
}
bool ControllerShortcut::IsEnabled() const {
return is_enabled;
}
void ControllerShortcut::ControllerUpdateEvent(Core::HID::ControllerTriggerType type) {
if (!is_enabled) {
return;
}
if (type != Core::HID::ControllerTriggerType::Button) {
return;
}
if (button_sequence.npad.raw == Core::HID::NpadButton::None &&
button_sequence.capture.raw == 0 && button_sequence.home.raw == 0) {
2021-11-15 23:57:41 +00:00
return;
}
const auto player_npad_buttons =
emulated_controller->GetNpadButtons().raw & button_sequence.npad.raw;
const u64 player_capture_buttons =
emulated_controller->GetCaptureButtons().raw & button_sequence.capture.raw;
const u64 player_home_buttons =
emulated_controller->GetHomeButtons().raw & button_sequence.home.raw;
if (player_npad_buttons == button_sequence.npad.raw &&
player_capture_buttons == button_sequence.capture.raw &&
player_home_buttons == button_sequence.home.raw && !active) {
// Force user to press the home or capture button again
active = true;
emit Activated();
return;
}
active = false;
}