Render emulator output on main window

Introduce hardware renderer
This commit is contained in:
Cacodemon345
2021-11-30 16:26:49 +06:00
parent 668887a30a
commit 0108c93e2d
9 changed files with 888 additions and 163 deletions

View File

@@ -6,6 +6,11 @@ set(CMAKE_AUTORCC ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
set(UI_EXTRA_FILES)
if (APPLE)
set(UI_EXTRA_FILES "macos_event_filter.mm")
endif()
add_library(plat STATIC qt.c qt_main.cpp qt_platform.cpp qt_midi.cpp cpp11_thread.cpp) add_library(plat STATIC qt.c qt_main.cpp qt_platform.cpp qt_midi.cpp cpp11_thread.cpp)
add_library(ui STATIC add_library(ui STATIC
qt_ui.cpp qt_ui.cpp
@@ -18,6 +23,10 @@ add_library(ui STATIC
qt_machinestatus.cpp qt_machinestatus.cpp
qt_machinestatus.hpp qt_machinestatus.hpp
qt_machinestatus.ui qt_machinestatus.ui
qt_gleswidget.cpp
qt_gleswidget.hpp
${UI_EXTRA_FILES}
qt_settings.cpp qt_settings.cpp
qt_settings.hpp qt_settings.hpp
@@ -89,3 +98,8 @@ target_link_libraries(
Qt5::Widgets Qt5::Widgets
Threads::Threads Threads::Threads
) )
if (NOT APPLE)
find_package(X11 REQUIRED)
target_link_libraries(ui PRIVATE X11::X11)
endif()

10
src/qt/cocoa_mouse.hpp Normal file
View File

@@ -0,0 +1,10 @@
#include <QAbstractNativeEventFilter>
#include <QByteArray>
class CocoaEventFilter : public QAbstractNativeEventFilter
{
public:
CocoaEventFilter() {};
~CocoaEventFilter();
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
};

View File

@@ -0,0 +1,107 @@
#include <SDL.h>
#include "86box/plat.h"
#include "cocoa_mouse.hpp"
#import <AppKit/AppKit.h>
extern "C"
{
#include <86box/86box.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>
#include <86box/config.h>
//#include <86box/plat.h>
#include <86box/plat_dynld.h>
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/ui.h>
#include <86box/video.h>
extern int mouse_capture;
}
typedef struct mouseinputdata
{
int deltax, deltay, deltaz;
int mousebuttons;
} mouseinputdata;
extern SDL_mutex* mousemutex;
extern mouseinputdata mousedata;
CocoaEventFilter::~CocoaEventFilter()
{
}
bool CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
if (mouse_capture)
{
if (eventType == "mac_generic_NSEvent")
{
NSEvent* event = (NSEvent*)message;
if ([event type] == NSEventTypeMouseMoved)
{
SDL_LockMutex(mousemutex);
mousedata.deltax += [event deltaX];
mousedata.deltay += [event deltaY];
SDL_UnlockMutex(mousemutex);
return true;
}
if ([event type] == NSEventTypeScrollWheel)
{
SDL_LockMutex(mousemutex);
mousedata.deltaz += [event deltaY];
SDL_UnlockMutex(mousemutex);
return true;
}
switch ([event type])
{
default: return false;
case NSEventTypeLeftMouseDown:
{
SDL_LockMutex(mousemutex);
mousedata.mousebuttons |= 1;
SDL_UnlockMutex(mousemutex);
break;
}
case NSEventTypeLeftMouseUp:
{
SDL_LockMutex(mousemutex);
mousedata.mousebuttons &= ~1;
SDL_UnlockMutex(mousemutex);
break;
}
case NSEventTypeRightMouseDown:
{
SDL_LockMutex(mousemutex);
mousedata.mousebuttons |= 2;
SDL_UnlockMutex(mousemutex);
break;
}
case NSEventTypeRightMouseUp:
{
SDL_LockMutex(mousemutex);
mousedata.mousebuttons &= ~2;
SDL_UnlockMutex(mousemutex);
break;
}
case NSEventTypeOtherMouseDown:
{
SDL_LockMutex(mousemutex);
mousedata.mousebuttons |= 4;
SDL_UnlockMutex(mousemutex);
break;
}
case NSEventTypeOtherMouseUp:
{
if (mouse_get_buttons() < 3) { plat_mouse_capture(0); return true; }
SDL_LockMutex(mousemutex);
mousedata.mousebuttons &= ~4;
SDL_UnlockMutex(mousemutex);
break;
}
}
return true;
}
}
return false;
}

154
src/qt/qt_gleswidget.cpp Normal file
View File

@@ -0,0 +1,154 @@
#include <SDL.h>
#include <QApplication>
#include "qt_gleswidget.hpp"
#ifdef __APPLE__
#include <CoreGraphics/CoreGraphics.h>
#endif
extern "C"
{
#include <86box/mouse.h>
#include <86box/plat.h>
#include <86box/video.h>
}
typedef struct mouseinputdata
{
int deltax, deltay, deltaz;
int mousebuttons;
} mouseinputdata;
mouseinputdata mousedata;
SDL_mutex* mousemutex;
void
qt_mouse_capture(int on)
{
if (!on)
{
mouse_capture = 0;
QApplication::setOverrideCursor(Qt::ArrowCursor);
#ifdef __APPLE__
CGAssociateMouseAndMouseCursorPosition(true);
#endif
return;
}
mouse_capture = 1;
QApplication::setOverrideCursor(Qt::BlankCursor);
#ifdef __APPLE__
CGAssociateMouseAndMouseCursorPosition(false);
#endif
return;
}
void qt_mouse_poll()
{
SDL_LockMutex(mousemutex);
mouse_x = mousedata.deltax;
mouse_y = mousedata.deltay;
mouse_z = mousedata.deltaz;
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
mouse_buttons = mousedata.mousebuttons;
SDL_UnlockMutex(mousemutex);
}
void GLESWidget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void GLESWidget::initializeGL()
{
initializeOpenGLFunctions();
}
void GLESWidget::paintGL()
{
QPainter painter(this);
//painter.fillRect(rect, QColor(0, 0, 0));
painter.drawImage(QRect(0, 0, width(), height()), m_image.convertToFormat(QImage::Format_RGBA8888), QRect(sx, sy, sw, sh));
painter.end();
update();
}
void GLESWidget::mouseReleaseEvent(QMouseEvent *event)
{
if (this->geometry().contains(event->pos()) && event->button() == Qt::LeftButton && !mouse_capture)
{
this->grabMouse();
return;
}
if (mouse_capture && event->button() == Qt::MiddleButton && mouse_get_buttons() < 3)
{
this->releaseMouse();
return;
}
if (mouse_capture)
{
SDL_LockMutex(mousemutex);
mousedata.mousebuttons &= ~event->button();
SDL_UnlockMutex(mousemutex);
}
}
void GLESWidget::mousePressEvent(QMouseEvent *event)
{
if (mouse_capture)
{
SDL_LockMutex(mousemutex);
mousedata.mousebuttons |= event->button();
SDL_UnlockMutex(mousemutex);
}
}
void GLESWidget::wheelEvent(QWheelEvent *event)
{
if (mouse_capture)
{
SDL_LockMutex(mousemutex);
mousedata.deltay += event->pixelDelta().y();
SDL_UnlockMutex(mousemutex);
}
}
int ignoreNextMouseEvent = 0;
void GLESWidget::mouseMoveEvent(QMouseEvent *event)
{
if (!mouse_capture) { event->ignore(); return; }
#ifdef __APPLE__
event->accept();
return;
#else
static QPoint oldPos = QCursor::pos();
if (ignoreNextMouseEvent) { oldPos = event->pos(); ignoreNextMouseEvent--; event->accept(); return; }
SDL_LockMutex(mousemutex);
mousedata.deltax += event->pos().x() - oldPos.x();
mousedata.deltay += event->pos().y() - oldPos.y();
SDL_UnlockMutex(mousemutex);
QCursor::setPos(mapToGlobal(QPoint(width() / 2, height() / 2)));
oldPos = event->pos();
ignoreNextMouseEvent = 1;
#endif
}
void GLESWidget::qt_real_blit(int x, int y, int w, int h)
{
// printf("Offpainter thread ID: %X\n", SDL_ThreadID());
if ((w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL))
{
video_blit_complete();
return;
}
sx = x;
sy = y;
sw = this->w = w;
sh = this->h = h;
auto imagebits = m_image.bits();
for (int y1 = y; y1 < (y + h - 1); y1++)
{
auto scanline = imagebits + (y1 * (2048 + 64) * 4);
video_copy(scanline + (x * 4), &(buffer32->line[y1][x]), w * 4);
}
if (screenshots)
{
video_screenshot((uint32_t *)imagebits, 0, 0, 2048 + 64);
}
video_blit_complete();
}

41
src/qt/qt_gleswidget.hpp Normal file
View File

@@ -0,0 +1,41 @@
#include <QOpenGLFunctions>
#include <QOpenGLWidget>
#include <QPainter>
#include <QEvent>
#include <QKeyEvent>
class GLESWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
private:
QImage m_image{QSize(2048 + 64, 2048 + 64), QImage::Format_RGB32};
int x, y, w, h, sx, sy, sw, sh;
public:
void resizeGL(int w, int h) override;
void initializeGL() override;
void paintGL() override;
GLESWidget(QWidget* parent = nullptr)
: QOpenGLWidget(parent)
{
setMinimumSize(16, 16);
}
~GLESWidget()
{
makeCurrent();
}
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent *event) override;
void keyPressEvent(QKeyEvent* event) override
{
event->ignore();
}
void keyReleaseEvent(QKeyEvent* event) override
{
event->ignore();
}
public slots:
void qt_real_blit(int x, int y, int w, int h);
};

View File

@@ -11,8 +11,11 @@
#include <thread> #include <thread>
#include "SDL.h"
#include "SDL_mutex.h"
#include "qt_mainwindow.hpp" #include "qt_mainwindow.hpp"
#include "qt_sdl.h" #include "qt_sdl.h"
#include "cocoa_mouse.hpp"
// Void Cast // Void Cast
@@ -73,9 +76,16 @@ main_thread_fn()
is_quit = 1; is_quit = 1;
} }
extern SDL_mutex* mousemutex;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
QApplication app(argc, argv); QApplication app(argc, argv);
#ifdef __APPLE__
CocoaEventFilter cocoafilter;
app.installNativeEventFilter(&cocoafilter);
#endif
elapsed_timer.start(); elapsed_timer.start();
SDL_Init(SDL_INIT_TIMER);
mousemutex = SDL_CreateMutex();
main_window = new MainWindow(); main_window = new MainWindow();
main_window->show(); main_window->show();
@@ -91,6 +101,7 @@ int main(int argc, char* argv[]) {
// plat_pause(0); // plat_pause(0);
/* Initialize the rendering window, or fullscreen. */ /* Initialize the rendering window, or fullscreen. */
QTimer::singleShot(50, []() { plat_resize(640, 480); } );
auto main_thread = std::thread([] { auto main_thread = std::thread([] {
main_thread_fn(); main_thread_fn();
}); });

View File

@@ -1,10 +1,14 @@
#include "qt_mainwindow.hpp" #include "qt_mainwindow.hpp"
#include "ui_qt_machinestatus.h"
#include "ui_qt_mainwindow.h" #include "ui_qt_mainwindow.h"
#include <qevent.h>
extern "C" { extern "C" {
#include <86box/86box.h> #include <86box/86box.h>
#include <86box/config.h> #include <86box/config.h>
#include <86box/keyboard.h>
#include <86box/plat.h> #include <86box/plat.h>
#include <86box/video.h>
#include "qt_sdl.h" #include "qt_sdl.h"
}; };
@@ -16,7 +20,19 @@ extern "C" {
#include <QKeyEvent> #include <QKeyEvent>
#include <QMessageBox> #include <QMessageBox>
#include <array>
#include "qt_settings.hpp" #include "qt_settings.hpp"
#include "qt_gleswidget.hpp"
#ifdef __unix__
#include <X11/Xlib.h>
#include <X11/keysym.h>
#endif
extern void qt_mouse_poll();
extern void qt_mouse_capture(int);
extern "C" void qt_blit(int x, int y, int w, int h);
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
@@ -25,25 +41,36 @@ MainWindow::MainWindow(QWidget *parent) :
Q_INIT_RESOURCE(qt_resources); Q_INIT_RESOURCE(qt_resources);
ui->setupUi(this); ui->setupUi(this);
video_setblit(qt_blit);
this->hw_widget = new GLESWidget(this);
this->hw_widget->setMouseTracking(true);
this->hw_widget->setGeometry(QRect(this->menuWidget() ? QPoint(0,this->menuWidget()->size().height()) : QPoint(0,0), QSize(640, 480)));
this->setCentralWidget(this->hw_widget);
connect(this, &MainWindow::blitToWidget, (GLESWidget*)this->hw_widget, &GLESWidget::qt_real_blit);
connect(this, &MainWindow::showMessageForNonQtThread, this, &MainWindow::showMessage_, Qt::BlockingQueuedConnection); connect(this, &MainWindow::showMessageForNonQtThread, this, &MainWindow::showMessage_, Qt::BlockingQueuedConnection);
connect(this, &MainWindow::pollMouse, this, [] { connect(this, &MainWindow::pollMouse, this, [] {
sdl_mouse_poll(); qt_mouse_poll();
}); });
connect(this, &MainWindow::setMouseCapture, this, [](bool state) { connect(this, &MainWindow::setMouseCapture, this, [this](bool state) {
mouse_capture = state ? 1 : 0; mouse_capture = state ? 1 : 0;
sdl_mouse_capture(mouse_capture); qt_mouse_capture(mouse_capture);
if (mouse_capture) hw_widget->grabMouse();
else hw_widget->releaseMouse();
}); });
connect(this, &MainWindow::setFullscreen, this, [](bool state) { connect(this, &MainWindow::setFullscreen, this, [this](bool state) {
video_fullscreen = state ? 1 : 0; video_fullscreen = state ? 1 : 0;
sdl_set_fs(video_fullscreen); //sdl_set_fs(video_fullscreen);
this->setFullscreen(state);
}); });
connect(this, &MainWindow::resizeContents, this, [this](int w, int h) { connect(this, &MainWindow::resizeContents, this, [this](int w, int h) {
sdl_resize(w, h); this->hw_widget->resize(w, h);
this->resize(w, h + menuBar()->height() + statusBar()->height());
}); });
connect(ui->menubar, &QMenuBar::triggered, this, [] { connect(ui->menubar, &QMenuBar::triggered, this, [] {
@@ -56,7 +83,7 @@ MainWindow::MainWindow(QWidget *parent) :
ui->actionKeyboard_requires_capture->setChecked(kbd_req_capture); ui->actionKeyboard_requires_capture->setChecked(kbd_req_capture);
ui->actionRight_CTRL_is_left_ALT->setChecked(rctrl_is_lalt); ui->actionRight_CTRL_is_left_ALT->setChecked(rctrl_is_lalt);
#if 0
sdl_inits(); sdl_inits();
sdl_timer = new QTimer(this); sdl_timer = new QTimer(this);
connect(sdl_timer, &QTimer::timeout, this, [] { connect(sdl_timer, &QTimer::timeout, this, [] {
@@ -66,10 +93,13 @@ MainWindow::MainWindow(QWidget *parent) :
} }
}); });
sdl_timer->start(5); sdl_timer->start(5);
#endif
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
sdl_close(); //sdl_close();
startblit();
//delete hw_widget;
delete ui; delete ui;
} }
@@ -123,165 +153,494 @@ void MainWindow::on_actionSettings_triggered() {
} }
} }
static const int keycode_entries = 136; std::array<uint32_t, 256> x11_to_xt_base
// xmodmap -pk {
static const uint16_t xfree86_keycode_table[keycode_entries] = { 0,
/* 0 */ 0, 0,
/* 1 */ 0, 0,
/* 2 */ 0, 0,
/* 3 */ 0, 0,
/* 4 */ 0, 0,
/* 5 */ 0, 0,
/* 6 */ 0, 0,
/* 7 */ 0, 0,
/* 8 */ 0, 0x01,
/* 9 */ 0x01, // Esc 0x02,
/* 10 */ 0x02, // 1 0x03,
/* 11 */ 0x03, // 2 0x04,
/* 12 */ 0x04, // 3 0x05,
/* 13 */ 0x05, // 4 0x06,
/* 14 */ 0x06, // 5 0x07,
/* 15 */ 0x07, // 6 0x08,
/* 16 */ 0x08, // 7 0x09,
/* 17 */ 0x09, // 8 0x0A,
/* 18 */ 0x0a, // 9 0x0B,
/* 19 */ 0x0b, // 0 0x0C,
/* 20 */ 0x0c, // - 0x0D,
/* 21 */ 0x0d, // = 0x0E,
/* 22 */ 0x0e, // BackSpace 0x0F,
/* 23 */ 0x0f, // Tab 0x10,
/* 24 */ 0x10, // Q 0x11,
/* 25 */ 0x11, // W 0x12,
/* 26 */ 0x12, // E 0x13,
/* 27 */ 0x13, // R 0x14,
/* 28 */ 0x14, // T 0x15,
/* 29 */ 0x15, // Y 0x16,
/* 30 */ 0x16, // U 0x17,
/* 31 */ 0x17, // I 0x18,
/* 32 */ 0x18, // O 0x19,
/* 33 */ 0x19, // P 0x1A,
/* 34 */ 0x1a, // [ 0x1B,
/* 35 */ 0x1b, // ] 0x1C,
/* 36 */ 0x1c, // Return 0x1D,
/* 37 */ 0x1d, // LeftControl 0x1E,
/* 38 */ 0x1e, // A 0x1F,
/* 39 */ 0x1f, // S 0x20,
/* 40 */ 0x20, // D 0x21,
/* 41 */ 0x21, // F 0x22,
/* 42 */ 0x22, // G 0x23,
/* 43 */ 0x23, // H 0x24,
/* 44 */ 0x24, // J 0x25,
/* 45 */ 0x25, // K 0x26,
/* 46 */ 0x26, // L 0x27,
/* 47 */ 0x27, // ; 0x28,
/* 48 */ 0x28, // ' 0x29,
/* 49 */ 0x29, // ` (???) 0x2A,
/* 50 */ 0x2a, // LeftShift 0x2B,
/* 51 */ 0x2b, // BackSlash 0x2C,
/* 52 */ 0x2c, // Z 0x2D,
/* 53 */ 0x2d, // X 0x2E,
/* 54 */ 0x2e, // C 0x2F,
/* 55 */ 0x2f, // V 0x30,
/* 56 */ 0x30, // B 0x31,
/* 57 */ 0x31, // N 0x32,
/* 58 */ 0x32, // M 0x33,
/* 59 */ 0x33, // , 0x34,
/* 60 */ 0x34, // . 0x35,
/* 61 */ 0x35, // - 0x36,
/* 62 */ 0x36, // RightShift 0x37,
/* 63 */ 0x37, // KeyPad Multiply 0x38,
/* 64 */ 0x38, // LeftAlt 0x39,
/* 65 */ 0x39, // Space 0x3A,
/* 66 */ 0x3a, // CapsLock 0x3B,
/* 67 */ 0x3b, // F01 0x3C,
/* 68 */ 0x3c, // F02 0x3D,
/* 69 */ 0x3d, // F03 0x3E,
/* 70 */ 0x3e, // F04 0x3F,
/* 71 */ 0x3f, // F05 0x40,
/* 72 */ 0x40, // F06 0x41,
/* 73 */ 0x41, // F07 0x42,
/* 74 */ 0x42, // F08 0x43,
/* 75 */ 0x43, // F09 0x44,
/* 76 */ 0x44, // F10 0x45,
/* 77 */ 0x45, // NumLock 0x46,
/* 78 */ 0x46, // ScrollLock 0x47,
/* 79 */ 0x47, // KeyPad7 0x48,
/* 80 */ 0x48, // KeyPad8 0x49,
/* 81 */ 0x49, // KeyPad9 0x4A,
/* 82 */ 0x4a, // KeyPad Minus 0x4B,
/* 83 */ 0x4b, // KeyPad4 0x4C,
/* 84 */ 0x4c, // KeyPad5 0x4D,
/* 85 */ 0x4d, // KeyPad6 0x4E,
/* 86 */ 0x4e, // KeyPad Plus 0x4F,
/* 87 */ 0x4f, // KeyPad1 0x50,
/* 88 */ 0x50, // KeyPad2 0x51,
/* 89 */ 0x51, // KeyPad3 0x52,
/* 90 */ 0x52, // KeyPad0 0x53,
/* 91 */ 0x53, // KeyPad . 0x54,
/* 92 */ 0, 0x55,
/* 93 */ 0, 0x56,
/* 94 */ 0x56, // Less/Great 0x57,
/* 95 */ 0x57, // F11 0x58,
/* 96 */ 0x58, // F12 0x147,
/* 97 */ 0, 0x148,
/* 98 */ 0, 0x149,
/* 99 */ 0, 0,
/* 100 */ 0, 0x14B,
/* 101 */ 0, 0,
/* 102 */ 0, 0x14D,
/* 103 */ 0, 0x14F,
/* 104 */ 0x11c, // KeyPad Enter 0x150,
/* 105 */ 0x11d, // RightControl 0x151,
/* 106 */ 0x135, // KeyPad Divide 0x152,
/* 107 */ 0x137, // PrintScreen / SysReq 0x153,
/* 108 */ 0x138, // RightAlt 0x11C,
/* 109 */ 0, 0x11D,
/* 110 */ 0x147, // Home 0, // Pause/Break key.
/* 111 */ 0x148, // Up 0x137,
/* 112 */ 0x149, // PageUp 0x135,
/* 113 */ 0x14b, // Left 0x138,
/* 114 */ 0x14d, // Right 0, // Ditto as above comment.
/* 115 */ 0x14f, // End 0x15B,
/* 116 */ 0x150, // Down 0x15C,
/* 117 */ 0x151, // PageDown 0x15D,
/* 118 */ 0x152, // Insert
/* 119 */ 0x153, // Delete
/* 120 */ 0,
/* 121 */ 0,
/* 122 */ 0,
/* 123 */ 0,
/* 124 */ 0,
/* 125 */ 0,
/* 126 */ 0,
/* 127 */ 0,
/* 128 */ 0,
/* 129 */ 0,
/* 130 */ 0,
/* 131 */ 0,
/* 132 */ 0,
/* 133 */ 0x15b, // SuperLeft
/* 134 */ 0x15c, // SuperRight
/* 135 */ 0x15d, // Application
}; };
//static void handle_keypress_event(int state, quint32 native_scancode) { std::array<uint32_t, 256> x11_to_xt_2
// if (native_scancode > keycode_entries) { {
// return; 0,
// } 0,
// uint16_t translated_code = xfree86_keycode_table[native_scancode]; 0,
// if (translated_code == 0) { 0,
// return; 0,
// } 0,
// keyboard_input(state, translated_code); 0,
0,
0,
0x01,
0x02,
0x03,
0x04,
0x05,
0x06,
0x07,
0x08,
0x09,
0x0A,
0x0B,
0x0C,
0x0D,
0x0E,
0x0F,
0x10,
0x11,
0x12,
0x13,
0x14,
0x15,
0x16,
0x17,
0x18,
0x19,
0x1A,
0x1B,
0x1C,
0x1D,
0x1E,
0x1F,
0x20,
0x21,
0x22,
0x23,
0x24,
0x25,
0x26,
0x27,
0x28,
0x29,
0x2A,
0x2B,
0x2C,
0x2D,
0x2E,
0x2F,
0x30,
0x31,
0x32,
0x33,
0x34,
0x35,
0x36,
0x37,
0x38,
0x39,
0x3A,
0x3B,
0x3C,
0x3D,
0x3E,
0x3F,
0x40,
0x41,
0x42,
0x43,
0x44,
0x45,
0x46,
0x47,
0x48,
0x49,
0x4A,
0x4B,
0x4C,
0x4D,
0x4E,
0x4F,
0x50,
0x51,
0x52,
0x53,
0x54,
0x55,
0x56,
0x57,
0x58,
0,
0,
0,
0,
0,
0,
0,
0x11C,
0x11D,
0x135,
0x137,
0x138,
0,
0x147,
0x148,
0x149,
0x14B,
0x14D,
0x14F,
0x150,
0x151,
0x152,
0x153
};
// if (keyboard_isfsexit() > 0) { std::array<uint32_t, 256> x11_to_xt_vnc
// plat_setfullscreen(0); {
// } 0,
0,
0,
0,
0,
0,
0,
0,
0,
0x1D,
0x11D,
0x2A,
0x36,
0,
0,
0x38,
0x138,
0x39,
0x0B,
0x02,
0x03,
0x04,
0x05,
0x06,
0x07,
0x08,
0x09,
0x0A,
0x0C,
0x0D,
0x1A,
0x1B,
0x27,
0x28,
0x29,
0x33,
0x34,
0x35,
0x2B,
0x1E,
0x30,
0x2E,
0x20,
0x12,
0x21,
0x22,
0x23,
0x17,
0x24,
0x25,
0x26,
0x32,
0x31,
0x18,
0x19,
0x10,
0x13,
0x1F,
0x14,
0x16,
0x2F,
0x11,
0x2D,
0x15,
0x2C,
0x0E,
0x1C,
0x0F,
0x01,
0x153,
0x147,
0x14F,
0x149,
0x151,
0x148,
0x150,
0x14B,
0x14D,
};
// if (keyboard_ismsexit() > 0) { std::array<uint32_t, 256> darwin_to_xt
// plat_mouse_capture(0); {
// } 0x1E,
//} 0x1F,
0x20,
0x21,
0x23,
0x22,
0x2C,
0x2D,
0x2E,
0x2F,
0x2B,
0x30,
0x10,
0x11,
0x12,
0x13,
0x15,
0x14,
0x02,
0x03,
0x04,
0x05,
0x07,
0x06,
0x0D,
0x0A,
0x08,
0x0C,
0x09,
0x0B,
0x1B,
0x18,
0x16,
0x1A,
0x17,
0x19,
0x1C,
0x26,
0x24,
0x28,
0x25,
0x27,
0x2B,
0x33,
0x35,
0x31,
0x32,
0x34,
0x0F,
0x39,
0x29,
0x0E,
0x11C,
0x01,
0x15C,
0x15B,
0x2A,
0x3A,
0x38,
0x1D,
0x36,
0x138,
0x11D,
0x15C,
0,
0x53,
0,
0x37,
0,
0x4E,
0,
0x45,
0x130,
0x12E,
0x120,
0x135,
0x11C,
0,
0x4A,
0,
0,
0,
0x52,
0x4F,
0x50,
0x51,
0x4B,
0x4C,
0x4D,
0x47,
0,
0x48,
0x49,
0,
0,
0,
0x3F,
0x40,
0x41,
0x3D,
0x42,
0x43,
0,
0x57,
0,
0x137,
0,
0x46,
0,
0x44,
0x15D,
0x58,
0,
0, // Pause/Break key.
0x152,
0x147,
0x149,
0x153,
0x3E,
0x14F,
0x3C,
0x151,
0x3B,
0x14B,
0x14D,
0x150,
0x148,
0,
};
static std::array<uint32_t, 256>& selected_keycode = x11_to_xt_base;
uint16_t x11_keycode_to_keysym(uint32_t keycode)
{
#ifdef __APPLE__
return darwin_to_xt[keycode];
#else
static Display* x11display = nullptr;
if (QApplication::platformName().contains("wayland"))
{
selected_keycode = x11_to_xt_2;
}
else if (!x11display)
{
x11display = XOpenDisplay(nullptr);
if (XKeysymToKeycode(x11display, XK_Home) == 110)
{
selected_keycode = x11_to_xt_2;
}
else if (XKeysymToKeycode(x11display, XK_Home) == 69)
{
selected_keycode = x11_to_xt_vnc;
}
}
return selected_keycode[keycode];
#endif
}
void MainWindow::on_actionFullscreen_triggered() { void MainWindow::on_actionFullscreen_triggered() {
setFullscreen(true); setFullscreen(true);
@@ -299,3 +658,21 @@ void MainWindow::showMessage_(const QString &header, const QString &message) {
QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this); QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this);
box.exec(); box.exec();
} }
void MainWindow::keyPressEvent(QKeyEvent* event)
{
#ifdef __APPLE__
keyboard_input(1, x11_keycode_to_keysym(event->nativeVirtualKey()));
#else
keyboard_input(1, x11_keycode_to_keysym(event->nativeScanCode()));
#endif
}
void MainWindow::keyReleaseEvent(QKeyEvent* event)
{
#ifdef __APPLE__
keyboard_input(0, x11_keycode_to_keysym(event->nativeVirtualKey()));
#else
keyboard_input(0, x11_keycode_to_keysym(event->nativeScanCode()));
#endif
}

View File

@@ -3,6 +3,7 @@
#include <QMainWindow> #include <QMainWindow>
#include <QLabel> #include <QLabel>
#include <qevent.h>
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
@@ -19,6 +20,7 @@ public:
void showMessage(const QString& header, const QString& message); void showMessage(const QString& header, const QString& message);
signals: signals:
void paint(const QImage& image); void paint(const QImage& image);
void blitToWidget(int x, int y, int w, int h);
void resizeContents(int w, int h); void resizeContents(int w, int h);
void pollMouse(); void pollMouse();
void updateStatusBarPanes(); void updateStatusBarPanes();
@@ -41,6 +43,9 @@ private slots:
void on_actionKeyboard_requires_capture_triggered(); void on_actionKeyboard_requires_capture_triggered();
void showMessage_(const QString& header, const QString& message); void showMessage_(const QString& header, const QString& message);
protected:
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
private: private:
struct DeltaPos { struct DeltaPos {
int x = 0; int x = 0;
@@ -51,6 +56,7 @@ private:
DeltaPos mouseDelta; DeltaPos mouseDelta;
QWindow* sdl_wrapped_window; QWindow* sdl_wrapped_window;
QWidget* sdl_wrapped_widget; QWidget* sdl_wrapped_widget;
QWidget* hw_widget;
QTimer* sdl_timer; QTimer* sdl_timer;
}; };

View File

@@ -36,6 +36,11 @@ wchar_t* ui_window_title(wchar_t* str)
return str; return str;
} }
extern "C" void qt_blit(int x, int y, int w, int h)
{
main_window->blitToWidget(x, y, w, h);
}
void mouse_poll() { void mouse_poll() {
main_window->pollMouse(); main_window->pollMouse();
} }