diff --git a/CMakeLists.txt b/CMakeLists.txt index 007c1ffd8..a6ffa89e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,7 @@ if(WIN32) # Default value for the `WIN32` target property, which specifies whether # to build the application for the Windows GUI or console subsystem - option(CMAKE_WIN32_EXECUTABLE "Build a Windows GUI executable" ON) + option(CMAKE_WIN32_EXECUTABLE "Build a Windows GUI executable" OFF) else() # Prefer dynamic builds everywhere else set(PREFER_STATIC OFF) diff --git a/src/86box.c b/src/86box.c index 168e8a8dc..dae2d4ba5 100644 --- a/src/86box.c +++ b/src/86box.c @@ -222,6 +222,37 @@ int other_ide_present = 0; /* IDE control int other_scsi_present = 0; /* SCSI controllers from non-SCSI cards are present */ +// Accelerator key array +struct accelKey acc_keys[NUM_ACCELS]; + +// Default accelerator key values +struct accelKey def_acc_keys[NUM_ACCELS] = { + { .name="send_ctrl_alt_del", .desc="Send Control+Alt+Del", + .seq="Ctrl+F12" }, + + { .name="send_ctrl_alt_esc", .desc="Send Control+Alt+Escape", + .seq="Ctrl+F10" }, + + { .name="fullscreen", .desc="Toggle fullscreen", + .seq="Ctrl+Alt+PgUp" }, + + { .name="screenshot", .desc="Screenshot", + .seq="Ctrl+F11" }, + + { .name="release_mouse", .desc="Release mouse pointer", + .seq="Ctrl+End" }, + + { .name="hard_reset", .desc="Hard reset", + .seq="Ctrl+Alt+F12" }, + + { .name="pause", .desc="Toggle pause", + .seq="Ctrl+Alt+F1" }, + + { .name="mute", .desc="Toggle mute", + .seq="Ctrl+Alt+M" } +}; + + /* Statistics. */ extern int mmuflush; extern int readlnum; @@ -654,7 +685,6 @@ usage: #ifdef USE_INSTRUMENT printf("-J or --instrument name - set 'name' to be the profiling instrument\n"); #endif - printf("-K or --keycodes codes - set 'codes' to be the uncapture combination\n"); printf("-L or --logfile path - set 'path' to be the logfile\n"); printf("-M or --missing - dump missing machines and video cards\n"); printf("-N or --noconfirm - do not ask for confirmation on quit\n"); @@ -745,13 +775,6 @@ usage: do_nothing = 1; } else if (!strcasecmp(argv[c], "--nohook") || !strcasecmp(argv[c], "-W")) { hook_enabled = 0; - } else if (!strcasecmp(argv[c], "--keycodes") || !strcasecmp(argv[c], "-K")) { - if ((c + 1) == argc) - goto usage; - - sscanf(argv[++c], "%03hX,%03hX,%03hX,%03hX,%03hX,%03hX", - &key_prefix_1_1, &key_prefix_1_2, &key_prefix_2_1, &key_prefix_2_2, - &key_uncapture_1, &key_uncapture_2); } else if (!strcasecmp(argv[c], "--clearboth") || !strcasecmp(argv[c], "-X")) { if ((c + 1) == argc) goto usage; @@ -1003,6 +1026,14 @@ usage: gdbstub_init(); + // Initialize the keyboard accelerator list with default values + for(int x=0;x + * Cacodemon345 + * + * Copyright 2021 Joakim L. Gilje + * Copyright 2022 Cacodemon345 + */ +#include "qt_keybind.hpp" +#include "ui_qt_keybind.h" +#include "qt_settings.hpp" +#include "qt_singlekeyseqedit.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include <86box/86box.h> +#include <86box/ini.h> +#include <86box/config.h> +#include <86box/device.h> +#include <86box/midi_rtmidi.h> +#include <86box/mem.h> +#include <86box/random.h> +#include <86box/rom.h> +} + +#include "qt_filefield.hpp" +#include "qt_models_common.hpp" +#ifdef Q_OS_LINUX +# include +# include +#endif +#ifdef Q_OS_WINDOWS +#include +#endif + +KeyBinder::KeyBinder(QWidget *parent) + : QDialog(parent) + , ui(new Ui::KeyBinder) +{ + ui->setupUi(this); + singleKeySequenceEdit *seq = new singleKeySequenceEdit(); + ui->formLayout->addRow(seq); + seq->setObjectName("keySequence"); + this->setTabOrder(seq, ui->buttonBox); +} + +KeyBinder::~KeyBinder() +{ + delete ui; +} + +void +KeyBinder::showEvent( QShowEvent* event ) { + QWidget::showEvent( event ); + this->findChild()->setFocus(); +} + +bool KeyBinder::eventFilter(QObject *obj, QEvent *event) +{ + return QObject::eventFilter(obj, event); +} + +QKeySequence +KeyBinder::BindKey(QString CurValue) +{ + KeyBinder kb; + kb.setWindowTitle("Bind Key"); + kb.setFixedSize(kb.minimumSizeHint()); + kb.findChild()->setKeySequence(QKeySequence::fromString(CurValue)); + + if (kb.exec() == QDialog::Accepted) { + QKeySequenceEdit *seq = kb.findChild(); + return (seq->keySequence()); + } else { + return (false); + } +} \ No newline at end of file diff --git a/src/qt/qt_keybind.hpp b/src/qt/qt_keybind.hpp new file mode 100644 index 000000000..e8e7b6e5e --- /dev/null +++ b/src/qt/qt_keybind.hpp @@ -0,0 +1,33 @@ +#ifndef QT_KeyBinder_HPP +#define QT_KeyBinder_HPP + +#include + +#include "qt_settings.hpp" + +extern "C" { +struct _device_; +} + +namespace Ui { +class KeyBinder; +} + +class Settings; + +class KeyBinder : public QDialog { + Q_OBJECT + +public: + explicit KeyBinder(QWidget *parent = nullptr); + ~KeyBinder() override; + + static QKeySequence BindKey(QString CurValue); + +private: + Ui::KeyBinder *ui; + bool eventFilter(QObject *obj, QEvent *event); + void showEvent( QShowEvent* event ); +}; + +#endif // QT_KeyBinder_HPP diff --git a/src/qt/qt_keybind.ui b/src/qt/qt_keybind.ui new file mode 100644 index 000000000..835e12020 --- /dev/null +++ b/src/qt/qt_keybind.ui @@ -0,0 +1,85 @@ + + + KeyBinder + + + + 0 + 0 + 400 + 103 + + + + Dialog + + + + + + + + Enter key combo: + + + Qt::AlignmentFlag::AlignCenter + + + + + + + + + Qt::Orientation::Horizontal + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + + + buttonBox + accepted() + KeyBinder + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + KeyBinder + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 760ca7d9b..1fb9b3fb5 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -139,6 +139,7 @@ namespace IOKit { # include "be_keyboard.hpp" extern MainWindow *main_window; +QShortcut *windowedShortcut; filter_result keyb_filter(BMessage *message, BHandler **target, BMessageFilter *filter) @@ -675,17 +676,6 @@ MainWindow::MainWindow(QWidget *parent) /* Remove default Shift+F10 handler, which unfocuses keyboard input even with no context menu. */ connect(new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F10), this), &QShortcut::activated, this, [](){}); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - auto windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_PageDown), this); -#else - auto windowedShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_PageDown), this); -#endif - windowedShortcut->setContext(Qt::ShortcutContext::ApplicationShortcut); - connect(windowedShortcut, &QShortcut::activated, this, [this] () { - if (video_fullscreen) - ui->actionFullscreen->trigger(); - }); - connect(this, &MainWindow::initRendererMonitor, this, &MainWindow::initRendererMonitorSlot); connect(this, &MainWindow::initRendererMonitorForNonQtThread, this, &MainWindow::initRendererMonitorSlot, Qt::BlockingQueuedConnection); connect(this, &MainWindow::destroyRendererMonitor, this, &MainWindow::destroyRendererMonitorSlot); @@ -761,6 +751,8 @@ MainWindow::MainWindow(QWidget *parent) }); } #endif + + updateShortcuts(); } void @@ -826,6 +818,57 @@ MainWindow::closeEvent(QCloseEvent *event) event->accept(); } + +void MainWindow::updateShortcuts() +{ + /* + Update menu shortcuts from accelerator table + + Note that these only work in windowed mode. If you add any new shortcuts, + you have to go duplicate them in MainWindow::eventFilter() + */ + + // First we need to wipe all existing accelerators, otherwise Qt will + // run into conflicts with old ones. + ui->actionTake_screenshot->setShortcut(QKeySequence()); + ui->actionCtrl_Alt_Del->setShortcut(QKeySequence()); + ui->actionCtrl_Alt_Esc->setShortcut(QKeySequence()); + ui->actionHard_Reset->setShortcut(QKeySequence()); + ui->actionPause->setShortcut(QKeySequence()); + ui->actionMute_Unmute->setShortcut(QKeySequence()); + + int accID; + QKeySequence seq; + + accID = FindAccelerator("screenshot"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionTake_screenshot->setShortcut(seq); + + accID = FindAccelerator("send_ctrl_alt_del"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionCtrl_Alt_Del->setShortcut(seq); + + accID = FindAccelerator("send_ctrl_alt_esc"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionCtrl_Alt_Esc->setShortcut(seq); + + accID = FindAccelerator("hard_reset"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionHard_Reset->setShortcut(seq); + + accID = FindAccelerator("fullscreen"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionFullscreen->setShortcut(seq); + + accID = FindAccelerator("pause"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionPause->setShortcut(seq); + + accID = FindAccelerator("mute"); + seq = QKeySequence::fromString(acc_keys[accID].seq); + ui->actionMute_Unmute->setShortcut(seq); +} + void MainWindow::resizeEvent(QResizeEvent *event) { @@ -1026,6 +1069,7 @@ MainWindow::on_actionSettings_triggered() case QDialog::Accepted: settings.save(); config_changed = 2; + updateShortcuts(); pc_reset_hard(); break; case QDialog::Rejected: @@ -1250,7 +1294,10 @@ MainWindow::on_actionFullscreen_triggered() if (video_fullscreen_first) { bool wasCaptured = mouse_capture == 1; - QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), tr("Press Ctrl+Alt+PgDn to return to windowed mode."), QMessageBox::Ok, this); + char strFullscreen[100]; + sprintf(strFullscreen, qPrintable(tr("Press %s to return to windowed mode.")), acc_keys[FindAccelerator("fullscreen")].seq); + + QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), QString(strFullscreen), QMessageBox::Ok, this); QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!video_fullscreen_first); @@ -1294,9 +1341,78 @@ MainWindow::getTitle(wchar_t *title) } } + +// Helper to find an accelerator key and return it's sequence +// TODO: Is there a more central place to put this? +QKeySequence +MainWindow::FindAcceleratorSeq(const char *name) +{ + int accID = FindAccelerator(name); + if(accID == -1) + return false; + + return(QKeySequence::fromString(acc_keys[accID].seq)); +} + bool MainWindow::eventFilter(QObject *receiver, QEvent *event) { + // Detect shortcuts when menubar is hidden + // TODO: Could this be simplified by proxying the event and manually + // shoving it into the menubar? + if (event->type() == QEvent::KeyPress) + { + this->keyPressEvent((QKeyEvent *) event); + + // We check for mouse release even if we aren't fullscreen, + // because it's not a menu accelerator. + if (event->type() == QEvent::KeyPress) + { + QKeyEvent *ke = (QKeyEvent *) event; + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("release_mouse")) + { + plat_mouse_capture(0); + } + } + + if (event->type() == QEvent::KeyPress && video_fullscreen != 0) + { + QKeyEvent *ke = (QKeyEvent *) event; + + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("screenshot")) + { + ui->actionTake_screenshot->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("fullscreen")) + { + ui->actionFullscreen->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("hard_reset")) + { + ui->actionHard_Reset->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("send_ctrl_alt_del")) + { + ui->actionCtrl_Alt_Del->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("send_ctrl_alt_esc")) + { + ui->actionCtrl_Alt_Esc->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("pause")) + { + ui->actionPause->trigger(); + } + if ((QKeySequence)(ke->key() | ke->modifiers()) == FindAcceleratorSeq("mute")) + { + ui->actionMute_Unmute->trigger(); + } + + return true; + } + } + + if (!dopause) { if (event->type() == QEvent::Shortcut) { auto shortcutEvent = (QShortcutEvent *) event; @@ -1306,8 +1422,8 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) } } if (event->type() == QEvent::KeyPress) { - event->accept(); - this->keyPressEvent((QKeyEvent *) event); + event->accept(); + return true; } if (event->type() == QEvent::KeyRelease) { @@ -1327,7 +1443,7 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) plat_pause(curdopause); } } - + return QMainWindow::eventFilter(receiver, event); } @@ -1393,10 +1509,7 @@ MainWindow::keyPressEvent(QKeyEvent *event) processKeyboardInput(true, event->nativeScanCode()); #endif } - - if (keyboard_ismsexit()) - plat_mouse_capture(0); - + event->accept(); } diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 739d179ff..5811ac36a 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -32,7 +33,10 @@ public: QSize getRenderWidgetSize(); void setSendKeyboardInput(bool enabled); void reloadAllRenderers(); - + QShortcut *windowedShortcut; + QKeySequence FindAcceleratorSeq(const char *name); + + std::array, 8> renderers; signals: void paint(const QImage &image); @@ -159,6 +163,7 @@ private: std::unique_ptr status; std::shared_ptr mm; + void updateShortcuts(); void processKeyboardInput(bool down, uint32_t keycode); #ifdef Q_OS_MACOS uint32_t last_modifiers = 0; @@ -184,7 +189,6 @@ private: friend class RendererStack; // For UI variable access by non-primary renderer windows. friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes. - bool isShowMessage = false; }; diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 0f792feda..26682528d 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -595,8 +595,14 @@ ProgSettings::reloadStrings() { translatedstrings.clear(); translatedstrings[STRING_MOUSE_CAPTURE] = QCoreApplication::translate("", "Click to capture mouse").toStdWString(); - translatedstrings[STRING_MOUSE_RELEASE] = QCoreApplication::translate("", "Press %1 to release mouse").arg(QCoreApplication::translate("", MOUSE_CAPTURE_KEYSEQ)).toStdWString(); - translatedstrings[STRING_MOUSE_RELEASE_MMB] = QCoreApplication::translate("", "Press %1 or middle button to release mouse").arg(QCoreApplication::translate("", MOUSE_CAPTURE_KEYSEQ)).toStdWString(); + + char mouseCaptureKeyseq[100]; + sprintf(mouseCaptureKeyseq, qPrintable(QCoreApplication::translate("", "Press %s to release mouse")), acc_keys[FindAccelerator("release_mouse")].seq); + translatedstrings[STRING_MOUSE_RELEASE] = QString(mouseCaptureKeyseq).toStdWString(); + + sprintf(mouseCaptureKeyseq, qPrintable(QCoreApplication::translate("", "Press %s or middle button to release mouse")), acc_keys[FindAccelerator("release_mouse")].seq); + translatedstrings[STRING_MOUSE_RELEASE_MMB] = QString(mouseCaptureKeyseq).toStdWString(); + translatedstrings[STRING_INVALID_CONFIG] = QCoreApplication::translate("", "Invalid configuration").toStdWString(); translatedstrings[STRING_NO_ST506_ESDI_CDROM] = QCoreApplication::translate("", "MFM/RLL or ESDI CD-ROM drives never existed").toStdWString(); translatedstrings[STRING_PCAP_ERROR_NO_DEVICES] = QCoreApplication::translate("", "No PCap devices found").toStdWString(); diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index d7c61e8d2..f87296451 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -16,8 +16,12 @@ */ #include "qt_settingsinput.hpp" #include "ui_qt_settingsinput.h" +#include "qt_mainwindow.hpp" +#include "qt_progsettings.hpp" #include +#include +#include extern "C" { #include <86box/86box.h> @@ -25,11 +29,18 @@ extern "C" { #include <86box/machine.h> #include <86box/mouse.h> #include <86box/gameport.h> +#include <86box/ui.h> } #include "qt_models_common.hpp" #include "qt_deviceconfig.hpp" #include "qt_joystickconfiguration.hpp" +#include "qt_keybind.hpp" + +extern MainWindow *main_window; + +// Temporary working copy of key list +accelKey acc_keys_t[NUM_ACCELS]; SettingsInput::SettingsInput(QWidget *parent) : QWidget(parent) @@ -37,9 +48,51 @@ SettingsInput::SettingsInput(QWidget *parent) { ui->setupUi(this); + QStandardItemModel *model; + QStringList horizontalHeader; + QStringList verticalHeader; + + horizontalHeader.append(tr("Action")); + horizontalHeader.append(tr("Keybind")); + + QTableWidget *keyTable = ui->tableKeys; + keyTable->setRowCount(10); + keyTable->setColumnCount(3); + keyTable->setColumnHidden(2, true); + keyTable->setColumnWidth(0, 200); + keyTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + QStringList headers; + //headers << "Action" << "Bound key"; + keyTable->setHorizontalHeaderLabels(headers); + keyTable->verticalHeader()->setVisible(false); + keyTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + keyTable->setSelectionBehavior(QAbstractItemView::SelectRows); + keyTable->setSelectionMode(QAbstractItemView::SingleSelection); + keyTable->setShowGrid(true); + + // Make a working copy of acc_keys so we can check for dupes later without getting + // confused + for(int x=0;xtableKeys, &QTableWidget::cellDoubleClicked, + this, &SettingsInput::on_tableKeys_doubleClicked); + + connect(ui->pushButtonBind, &QPushButton::clicked, + this, &SettingsInput::on_pushButtonBind_Clicked); + + connect(ui->pushButtonClearBind, &QPushButton::clicked, + this, &SettingsInput::on_pushButtonClearBind_Clicked); + onCurrentMachineChanged(machine); } + SettingsInput::~SettingsInput() { delete ui; @@ -50,8 +103,16 @@ SettingsInput::save() { mouse_type = ui->comboBoxMouse->currentData().toInt(); joystick_type = ui->comboBoxJoystick->currentData().toInt(); + + // Copy accelerators from working set to global set + for(int x=0;xcomboBoxJoystick->setCurrentIndex(selectedRow); } +void +SettingsInput::refreshInputList() +{ + + for (int x=0;xtableKeys->setItem(x, 0, new QTableWidgetItem(tr(acc_keys_t[x].desc))); + ui->tableKeys->setItem(x, 1, new QTableWidgetItem(acc_keys_t[x].seq)); + ui->tableKeys->setItem(x, 2, new QTableWidgetItem(acc_keys_t[x].name)); + } +} + +void +SettingsInput::on_tableKeys_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn) +{ + // Enable/disable bind/clear buttons if user clicked valid row + QTableWidgetItem *cell = ui->tableKeys->item(currentRow,1); + if (!cell) + { + ui->pushButtonBind->setEnabled(false); + ui->pushButtonClearBind->setEnabled(false); + } + else + { + ui->pushButtonBind->setEnabled(true); + ui->pushButtonClearBind->setEnabled(true); + } +} + +void +SettingsInput::on_tableKeys_doubleClicked(int row, int col) +{ + // Edit bind + QTableWidgetItem *cell = ui->tableKeys->item(row,1); + if (!cell) return; + + QKeySequence keyseq = KeyBinder::BindKey(cell->text()); + if (keyseq != false) { + // If no change was made, don't change anything. + if (keyseq.toString(QKeySequence::NativeText) == cell->text()) return; + + // Otherwise, check for conflicts. + // Check against the *working* copy - NOT the one in use by the app, + // so we don't test against shortcuts the user already changed. + for(int x=0;xshowMessage(MBX_ANSI & MBX_INFO, "Bind conflict", "This key combo is already in use", false); + return; + } + } + // If we made it here, there were no conflicts. + // Go ahead and apply the bind. + + // Find the correct accelerator key entry + int accKeyID = FindAccelerator(qPrintable(ui->tableKeys->item(row,2)->text())); + if (accKeyID < 0) return; // this should never happen + + // Make the change + cell->setText(keyseq.toString(QKeySequence::NativeText)); + strcpy(acc_keys_t[accKeyID].seq, qPrintable(keyseq.toString(QKeySequence::NativeText))); + + refreshInputList(); + } +} + +void +SettingsInput::on_pushButtonBind_Clicked() +{ + // Edit bind + QTableWidgetItem *cell = ui->tableKeys->currentItem(); + if (!cell) return; + + on_tableKeys_doubleClicked(cell->row(), cell->column()); +} + +void +SettingsInput::on_pushButtonClearBind_Clicked() +{ + // Wipe bind + QTableWidgetItem *cell = ui->tableKeys->currentItem(); + if (!cell) return; + + cell->setText(""); + // Find the correct accelerator key entry + int accKeyID = FindAccelerator(qPrintable(ui->tableKeys->item(cell->row(),2)->text())); + if (accKeyID < 0) return; // this should never happen + + // Make the change + cell->setText(""); + strcpy(acc_keys_t[accKeyID].seq, ""); +} + void SettingsInput::on_comboBoxMouse_currentIndexChanged(int index) { diff --git a/src/qt/qt_settingsinput.hpp b/src/qt/qt_settingsinput.hpp index 0b8b665aa..ec7dc393b 100644 --- a/src/qt/qt_settingsinput.hpp +++ b/src/qt/qt_settingsinput.hpp @@ -2,6 +2,12 @@ #define QT_SETTINGSINPUT_HPP #include +#include +#include +#include +#include +#include +#include namespace Ui { class SettingsInput; @@ -27,10 +33,15 @@ private slots: void on_pushButtonJoystick2_clicked(); void on_pushButtonJoystick3_clicked(); void on_pushButtonJoystick4_clicked(); + void on_tableKeys_doubleClicked(int row, int col); + void on_tableKeys_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn); + void on_pushButtonBind_Clicked(); + void on_pushButtonClearBind_Clicked(); private: Ui::SettingsInput *ui; int machineId = 0; + void refreshInputList(); }; #endif // QT_SETTINGSINPUT_HPP diff --git a/src/qt/qt_settingsinput.ui b/src/qt/qt_settingsinput.ui index 839461119..b7074eeaa 100644 --- a/src/qt/qt_settingsinput.ui +++ b/src/qt/qt_settingsinput.ui @@ -23,17 +23,16 @@ 0 - - - - Joystick 2... + + + + + 0 + 0 + - - - - - - Joystick: + + 30 @@ -44,13 +43,6 @@ - - - - Mouse: - - - @@ -58,21 +50,15 @@ - - - - Qt::Vertical + + + + false - - QSizePolicy::Expanding + + Bind - - - 20 - 40 - - - + @@ -81,6 +67,44 @@ + + + + 30 + + + + + + + Mouse: + + + + + + + false + + + Clear binding + + + + + + + Joystick: + + + + + + + Joystick 2... + + + @@ -94,23 +118,29 @@ - - - - 30 - - - - 0 - 0 - + + + + Key Bindings: - - - - 30 + + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + false + + + false + + + true + + + QAbstractItemView::SelectionBehavior::SelectRows diff --git a/src/qt/qt_singlekeyseqedit.cpp b/src/qt/qt_singlekeyseqedit.cpp new file mode 100644 index 000000000..f17d2164f --- /dev/null +++ b/src/qt/qt_singlekeyseqedit.cpp @@ -0,0 +1,20 @@ +#include "qt_singlekeyseqedit.hpp" + +/* + This subclass of QKeySequenceEdit restricts the input to only a single + shortcut instead of an unlimited number with a fixed timeout. +*/ + +singleKeySequenceEdit::singleKeySequenceEdit(QWidget *parent) : QKeySequenceEdit(parent) {} + +void singleKeySequenceEdit::keyPressEvent(QKeyEvent *event) +{ + QKeySequenceEdit::keyPressEvent(event); + if (this->keySequence().count() > 0) { + QKeySequenceEdit::setKeySequence(this->keySequence()); + + // This could have unintended consequences since it will happen + // every single time the user presses a key. + emit editingFinished(); + } +} \ No newline at end of file diff --git a/src/qt/qt_singlekeyseqedit.hpp b/src/qt/qt_singlekeyseqedit.hpp new file mode 100644 index 000000000..43ebe70b2 --- /dev/null +++ b/src/qt/qt_singlekeyseqedit.hpp @@ -0,0 +1,16 @@ +#ifndef SINGLEKEYSEQUENCEEDIT_H +#define SINGLEKEYSEQUENCEEDIT_H + +#include +#include + +class singleKeySequenceEdit : public QKeySequenceEdit +{ + Q_OBJECT +public: + singleKeySequenceEdit(QWidget *parent = nullptr); + + void keyPressEvent(QKeyEvent *) override; +}; + +#endif // SINGLEKEYSEQUENCEEDIT_H diff --git a/src/unix/unix.c b/src/unix/unix.c index 395e6f540..8e44cc26a 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -1338,9 +1338,6 @@ main(int argc, char **argv) } } } - if (mouse_capture && keyboard_ismsexit()) { - plat_mouse_capture(0); - } if (blitreq) { extern void sdl_blit(int x, int y, int w, int h); sdl_blit(params.x, params.y, params.w, params.h);