mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-06-01 12:15:03 -06:00
Merge 0c5d2ba557 into 336d871a7f
This commit is contained in:
commit
c3177f2871
@ -11,6 +11,7 @@ enum class Hotkey(val button: Int) {
|
|||||||
PAUSE_OR_RESUME(10004),
|
PAUSE_OR_RESUME(10004),
|
||||||
QUICKSAVE(10005),
|
QUICKSAVE(10005),
|
||||||
QUICKLOAD(10006),
|
QUICKLOAD(10006),
|
||||||
TURBO_LIMIT(10007),
|
TURBO_TOGGLE(10007),
|
||||||
ENABLE(10008);
|
ENABLE(10008),
|
||||||
|
TURBO_HOLD(10009);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import org.citra.citra_emu.utils.TurboHelper
|
|||||||
import org.citra.citra_emu.display.ScreenAdjustmentUtil
|
import org.citra.citra_emu.display.ScreenAdjustmentUtil
|
||||||
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
||||||
import org.citra.citra_emu.features.settings.model.Settings
|
import org.citra.citra_emu.features.settings.model.Settings
|
||||||
|
import org.citra.citra_emu.utils.Log
|
||||||
|
|
||||||
class HotkeyUtility(
|
class HotkeyUtility(
|
||||||
private val screenAdjustmentUtil: ScreenAdjustmentUtil,
|
private val screenAdjustmentUtil: ScreenAdjustmentUtil,
|
||||||
@ -40,6 +41,7 @@ class HotkeyUtility(
|
|||||||
|
|
||||||
// Now process all internal buttons associated with this keypress
|
// Now process all internal buttons associated with this keypress
|
||||||
for (button in buttonSet) {
|
for (button in buttonSet) {
|
||||||
|
Log.debug("Button pressed: " + button)
|
||||||
currentlyPressedButtons.add(button)
|
currentlyPressedButtons.add(button)
|
||||||
//option 1 - this is the enable command, which was already handled
|
//option 1 - this is the enable command, which was already handled
|
||||||
if (button == Hotkey.ENABLE.button) {
|
if (button == Hotkey.ENABLE.button) {
|
||||||
@ -78,9 +80,11 @@ class HotkeyUtility(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (button in buttonSet) {
|
for (button in buttonSet) {
|
||||||
|
Log.debug("Button released: " + button)
|
||||||
// this is a hotkey button
|
// this is a hotkey button
|
||||||
if (hotkeyButtons.contains(button)) {
|
if (hotkeyButtons.contains(button)) {
|
||||||
currentlyPressedButtons.remove(button)
|
currentlyPressedButtons.remove(button)
|
||||||
|
handleHotkeyRelease(button)
|
||||||
if (!currentlyPressedButtons.any { hotkeyButtons.contains(it) }) {
|
if (!currentlyPressedButtons.any { hotkeyButtons.contains(it) }) {
|
||||||
// all hotkeys are no longer pressed
|
// all hotkeys are no longer pressed
|
||||||
hotkeyIsPressed = false
|
hotkeyIsPressed = false
|
||||||
@ -106,13 +110,23 @@ class HotkeyUtility(
|
|||||||
return handled
|
return handled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun handleHotkeyRelease(bindedButton: Int): Boolean {
|
||||||
|
Log.debug("Handling hotkey button release: " + bindedButton)
|
||||||
|
if (bindedButton == Hotkey.TURBO_HOLD.button) {
|
||||||
|
TurboHelper.setTurboEnabled(false, false)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fun handleHotkey(bindedButton: Int): Boolean {
|
fun handleHotkey(bindedButton: Int): Boolean {
|
||||||
|
Log.debug("Handling hotkey button press: " + bindedButton)
|
||||||
when (bindedButton) {
|
when (bindedButton) {
|
||||||
Hotkey.SWAP_SCREEN.button -> screenAdjustmentUtil.swapScreen()
|
Hotkey.SWAP_SCREEN.button -> screenAdjustmentUtil.swapScreen()
|
||||||
Hotkey.CYCLE_LAYOUT.button -> screenAdjustmentUtil.cycleLayouts()
|
Hotkey.CYCLE_LAYOUT.button -> screenAdjustmentUtil.cycleLayouts()
|
||||||
Hotkey.CLOSE_GAME.button -> EmulationLifecycleUtil.closeGame()
|
Hotkey.CLOSE_GAME.button -> EmulationLifecycleUtil.closeGame()
|
||||||
Hotkey.PAUSE_OR_RESUME.button -> EmulationLifecycleUtil.pauseOrResume()
|
Hotkey.PAUSE_OR_RESUME.button -> EmulationLifecycleUtil.pauseOrResume()
|
||||||
Hotkey.TURBO_LIMIT.button -> TurboHelper.toggleTurbo(true)
|
Hotkey.TURBO_TOGGLE.button -> TurboHelper.toggleTurbo(true)
|
||||||
|
Hotkey.TURBO_HOLD.button -> TurboHelper.setTurboEnabled(true, false)
|
||||||
Hotkey.QUICKSAVE.button -> {
|
Hotkey.QUICKSAVE.button -> {
|
||||||
NativeLibrary.saveState(NativeLibrary.QUICKSAVE_SLOT)
|
NativeLibrary.saveState(NativeLibrary.QUICKSAVE_SLOT)
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
|
|||||||
@ -143,7 +143,8 @@ class Settings {
|
|||||||
const val HOTKEY_PAUSE_OR_RESUME = "hotkey_pause_or_resume_game"
|
const val HOTKEY_PAUSE_OR_RESUME = "hotkey_pause_or_resume_game"
|
||||||
const val HOTKEY_QUICKSAVE = "hotkey_quickload"
|
const val HOTKEY_QUICKSAVE = "hotkey_quickload"
|
||||||
const val HOTKEY_QUICKlOAD = "hotkey_quickpause"
|
const val HOTKEY_QUICKlOAD = "hotkey_quickpause"
|
||||||
const val HOTKEY_TURBO_LIMIT = "hotkey_turbo_limit"
|
const val HOTKEY_TURBO_TOGGLE = "hotkey_turbo_limit"
|
||||||
|
const val HOTKEY_TURBO_HOLD = "hotkey_turbo_hold"
|
||||||
|
|
||||||
val buttonKeys = listOf(
|
val buttonKeys = listOf(
|
||||||
KEY_BUTTON_A,
|
KEY_BUTTON_A,
|
||||||
@ -211,7 +212,8 @@ class Settings {
|
|||||||
HOTKEY_PAUSE_OR_RESUME,
|
HOTKEY_PAUSE_OR_RESUME,
|
||||||
HOTKEY_QUICKSAVE,
|
HOTKEY_QUICKSAVE,
|
||||||
HOTKEY_QUICKlOAD,
|
HOTKEY_QUICKlOAD,
|
||||||
HOTKEY_TURBO_LIMIT
|
HOTKEY_TURBO_TOGGLE,
|
||||||
|
HOTKEY_TURBO_HOLD
|
||||||
)
|
)
|
||||||
val hotkeyTitles = listOf(
|
val hotkeyTitles = listOf(
|
||||||
R.string.controller_hotkey_enable_button,
|
R.string.controller_hotkey_enable_button,
|
||||||
@ -221,7 +223,8 @@ class Settings {
|
|||||||
R.string.emulation_toggle_pause,
|
R.string.emulation_toggle_pause,
|
||||||
R.string.emulation_quicksave,
|
R.string.emulation_quicksave,
|
||||||
R.string.emulation_quickload,
|
R.string.emulation_quickload,
|
||||||
R.string.turbo_limit_hotkey
|
R.string.turbo_limit_hotkey,
|
||||||
|
R.string.turbo_hold_hotkey
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Move these in with the other setting keys in GenerateSettingKeys.cmake
|
// TODO: Move these in with the other setting keys in GenerateSettingKeys.cmake
|
||||||
|
|||||||
@ -136,7 +136,8 @@ class InputBindingSetting(
|
|||||||
Settings.HOTKEY_PAUSE_OR_RESUME -> Hotkey.PAUSE_OR_RESUME.button
|
Settings.HOTKEY_PAUSE_OR_RESUME -> Hotkey.PAUSE_OR_RESUME.button
|
||||||
Settings.HOTKEY_QUICKSAVE -> Hotkey.QUICKSAVE.button
|
Settings.HOTKEY_QUICKSAVE -> Hotkey.QUICKSAVE.button
|
||||||
Settings.HOTKEY_QUICKlOAD -> Hotkey.QUICKLOAD.button
|
Settings.HOTKEY_QUICKlOAD -> Hotkey.QUICKLOAD.button
|
||||||
Settings.HOTKEY_TURBO_LIMIT -> Hotkey.TURBO_LIMIT.button
|
Settings.HOTKEY_TURBO_TOGGLE -> Hotkey.TURBO_TOGGLE.button
|
||||||
|
Settings.HOTKEY_TURBO_HOLD -> Hotkey.TURBO_HOLD.button
|
||||||
else -> -1
|
else -> -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -164,7 +164,8 @@
|
|||||||
<string name="button_zr" translatable="false">ZR</string>
|
<string name="button_zr" translatable="false">ZR</string>
|
||||||
<string name="input_message_analog_only">This control must be bound to a gamepad analog stick or D-pad axis!</string>
|
<string name="input_message_analog_only">This control must be bound to a gamepad analog stick or D-pad axis!</string>
|
||||||
<string name="input_message_button_only">This control must be bound to a gamepad button!</string>
|
<string name="input_message_button_only">This control must be bound to a gamepad button!</string>
|
||||||
<string name="turbo_limit_hotkey">Turbo Speed</string>
|
<string name="turbo_limit_hotkey">Turbo (Toggle)</string>
|
||||||
|
<string name="turbo_hold_hotkey">Turbo (Hold)</string>
|
||||||
<string name="turbo_enabled_toast">Turbo Speed Enabled</string>
|
<string name="turbo_enabled_toast">Turbo Speed Enabled</string>
|
||||||
<string name="turbo_disabled_toast">Turbo Speed Disabled</string>
|
<string name="turbo_disabled_toast">Turbo Speed Disabled</string>
|
||||||
|
|
||||||
|
|||||||
@ -918,6 +918,27 @@ void GMainWindow::InitializeHotkeys() {
|
|||||||
const auto fullscreen_hotkey = hotkey_registry.GetKeySequence(main_window, fullscreen);
|
const auto fullscreen_hotkey = hotkey_registry.GetKeySequence(main_window, fullscreen);
|
||||||
add_secondary_window_hotkey(action_secondary_fullscreen, fullscreen_hotkey,
|
add_secondary_window_hotkey(action_secondary_fullscreen, fullscreen_hotkey,
|
||||||
SLOT(ToggleSecondaryFullscreen()));
|
SLOT(ToggleSecondaryFullscreen()));
|
||||||
|
|
||||||
|
// add Toggle(Hold) to the event filter to be caught manually and processed in the two below
|
||||||
|
// methods
|
||||||
|
filter->sequences_to_catch.emplace(
|
||||||
|
hotkey_registry.GetKeySequence(main_window, QStringLiteral("Turbo Mode (Hold)")));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnSequencePressed(QKeySequence seq) {
|
||||||
|
auto turbo_sequence = hotkey_registry.GetKeySequence(QStringLiteral("Main Window"),
|
||||||
|
QStringLiteral("Turbo Mode (Hold)"));
|
||||||
|
if (seq == turbo_sequence) {
|
||||||
|
SetTurboEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnSequenceReleased(QKeySequence seq) {
|
||||||
|
auto turbo_sequence = hotkey_registry.GetKeySequence(QStringLiteral("Main Window"),
|
||||||
|
QStringLiteral("Turbo Mode (Hold)"));
|
||||||
|
if (seq == turbo_sequence) {
|
||||||
|
SetTurboEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::SetDefaultUIGeometry() {
|
void GMainWindow::SetDefaultUIGeometry() {
|
||||||
@ -991,19 +1012,49 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helper method to check if a keyevent matches a key sequence.
|
||||||
|
bool matchesKeyEvent(const QKeyEvent* event, const QKeySequence& seq) {
|
||||||
|
if (seq.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int seqKey = seq[0];
|
||||||
|
int eventKey = (event->key() | event->modifiers());
|
||||||
|
return eventKey == seqKey;
|
||||||
|
}
|
||||||
|
|
||||||
bool GApplicationEventFilter::eventFilter(QObject* object, QEvent* event) {
|
bool GApplicationEventFilter::eventFilter(QObject* object, QEvent* event) {
|
||||||
if (event->type() == QEvent::FileOpen) {
|
if (event->type() == QEvent::FileOpen) {
|
||||||
emit FileOpen(static_cast<QFileOpenEvent*>(event));
|
emit FileOpen(static_cast<QFileOpenEvent*>(event));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (event->type() == QEvent::ShortcutOverride || event->type() == QEvent::KeyPress) {
|
||||||
|
QKeyEvent* key = static_cast<QKeyEvent*>(event);
|
||||||
|
for (auto seq : sequences_to_catch) {
|
||||||
|
if (matchesKeyEvent(key, seq)) {
|
||||||
|
emit SequencePressCaught(seq);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::KeyRelease) {
|
||||||
|
QKeyEvent* key = static_cast<QKeyEvent*>(event);
|
||||||
|
for (auto seq : sequences_to_catch) {
|
||||||
|
if (matchesKeyEvent(key, seq)) {
|
||||||
|
emit SequenceReleaseCaught(seq);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::ConnectAppEvents() {
|
void GMainWindow::ConnectAppEvents() {
|
||||||
const auto filter = new GApplicationEventFilter();
|
|
||||||
QGuiApplication::instance()->installEventFilter(filter);
|
QGuiApplication::instance()->installEventFilter(filter);
|
||||||
|
|
||||||
connect(filter, &GApplicationEventFilter::FileOpen, this, &GMainWindow::OnFileOpen);
|
connect(filter, &GApplicationEventFilter::FileOpen, this, &GMainWindow::OnFileOpen);
|
||||||
|
connect(filter, &GApplicationEventFilter::SequencePressCaught, this,
|
||||||
|
&GMainWindow::OnSequencePressed);
|
||||||
|
connect(filter, &GApplicationEventFilter::SequenceReleaseCaught, this,
|
||||||
|
&GMainWindow::OnSequenceReleased);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::ConnectWidgetEvents() {
|
void GMainWindow::ConnectWidgetEvents() {
|
||||||
|
|||||||
@ -95,6 +95,21 @@ enum class MediaType : u32;
|
|||||||
|
|
||||||
int LaunchQtFrontend(int argc, char* argv[]);
|
int LaunchQtFrontend(int argc, char* argv[]);
|
||||||
|
|
||||||
|
class GApplicationEventFilter : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::set<QKeySequence> sequences_to_catch{};
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void FileOpen(const QFileOpenEvent* event);
|
||||||
|
void SequencePressCaught(QKeySequence seq);
|
||||||
|
void SequenceReleaseCaught(QKeySequence seq);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject* object, QEvent* event) override;
|
||||||
|
};
|
||||||
|
|
||||||
class GMainWindow : public QMainWindow {
|
class GMainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -118,7 +133,8 @@ public:
|
|||||||
void AcceptDropEvent(QDropEvent* event);
|
void AcceptDropEvent(QDropEvent* event);
|
||||||
|
|
||||||
void OnFileOpen(const QFileOpenEvent* event);
|
void OnFileOpen(const QFileOpenEvent* event);
|
||||||
|
void OnSequencePressed(QKeySequence seq);
|
||||||
|
void OnSequenceReleased(QKeySequence seq);
|
||||||
void UninstallTitles(
|
void UninstallTitles(
|
||||||
const std::vector<std::tuple<Service::FS::MediaType, u64, QString>>& titles);
|
const std::vector<std::tuple<Service::FS::MediaType, u64, QString>>& titles);
|
||||||
|
|
||||||
@ -341,7 +357,7 @@ private:
|
|||||||
std::unique_ptr<Ui::MainWindow> ui;
|
std::unique_ptr<Ui::MainWindow> ui;
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
Core::Movie& movie;
|
Core::Movie& movie;
|
||||||
|
GApplicationEventFilter* filter = new GApplicationEventFilter();
|
||||||
GRenderWindow* render_window;
|
GRenderWindow* render_window;
|
||||||
GRenderWindow* secondary_window;
|
GRenderWindow* secondary_window;
|
||||||
|
|
||||||
@ -468,15 +484,5 @@ protected:
|
|||||||
void showEvent(QShowEvent* event) override;
|
void showEvent(QShowEvent* event) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GApplicationEventFilter : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void FileOpen(const QFileOpenEvent* event);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool eventFilter(QObject* object, QEvent* event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(std::size_t);
|
Q_DECLARE_METATYPE(std::size_t);
|
||||||
Q_DECLARE_METATYPE(Service::AM::InstallStatus);
|
Q_DECLARE_METATYPE(Service::AM::InstallStatus);
|
||||||
|
|||||||
@ -57,7 +57,7 @@ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> QtConfi
|
|||||||
// This must be in alphabetical order according to action name as it must have the same order as
|
// This must be in alphabetical order according to action name as it must have the same order as
|
||||||
// UISetting::values.shortcuts, which is alphabetically ordered.
|
// UISetting::values.shortcuts, which is alphabetically ordered.
|
||||||
// clang-format off
|
// clang-format off
|
||||||
const std::array<UISettings::Shortcut, 38> QtConfig::default_hotkeys {{
|
const std::array<UISettings::Shortcut, 39> QtConfig::default_hotkeys {{
|
||||||
{QStringLiteral("Advance Frame"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
{QStringLiteral("Advance Frame"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
||||||
{QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::WindowShortcut}},
|
{QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::WindowShortcut}},
|
||||||
{QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}},
|
{QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}},
|
||||||
@ -96,6 +96,7 @@ const std::array<UISettings::Shortcut, 38> QtConfig::default_hotkeys {{
|
|||||||
{QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}},
|
{QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}},
|
||||||
{QStringLiteral("Toggle Texture Dumping"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
{QStringLiteral("Toggle Texture Dumping"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
||||||
{QStringLiteral("Toggle Turbo Mode"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
{QStringLiteral("Toggle Turbo Mode"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
||||||
|
{QStringLiteral("Turbo Mode (Hold)"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
||||||
}};
|
}};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ public:
|
|||||||
|
|
||||||
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
||||||
static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
||||||
static const std::array<UISettings::Shortcut, 38> default_hotkeys;
|
static const std::array<UISettings::Shortcut, 39> default_hotkeys;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Initialize(const std::string& config_name);
|
void Initialize(const std::string& config_name);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user