Bugfix: All desktop hotkeys now work in dual-window mode.

The fullscreen hotkey now works differently. It always changes
the fullscreen setting, and attempts to fullscreen both windows
in dual-screen mode *if* they are on different screens. Othewise
it only fullscreens the main screen for consistency between layouts.

Geometry is always saved and restored from UISettings for more
consistency.
This commit is contained in:
David Griswold 2026-03-31 11:53:57 +03:00
parent 39363cd435
commit 88d1bef1ce
4 changed files with 62 additions and 41 deletions

View File

@ -194,6 +194,7 @@ if (ENABLE_QT)
"geometry"
"state"
"geometryRenderWindow"
"geometrySecondaryWindow"
"gameListHeaderState"
"microProfileDialogGeometry"
"name"

View File

@ -786,11 +786,19 @@ void GMainWindow::InitializeHotkeys() {
const auto link_action_shortcut = [&](QAction* action, const QString& action_name,
const bool primary_only = false) {
static const QString main_window = QStringLiteral("Main Window");
action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name));
auto context = hotkey_registry.GetShortcutContext(main_window, action_name);
auto shortcut = hotkey_registry.GetKeySequence(main_window, action_name);
action->setShortcut(shortcut);
action->setShortcutContext(context);
action->setAutoRepeat(false);
this->addAction(action);
if (!primary_only)
secondary_window->addAction(action);
// handle the shortcuts that are different per-screen
if (context == Qt::WidgetShortcut) {
render_window->addAction(action);
if (!primary_only) {
secondary_window->addAction(action);
}
}
};
link_action_shortcut(ui->action_Load_File, QStringLiteral("Load File"));
@ -802,7 +810,7 @@ void GMainWindow::InitializeHotkeys() {
link_action_shortcut(ui->action_Stop, QStringLiteral("Stop Emulation"));
link_action_shortcut(ui->action_Show_Filter_Bar, QStringLiteral("Toggle Filter Bar"));
link_action_shortcut(ui->action_Show_Status_Bar, QStringLiteral("Toggle Status Bar"));
link_action_shortcut(ui->action_Fullscreen, fullscreen, true);
link_action_shortcut(ui->action_Fullscreen, fullscreen);
link_action_shortcut(ui->action_Capture_Screenshot, QStringLiteral("Capture Screenshot"));
link_action_shortcut(ui->action_Screen_Layout_Swap_Screens, QStringLiteral("Swap Screens"));
link_action_shortcut(ui->action_Screen_Layout_Upright_Screens,
@ -824,10 +832,7 @@ void GMainWindow::InitializeHotkeys() {
// QShortcut Hotkeys
const auto connect_shortcut = [&](const QString& action_name, const auto& function) {
const auto* hotkey = hotkey_registry.GetHotkey(main_window, action_name, this);
const auto* secondary_hotkey =
hotkey_registry.GetHotkey(main_window, action_name, secondary_window);
connect(hotkey, &QShortcut::activated, this, function);
connect(secondary_hotkey, &QShortcut::activated, this, function);
};
connect_shortcut(QStringLiteral("Toggle Screen Layout"), &GMainWindow::ToggleScreenLayout);
@ -897,11 +902,6 @@ void GMainWindow::InitializeHotkeys() {
connect(action, SIGNAL(triggered()), this, slot);
secondary_window->addAction(action);
};
// Use the same fullscreen hotkey as the main window
const auto fullscreen_hotkey = hotkey_registry.GetKeySequence(main_window, fullscreen);
add_secondary_window_hotkey(action_secondary_fullscreen, fullscreen_hotkey,
SLOT(ToggleSecondaryFullscreen()));
}
void GMainWindow::SetDefaultUIGeometry() {
@ -920,6 +920,7 @@ void GMainWindow::RestoreUIState() {
restoreGeometry(UISettings::values.geometry);
restoreState(UISettings::values.state);
render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
secondary_window->restoreGeometry(UISettings::values.secondarywindow_geometry);
#if MICROPROFILE_ENABLED
microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry);
microProfileDialog->setVisible(UISettings::values.microprofile_visible.GetValue());
@ -2592,14 +2593,25 @@ void GMainWindow::ToggleSecondaryFullscreen() {
}
void GMainWindow::ShowFullscreen() {
QWidget* window_to_change =
ui->action_Single_Window_Mode->isChecked() ? static_cast<QWidget*>(this) : render_window;
if (ui->action_Single_Window_Mode->isChecked()) {
UISettings::values.geometry = saveGeometry();
ui->menubar->hide();
statusBar()->hide();
showFullScreen();
} else {
UISettings::values.renderwindow_geometry = render_window->saveGeometry();
render_window->showFullScreen();
}
bool secondary_on_same = window_to_change->screen() == secondary_window->screen();
window_to_change->showFullScreen();
// try to fullscreen the second window if it is visible and on a different screen from main
if (secondary_window->isVisible() && !secondary_on_same) {
UISettings::values.secondarywindow_geometry = secondary_window->saveGeometry();
LOG_INFO(Frontend, "Attempting to fullscreen secondary window");
secondary_window->showFullScreen();
}
}
@ -2613,12 +2625,16 @@ void GMainWindow::HideFullscreen() {
render_window->showNormal();
render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
}
if (secondary_window->isFullScreen()) {
secondary_window->restoreGeometry(UISettings::values.secondarywindow_geometry);
secondary_window->showNormal();
}
}
void GMainWindow::ToggleWindowMode() {
if (ui->action_Single_Window_Mode->isChecked()) {
// Render in the main window...
render_window->BackupGeometry();
UISettings::values.renderwindow_geometry = render_window->saveGeometry();
ui->horizontalLayout->addWidget(render_window);
render_window->setFocusPolicy(Qt::StrongFocus);
if (emulation_running) {
@ -2634,7 +2650,7 @@ void GMainWindow::ToggleWindowMode() {
render_window->setFocusPolicy(Qt::NoFocus);
if (emulation_running) {
render_window->setVisible(true);
render_window->RestoreGeometry();
render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
game_list->show();
}
}
@ -2645,10 +2661,10 @@ void GMainWindow::UpdateSecondaryWindowVisibility() {
return;
}
if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) {
secondary_window->RestoreGeometry();
secondary_window->restoreGeometry(UISettings::values.secondarywindow_geometry);
secondary_window->show();
} else {
secondary_window->BackupGeometry();
UISettings::values.secondarywindow_geometry = secondary_window->saveGeometry();
secondary_window->hide();
}
}
@ -3075,7 +3091,6 @@ void GMainWindow::OnCaptureScreenshot() {
.toString(QStringLiteral("dd.MM.yy_hh.mm.ss.z"))
.toStdString();
path.append(fmt::format("/{}_{}.png", filename, timestamp));
auto* const screenshot_window =
secondary_window->HasFocus() ? secondary_window : render_window;
screenshot_window->CaptureScreenshot(
@ -4137,6 +4152,7 @@ void GMainWindow::UpdateUISettings() {
if (!ui->action_Fullscreen->isChecked()) {
UISettings::values.geometry = saveGeometry();
UISettings::values.renderwindow_geometry = render_window->saveGeometry();
UISettings::values.secondarywindow_geometry = secondary_window->saveGeometry();
}
UISettings::values.state = saveState();
#if MICROPROFILE_ENABLED

View File

@ -59,41 +59,41 @@ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> QtConfi
// clang-format off
const std::array<UISettings::Shortcut, 38> QtConfig::default_hotkeys {{
{QStringLiteral("Advance Frame"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
{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 Up"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}},
{QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::WidgetWithChildrenShortcut}},
{QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}},
{QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::ApplicationShortcut}},
{QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
{QStringLiteral("Audio Volume Up"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
{QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::ApplicationShortcut}},
{QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::ApplicationShortcut}},
{QStringLiteral("Decrease 3D Factor"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+-"), Qt::ApplicationShortcut}},
{QStringLiteral("Decrease Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("-"), Qt::ApplicationShortcut}},
{QStringLiteral("Exit Azahar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"), Qt::WindowShortcut}},
{QStringLiteral("Exit Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("Esc"), Qt::WindowShortcut}},
{QStringLiteral("Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("F11"), Qt::WindowShortcut}},
{QStringLiteral("Exit Azahar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"), Qt::ApplicationShortcut}},
{QStringLiteral("Exit Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("Esc"), Qt::ApplicationShortcut}},
{QStringLiteral("Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("F11"), Qt::ApplicationShortcut}},
{QStringLiteral("Increase 3D Factor"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl++"), Qt::ApplicationShortcut}},
{QStringLiteral("Increase Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("+"), Qt::ApplicationShortcut}},
{QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::WidgetWithChildrenShortcut}},
{QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WidgetWithChildrenShortcut}},
{QStringLiteral("Load from Newest Non-Quicksave Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+V"), Qt::WindowShortcut}},
{QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::ApplicationShortcut}},
{QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::ApplicationShortcut}},
{QStringLiteral("Load from Newest Non-Quicksave Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+V"), Qt::ApplicationShortcut}},
{QStringLiteral("Multiplayer Browse Public Rooms"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+B"), Qt::ApplicationShortcut}},
{QStringLiteral("Multiplayer Create Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+N"), Qt::ApplicationShortcut}},
{QStringLiteral("Multiplayer Direct Connect to Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Shift"), Qt::ApplicationShortcut}},
{QStringLiteral("Multiplayer Leave Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+L"), Qt::ApplicationShortcut}},
{QStringLiteral("Multiplayer Show Current Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+R"), Qt::ApplicationShortcut}},
{QStringLiteral("Quick Save"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}},
{QStringLiteral("Quick Load"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}},
{QStringLiteral("Quick Save"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
{QStringLiteral("Quick Load"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
{QStringLiteral("Remove Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F3"), Qt::ApplicationShortcut}},
{QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}},
{QStringLiteral("Rotate Screens Upright"), QStringLiteral("Main Window"), {QStringLiteral("F8"), Qt::WindowShortcut}},
{QStringLiteral("Save to Oldest Non-Quicksave Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+C"), Qt::WindowShortcut}},
{QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}},
{QStringLiteral("Swap Screens"), QStringLiteral("Main Window"), {QStringLiteral("F9"), Qt::WindowShortcut}},
{QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::ApplicationShortcut}},
{QStringLiteral("Rotate Screens Upright"), QStringLiteral("Main Window"), {QStringLiteral("F8"), Qt::ApplicationShortcut}},
{QStringLiteral("Save to Oldest Non-Quicksave Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+C"), Qt::ApplicationShortcut}},
{QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::ApplicationShortcut}},
{QStringLiteral("Swap Screens"), QStringLiteral("Main Window"), {QStringLiteral("F9"), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle 3D"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+3"), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle Custom Textures"), QStringLiteral("Main Window"), {QStringLiteral("F7"), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}},
{QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle Frame Advancing"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+A"), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle Per-Application Speed"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle Screen Layout"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::WindowShortcut}},
{QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}},
{QStringLiteral("Toggle Screen Layout"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle Texture Dumping"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
{QStringLiteral("Toggle Turbo Mode"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
}};
@ -886,6 +886,8 @@ void QtConfig::ReadUILayoutValues() {
UISettings::values.state = ReadSetting(Settings::QKeys::state).toByteArray();
UISettings::values.renderwindow_geometry =
ReadSetting(Settings::QKeys::geometryRenderWindow).toByteArray();
UISettings::values.secondarywindow_geometry =
ReadSetting(Settings::QKeys::geometrySecondaryWindow).toByteArray();
UISettings::values.gamelist_header_state =
ReadSetting(Settings::QKeys::gameListHeaderState).toByteArray();
UISettings::values.microprofile_geometry =
@ -1413,6 +1415,8 @@ void QtConfig::SaveUILayoutValues() {
WriteSetting(Settings::QKeys::geometry, UISettings::values.geometry);
WriteSetting(Settings::QKeys::state, UISettings::values.state);
WriteSetting(Settings::QKeys::geometryRenderWindow, UISettings::values.renderwindow_geometry);
WriteSetting(Settings::QKeys::geometrySecondaryWindow,
UISettings::values.secondarywindow_geometry);
WriteSetting(Settings::QKeys::gameListHeaderState, UISettings::values.gamelist_header_state);
WriteSetting(Settings::QKeys::microProfileDialogGeometry,
UISettings::values.microprofile_geometry);

View File

@ -70,7 +70,7 @@ struct Values {
QByteArray state;
QByteArray renderwindow_geometry;
QByteArray secondarywindow_geometry;
QByteArray gamelist_header_state;
QByteArray microprofile_geometry;