1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Undoes extra dependency, checks for X11 at runtime.

This commit is contained in:
Thomas Harte 2020-07-08 00:15:44 -04:00
parent 0763ae38dd
commit fa26c82273
3 changed files with 57 additions and 47 deletions

View File

@ -1,11 +1,5 @@
QT += core gui multimedia widgets
unix:!mac {
# For non-Mac UNIX targets, include X11 extras to check for X11.
# x11extras isn't supported on the Mac.
QT += x11extras
}
CONFIG += c++17
# Permit multiple source files in different directories to have the same file name.

View File

@ -765,54 +765,52 @@ void MainWindow::keyReleaseEvent(QKeyEvent *event) {
processEvent(event);
}
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
// Qt is the worst.
//
// Assume your keyboard has a key labelled both . and >, as they do on US and UK keyboards. Call it the dot key.
// Perform the following:
// 1. press dot key;
// 2. press shift key;
// 3. release dot key;
// 4. release shift key.
//
// Per empirical testing, and key repeat aside, on both macOS and Ubuntu 19.04 that sequence will result in
// _three_ keypress events, but only _two_ key release events. You'll get presses for Qt::Key_Period, Qt::Key_Greater
// and Qt::Key_Shift. You'll get releases only for Qt::Key_Greater and Qt::Key_Shift.
//
// How can you detect at runtime that Key_Greater and Key_Period are the same physical key?
//
// You can't. On Ubuntu they have the same values for QKeyEvent::nativeScanCode(), which are unique to the key,
// but they have different ::nativeVirtualKey()s.
//
// On macOS they have the same ::nativeScanCode() only because on macOS [almost] all keys have the same
// ::nativeScanCode(). So that's not usable. They have the same ::nativeVirtualKey()s, but since that isn't true
// on Ubuntu, that's also not usable.
//
// So how can you track the physical keys on a keyboard via Qt?
//
// You can't. Qt is the worst. SDL doesn't have this problem, including in X11, but I'm not sure I want the extra
// dependency. I may need to reassess.
#include <QX11Info>
std::optional<Inputs::Keyboard::Key> MainWindow::keyForEvent(QKeyEvent *event) {
// Workaround for X11: assume PC-esque mapping from ::nativeScanCode to symbols.
#endif
if(QGuiApplication::platformName() == QLatin1String("xcb")) {
#define BIND(code, key) case code: return Inputs::Keyboard::Key::key;
bool MainWindow::processEvent(QKeyEvent *event) {
if(!machine) return true;
switch(event->nativeVirtualKey()) {
default: qDebug() << "Unmapped" << event->nativeScanCode(); return {};
}
const auto keyboardMachine = machine->keyboard_machine();
if(!keyboardMachine) return true;
#undef BIND
}
// Qt is the worst.
//
// Assume your keyboard has a key labelled both . and >, as they do on US and UK keyboards. Call it the dot key.
// Perform the following:
// 1. press dot key;
// 2. press shift key;
// 3. release dot key;
// 4. release shift key.
//
// Per empirical testing, and key repeat aside, on both macOS and Ubuntu 19.04 that sequence will result in
// _three_ keypress events, but only _two_ key release events. You'll get presses for Qt::Key_Period, Qt::Key_Greater
// and Qt::Key_Shift. You'll get releases only for Qt::Key_Greater and Qt::Key_Shift.
//
// How can you detect at runtime that Key_Greater and Key_Period are the same physical key?
//
// You can't. On Ubuntu they have the same values for QKeyEvent::nativeScanCode(), which are unique to the key,
// but they have different ::nativeVirtualKey()s.
//
// On macOS they have the same ::nativeScanCode() only because on macOS [almost] all keys have the same
// ::nativeScanCode(). So that's not usable. They have the same ::nativeVirtualKey()s, but since that isn't true
// on Ubuntu, that's also not usable.
//
// So how can you track the physical keys on a keyboard via Qt?
//
// You can't. Qt is the worst. SDL doesn't have this problem, including in X11, so this seems to be a problem
// Qt has invented for itself.
// Workaround for X11: assume
// QX11Info::isPlatformX11();
#define BIND2(qtKey, clkKey) case Qt::qtKey: key = Inputs::Keyboard::Key::clkKey; break;
// Fall back on a limited, faulty adaptation.
#define BIND2(qtKey, clkKey) case Qt::qtKey: return Inputs::Keyboard::Key::clkKey;
#define BIND(key) BIND2(Key_##key, key)
Inputs::Keyboard::Key key;
switch(event->key()) {
default: return true;
default: return {};
BIND(Escape);
BIND(F1); BIND(F2); BIND(F3); BIND(F4); BIND(F5); BIND(F6);
@ -862,8 +860,22 @@ bool MainWindow::processEvent(QKeyEvent *event) {
BIND(NumLock);
}
#undef BIND
#undef BIND2
}
bool MainWindow::processEvent(QKeyEvent *event) {
if(!machine) return true;
const auto keyboardMachine = machine->keyboard_machine();
if(!keyboardMachine) return true;
const auto key = keyForEvent(event);
if(!key) return true;
std::unique_lock lock(machineMutex);
keyboardMachine->get_keyboard().set_key_pressed(key, event->text().size() ? event->text()[0].toLatin1() : '\0', event->type() == QEvent::KeyPress);
keyboardMachine->get_keyboard().set_key_pressed(*key, event->text().size() ? event->text()[0].toLatin1() : '\0', event->type() == QEvent::KeyPress);
return false;
}

View File

@ -5,6 +5,8 @@
#include <QMainWindow>
#include <memory>
#include <optional>
#include "audiobuffer.h"
#include "timer.h"
#include "ui_mainwindow.h"
@ -127,6 +129,8 @@ class MainWindow : public QMainWindow, public Outputs::Speaker::Speaker::Delegat
QMenu *helpMenu = nullptr;
void addHelpMenu();
std::optional<Inputs::Keyboard::Key> keyForEvent(QKeyEvent *);
};
#endif // MAINWINDOW_H