Keyboard: Add a configuration window

Add MAIN_WII_KEYBOARD_TRANSLATION to toggle the layout translation
This commit is contained in:
Sepalani 2025-05-02 15:29:34 +04:00
parent 6c331bbd4c
commit f8687a48e6
14 changed files with 138 additions and 1 deletions

View File

@ -140,7 +140,10 @@ int GetGameLayout()
u8 MapVirtualKeyToHID(u8 virtual_key, int host_layout, int game_layout)
{
// SDL3 keyboard state uses scan codes already based on HID usage id
return TranslateUsageID(virtual_key, host_layout, game_layout);
u8 usage_id = virtual_key;
if (Config::Get(Config::MAIN_WII_KEYBOARD_TRANSLATION))
usage_id = TranslateUsageID(usage_id, host_layout, game_layout);
return usage_id;
}
std::weak_ptr<Common::KeyboardContext> s_keyboard_context;

View File

@ -203,6 +203,8 @@ const Info<u64> MAIN_WII_SD_CARD_FILESIZE{{System::Main, "Core", "WiiSDCardFiles
const Info<bool> MAIN_WII_KEYBOARD{{System::Main, "Core", "WiiKeyboard"}, false};
const Info<int> MAIN_WII_KEYBOARD_HOST_LAYOUT{{System::Main, "Core", "WiiKeyboardHostLayout"}, 0};
const Info<int> MAIN_WII_KEYBOARD_GAME_LAYOUT{{System::Main, "Core", "WiiKeyboardGameLayout"}, 0};
const Info<bool> MAIN_WII_KEYBOARD_TRANSLATION{{System::Main, "Core", "WiiKeyboardTranslation"},
false};
const Info<bool> MAIN_WIIMOTE_CONTINUOUS_SCANNING{
{System::Main, "Core", "WiimoteContinuousScanning"}, false};
const Info<std::string> MAIN_WIIMOTE_AUTO_CONNECT_ADDRESSES{

View File

@ -113,6 +113,7 @@ extern const Info<u64> MAIN_WII_SD_CARD_FILESIZE;
extern const Info<bool> MAIN_WII_KEYBOARD;
extern const Info<int> MAIN_WII_KEYBOARD_HOST_LAYOUT;
extern const Info<int> MAIN_WII_KEYBOARD_GAME_LAYOUT;
extern const Info<bool> MAIN_WII_KEYBOARD_TRANSLATION;
extern const Info<bool> MAIN_WIIMOTE_CONTINUOUS_SCANNING;
extern const Info<std::string> MAIN_WIIMOTE_AUTO_CONNECT_ADDRESSES;
extern const Info<bool> MAIN_WIIMOTE_ENABLE_SPEAKER;

View File

@ -255,6 +255,8 @@ add_executable(dolphin-emu
DiscordHandler.h
DiscordJoinRequestDialog.cpp
DiscordJoinRequestDialog.h
EmulatedUSB/Keyboard.cpp
EmulatedUSB/Keyboard.h
EmulatedUSB/WiiSpeakWindow.cpp
EmulatedUSB/WiiSpeakWindow.h
EmulatedUSB/LogitechMicWindow.cpp

View File

@ -160,6 +160,7 @@
<ClCompile Include="Debugger\WatchWidget.cpp" />
<ClCompile Include="DiscordHandler.cpp" />
<ClCompile Include="DiscordJoinRequestDialog.cpp" />
<ClCompile Include="EmulatedUSB\Keyboard.cpp" />
<ClCompile Include="EmulatedUSB\LogitechMicWindow.cpp" />
<ClCompile Include="EmulatedUSB\WiiSpeakWindow.cpp" />
<ClCompile Include="FIFO\FIFOAnalyzer.cpp" />
@ -388,6 +389,7 @@
<QtMoc Include="Debugger\WatchWidget.h" />
<QtMoc Include="DiscordHandler.h" />
<QtMoc Include="DiscordJoinRequestDialog.h" />
<QtMoc Include="EmulatedUSB\Keyboard.h" />
<QtMoc Include="EmulatedUSB\LogitechMicWindow.h" />
<QtMoc Include="EmulatedUSB\WiiSpeakWindow.h" />
<QtMoc Include="FIFO\FIFOAnalyzer.h" />

View File

@ -0,0 +1,86 @@
// Copyright 2026 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "DolphinQt/EmulatedUSB/Keyboard.h"
#include <QComboBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QVBoxLayout>
#include "Common/Keyboard.h"
#include "Core/Config/MainSettings.h"
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
KeyboardWindow::KeyboardWindow(QWidget* parent) : QWidget(parent)
{
// i18n: Window for managing the Wii keyboard emulation
setWindowTitle(tr("Keyboard Manager"));
setWindowIcon(Resources::GetAppIcon());
setObjectName(QStringLiteral("keyboard_manager"));
setMinimumSize(QSize(500, 200));
auto* main_layout = new QVBoxLayout();
{
auto* group = new QGroupBox();
auto* hbox_layout = new QHBoxLayout();
hbox_layout->setAlignment(Qt::AlignHCenter);
auto* checkbox_emulate = new ConfigBool(tr("Connect USB Keyboard"), Config::MAIN_WII_KEYBOARD);
connect(checkbox_emulate, &QCheckBox::toggled, &Settings::Instance(),
&Settings::SetUSBKeyboardConnected);
connect(&Settings::Instance(), &Settings::USBKeyboardConnectionChanged, checkbox_emulate,
&QCheckBox::setChecked);
hbox_layout->addWidget(checkbox_emulate);
group->setLayout(hbox_layout);
main_layout->addWidget(group);
}
{
auto* group = new QGroupBox(tr("Layout Configuration"));
auto* grid_layout = new QGridLayout();
auto* checkbox_translate =
new ConfigBool(tr("Enable partial translation"), Config::MAIN_WII_KEYBOARD_TRANSLATION);
grid_layout->addWidget(checkbox_translate, 0, 0, 1, 2, Qt::AlignLeft);
auto create_combo = [checkbox_translate, grid_layout](int row, const QString& name,
const auto& config_info) {
grid_layout->addWidget(new QLabel(name), row, 0);
auto* combo = new QComboBox();
combo->addItem(tr("Automatic detection"), Common::KeyboardLayout::AUTO);
combo->addItem(QStringLiteral("QWERTY"), Common::KeyboardLayout::QWERTY);
combo->addItem(QStringLiteral("AZERTY"), Common::KeyboardLayout::AZERTY);
combo->addItem(QStringLiteral("QWERTZ"), Common::KeyboardLayout::QWERTZ);
combo->setCurrentIndex(combo->findData(Config::Get(config_info)));
combo->setEnabled(checkbox_translate->isChecked());
connect(combo, &QComboBox::currentIndexChanged, combo, [combo, config_info] {
const auto keyboard_layout = combo->currentData();
if (!keyboard_layout.isValid())
return;
Config::SetBaseOrCurrent(config_info, keyboard_layout.toInt());
Common::KeyboardContext::UpdateLayout();
});
connect(checkbox_translate, &QCheckBox::toggled, combo, &QComboBox::setEnabled);
grid_layout->addWidget(combo, row, 1);
};
create_combo(1, tr("Host layout:"), Config::MAIN_WII_KEYBOARD_HOST_LAYOUT);
create_combo(2, tr("Game layout:"), Config::MAIN_WII_KEYBOARD_GAME_LAYOUT);
group->setLayout(grid_layout);
main_layout->addWidget(group);
}
setLayout(main_layout);
}
KeyboardWindow::~KeyboardWindow() = default;

View File

@ -0,0 +1,14 @@
// Copyright 2026 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QWidget>
class KeyboardWindow : public QWidget
{
Q_OBJECT
public:
explicit KeyboardWindow(QWidget* parent = nullptr);
~KeyboardWindow() override;
};

View File

@ -91,6 +91,7 @@
#include "DolphinQt/Debugger/ThreadWidget.h"
#include "DolphinQt/Debugger/WatchWidget.h"
#include "DolphinQt/DiscordHandler.h"
#include "DolphinQt/EmulatedUSB/Keyboard.h"
#include "DolphinQt/EmulatedUSB/LogitechMicWindow.h"
#include "DolphinQt/EmulatedUSB/WiiSpeakWindow.h"
#include "DolphinQt/FIFO/FIFOPlayerWindow.h"
@ -568,6 +569,7 @@ void MainWindow::ConnectMenuBar()
connect(m_menu_bar, &MenuBar::ShowInfinityBase, this, &MainWindow::ShowInfinityBase);
connect(m_menu_bar, &MenuBar::ShowWiiSpeakWindow, this, &MainWindow::ShowWiiSpeakWindow);
connect(m_menu_bar, &MenuBar::ShowLogitechMicWindow, this, &MainWindow::ShowLogitechMicWindow);
connect(m_menu_bar, &MenuBar::ShowKeyboard, this, &MainWindow::ShowKeyboard);
connect(m_menu_bar, &MenuBar::ConnectWiiRemote, this, &MainWindow::OnConnectWiiRemote);
#ifdef USE_RETRO_ACHIEVEMENTS
@ -1449,6 +1451,18 @@ void MainWindow::ShowLogitechMicWindow()
m_logitech_mic_window->activateWindow();
}
void MainWindow::ShowKeyboard()
{
if (!m_keyboard_window)
{
m_keyboard_window = new KeyboardWindow();
}
m_keyboard_window->show();
m_keyboard_window->raise();
m_keyboard_window->activateWindow();
}
void MainWindow::StateLoad()
{
QString dialog_path = (Config::Get(Config::MAIN_CURRENT_STATE_PATH).empty()) ?

View File

@ -36,6 +36,7 @@ class GBATASInputWindow;
class GCTASInputWindow;
class HotkeyScheduler;
class InfinityBaseWindow;
class KeyboardWindow;
class JITWidget;
class LogConfigWidget;
class LogWidget;
@ -179,6 +180,7 @@ private:
void ShowInfinityBase();
void ShowWiiSpeakWindow();
void ShowLogitechMicWindow();
void ShowKeyboard();
void ShowMemcardManager();
void ShowResourcePackManager();
void ShowCheatsManager();
@ -257,6 +259,7 @@ private:
InfinityBaseWindow* m_infinity_window = nullptr;
WiiSpeakWindow* m_wii_speak_window = nullptr;
LogitechMicWindow* m_logitech_mic_window = nullptr;
KeyboardWindow* m_keyboard_window = nullptr;
MappingWindow* m_hotkey_window = nullptr;
FreeLookWindow* m_freelook_window = nullptr;

View File

@ -289,6 +289,7 @@ void MenuBar::AddToolsMenu()
usb_device_menu->addAction(tr("&Infinity Base"), this, &MenuBar::ShowInfinityBase);
usb_device_menu->addAction(tr("&Wii Speak"), this, &MenuBar::ShowWiiSpeakWindow);
usb_device_menu->addAction(tr("&Logitech USB Microphone"), this, &MenuBar::ShowLogitechMicWindow);
usb_device_menu->addAction(tr("&Keyboard"), this, &MenuBar::ShowKeyboard);
tools_menu->addMenu(usb_device_menu);
tools_menu->addSeparator();

View File

@ -101,6 +101,7 @@ signals:
void ShowInfinityBase();
void ShowWiiSpeakWindow();
void ShowLogitechMicWindow();
void ShowKeyboard();
void ConnectWiiRemote(int id);
#ifdef USE_RETRO_ACHIEVEMENTS

View File

@ -945,6 +945,7 @@ void Settings::SetUSBKeyboardConnected(bool connected)
Common::KeyboardContext::NotifyInit();
else
Common::KeyboardContext::NotifyQuit();
emit USBKeyboardConnectionChanged(connected);
}
}

View File

@ -226,6 +226,7 @@ signals:
void AnalyticsToggled(bool enabled);
void ReleaseDevices();
void DevicesChanged();
void USBKeyboardConnectionChanged(bool connected);
void WiiSpeakMuteChanged(bool muted);
void EnableGfxModsChanged(bool enabled);

View File

@ -90,6 +90,12 @@ void WiiPane::CreateLayout()
void WiiPane::ConnectLayout()
{
// Emulate USB keyboard
connect(&Settings::Instance(), &Settings::USBKeyboardConnectionChanged,
m_connect_keyboard_checkbox, &QCheckBox::setChecked);
connect(m_connect_keyboard_checkbox, &QCheckBox::toggled, &Settings::Instance(),
&Settings::SetUSBKeyboardConnected);
// Whitelisted USB Passthrough Devices
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
&WiiPane::PopulateUSBPassthroughListWidget);