Merge pull request #2432 from Cacodemon345/multimonitor-take2-ui
Multi-monitor support
This commit is contained in:
@@ -8,7 +8,7 @@ extern "C"
|
||||
#include <86box/video.h>
|
||||
}
|
||||
|
||||
D3D9Renderer::D3D9Renderer(QWidget *parent)
|
||||
D3D9Renderer::D3D9Renderer(QWidget *parent, int monitor_index)
|
||||
: QWidget{parent}, RendererCommon()
|
||||
{
|
||||
QPalette pal = palette();
|
||||
@@ -27,6 +27,7 @@ D3D9Renderer::D3D9Renderer(QWidget *parent)
|
||||
RendererCommon::parentWidget = parent;
|
||||
|
||||
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
this->m_monitor_index = monitor_index;
|
||||
}
|
||||
|
||||
D3D9Renderer::~D3D9Renderer()
|
||||
@@ -138,8 +139,8 @@ void D3D9Renderer::resizeEvent(QResizeEvent *event)
|
||||
|
||||
void D3D9Renderer::blit(int x, int y, int w, int h)
|
||||
{
|
||||
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || surfaceInUse) {
|
||||
video_blit_complete();
|
||||
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || surfaceInUse) {
|
||||
video_blit_complete_monitor(m_monitor_index);
|
||||
return;
|
||||
}
|
||||
surfaceInUse = true;
|
||||
@@ -152,16 +153,16 @@ void D3D9Renderer::blit(int x, int y, int w, int h)
|
||||
srcRect.right = source.right();
|
||||
|
||||
if (screenshots) {
|
||||
video_screenshot((uint32_t *) &(buffer32->line[y][x]), 0, 0, 2048);
|
||||
video_screenshot_monitor((uint32_t *) &(monitors[m_monitor_index].target_buffer->line[y][x]), 0, 0, 2048, m_monitor_index);
|
||||
}
|
||||
if (SUCCEEDED(d3d9surface->LockRect(&lockRect, &srcRect, 0))) {
|
||||
for (int y1 = 0; y1 < h; y1++) {
|
||||
video_copy(((uint8_t*)lockRect.pBits) + (y1 * lockRect.Pitch), &(buffer32->line[y + y1][x]), w * 4);
|
||||
video_copy(((uint8_t*)lockRect.pBits) + (y1 * lockRect.Pitch), &(monitors[m_monitor_index].target_buffer->line[y + y1][x]), w * 4);
|
||||
}
|
||||
video_blit_complete();
|
||||
video_blit_complete_monitor(m_monitor_index);
|
||||
d3d9surface->UnlockRect();
|
||||
}
|
||||
else video_blit_complete();
|
||||
else video_blit_complete_monitor(m_monitor_index);
|
||||
surfaceInUse = false;
|
||||
QTimer::singleShot(0, this, [this] { this->update(); });
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class D3D9Renderer : public QWidget, public RendererCommon
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit D3D9Renderer(QWidget *parent = nullptr);
|
||||
explicit D3D9Renderer(QWidget *parent = nullptr, int monitor_index = 0);
|
||||
~D3D9Renderer();
|
||||
bool hasBlitFunc() override { return true; }
|
||||
void blit(int x, int y, int w, int h) override;
|
||||
@@ -39,6 +39,7 @@ private:
|
||||
|
||||
std::atomic<bool> surfaceInUse{false}, finalized{false};
|
||||
bool alreadyInitialized = false;
|
||||
int m_monitor_index = 0;
|
||||
};
|
||||
|
||||
#endif // D3D9RENDERER_HPP
|
||||
|
||||
@@ -32,6 +32,7 @@ extern "C" {
|
||||
|
||||
void HardwareRenderer::resizeGL(int w, int h)
|
||||
{
|
||||
m_context->makeCurrent(this);
|
||||
glViewport(0, 0, qRound(w * devicePixelRatio()), qRound(h * devicePixelRatio()));
|
||||
}
|
||||
|
||||
|
||||
@@ -122,19 +122,13 @@ main_thread_fn()
|
||||
/* Just so we dont overload the host OS. */
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
/* If needed, handle a screen resize. */
|
||||
if (!atomic_flag_test_and_set(&doresize) && !video_fullscreen && !is_quit) {
|
||||
if (vid_resize & 2)
|
||||
plat_resize(fixed_size_x, fixed_size_y);
|
||||
else
|
||||
plat_resize(scrnsz_x, scrnsz_y);
|
||||
}
|
||||
}
|
||||
|
||||
is_quit = 1;
|
||||
}
|
||||
|
||||
static std::thread* main_thread;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, false);
|
||||
@@ -258,7 +252,7 @@ int main(int argc, char* argv[]) {
|
||||
main_window->installEventFilter(&socket);
|
||||
socket.connectToServer(qgetenv("86BOX_MANAGER_SOCKET"));
|
||||
}
|
||||
pc_reset_hard_init();
|
||||
//pc_reset_hard_init();
|
||||
|
||||
/* Set the PAUSE mode depending on the renderer. */
|
||||
// plat_pause(0);
|
||||
@@ -284,13 +278,38 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
/* Initialize the rendering window, or fullscreen. */
|
||||
auto main_thread = std::thread([] {
|
||||
main_thread_fn();
|
||||
QTimer::singleShot(0, &app, []
|
||||
{
|
||||
pc_reset_hard_init();
|
||||
main_thread = new std::thread(main_thread_fn);
|
||||
});
|
||||
|
||||
QTimer resizeTimer;
|
||||
resizeTimer.setInterval(0);
|
||||
resizeTimer.callOnTimeout([]()
|
||||
{
|
||||
/* If needed, handle a screen resize. */
|
||||
for (int i = 0; i < MONITORS_NUM; i++) {
|
||||
if (!monitors[i].target_buffer) continue;
|
||||
if (atomic_load(&doresize_monitors[i]) == 1 && !video_fullscreen && !is_quit) {
|
||||
if (vid_resize & 2)
|
||||
plat_resize_monitor(fixed_size_x, fixed_size_y, i);
|
||||
else
|
||||
plat_resize_monitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i);
|
||||
atomic_store(&doresize_monitors[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_quit) {
|
||||
QApplication::quit();
|
||||
}
|
||||
});
|
||||
resizeTimer.start();
|
||||
|
||||
auto ret = app.exec();
|
||||
cpu_thread_run = 0;
|
||||
main_thread.join();
|
||||
main_thread->join();
|
||||
pc_close(nullptr);
|
||||
|
||||
socket.close();
|
||||
return ret;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
* Copyright 2021-2022 Teemu Korhonen
|
||||
* Copyright 2022 dob205
|
||||
*/
|
||||
#include <QDebug>
|
||||
|
||||
#include "qt_mainwindow.hpp"
|
||||
#include "ui_qt_mainwindow.h"
|
||||
|
||||
@@ -61,6 +63,7 @@ extern "C" {
|
||||
#include <QPushButton>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include <QMenuBar>
|
||||
#include <QCheckBox>
|
||||
#include <QActionGroup>
|
||||
#include <QOpenGLContext>
|
||||
@@ -120,7 +123,7 @@ static BMessageFilter* filter;
|
||||
#endif
|
||||
|
||||
extern void qt_mouse_capture(int);
|
||||
extern "C" void qt_blit(int x, int y, int w, int h);
|
||||
extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index);
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
@@ -140,7 +143,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
statusBar()->setVisible(!hide_status_bar);
|
||||
statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }");
|
||||
ui->toolBar->setVisible(!hide_tool_bar);
|
||||
|
||||
renderers[0].reset(nullptr);
|
||||
auto toolbar_spacer = new QWidget();
|
||||
toolbar_spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
ui->toolBar->addWidget(toolbar_spacer);
|
||||
@@ -225,7 +228,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
});
|
||||
|
||||
connect(this, &MainWindow::resizeContents, this, [this](int w, int h) {
|
||||
if (!QApplication::platformName().contains("eglfs") && vid_resize == 0) {
|
||||
if (!QApplication::platformName().contains("eglfs") && vid_resize != 1) {
|
||||
w = (w / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.));
|
||||
|
||||
int modifiedHeight = (h / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.))
|
||||
@@ -238,6 +241,18 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
}
|
||||
});
|
||||
|
||||
connect(this, &MainWindow::resizeContentsMonitor, this, [this](int w, int h, int monitor_index)
|
||||
{
|
||||
if (!QApplication::platformName().contains("eglfs") && vid_resize != 1) {
|
||||
qDebug() << "Resize";
|
||||
w = (w / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.));
|
||||
|
||||
int modifiedHeight = (h / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.));
|
||||
|
||||
renderers[monitor_index]->setFixedSize(w, modifiedHeight);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->menubar, &QMenuBar::triggered, this, [this] {
|
||||
config_save();
|
||||
if (QApplication::activeWindow() == this)
|
||||
@@ -263,6 +278,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->actionHiDPI_scaling->setChecked(dpi_scale);
|
||||
ui->actionHide_status_bar->setChecked(hide_status_bar);
|
||||
ui->actionHide_tool_bar->setChecked(hide_tool_bar);
|
||||
ui->actionShow_non_primary_monitors->setChecked(show_second_monitors);
|
||||
ui->actionUpdate_status_bar_icons->setChecked(update_icons);
|
||||
ui->actionEnable_Discord_integration->setChecked(enable_discord);
|
||||
|
||||
@@ -305,27 +321,33 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
|
||||
connect(actGroup, &QActionGroup::triggered, [this](QAction* action) {
|
||||
vid_api = action->property("vid_api").toInt();
|
||||
RendererStack::Renderer newVidApi = RendererStack::Renderer::Software;
|
||||
switch (vid_api)
|
||||
{
|
||||
case 0:
|
||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
|
||||
newVidApi = RendererStack::Renderer::Software;
|
||||
break;
|
||||
case 1:
|
||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL);
|
||||
newVidApi = (RendererStack::Renderer::OpenGL);
|
||||
break;
|
||||
case 2:
|
||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES);
|
||||
newVidApi = (RendererStack::Renderer::OpenGLES);
|
||||
break;
|
||||
case 3:
|
||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3);
|
||||
newVidApi = (RendererStack::Renderer::OpenGL3);
|
||||
break;
|
||||
case 4:
|
||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Vulkan);
|
||||
newVidApi = (RendererStack::Renderer::Vulkan);
|
||||
break;
|
||||
case 5:
|
||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9);
|
||||
newVidApi = (RendererStack::Renderer::Direct3D9);
|
||||
break;
|
||||
}
|
||||
ui->stackedWidget->switchRenderer(newVidApi);
|
||||
if (!show_second_monitors) return;
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i]) renderers[i]->switchRenderer(newVidApi);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->stackedWidget, &RendererStack::rendererChanged, [this]() {
|
||||
@@ -495,6 +517,11 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
#endif
|
||||
|
||||
setContextMenuPolicy(Qt::PreventContextMenu);
|
||||
|
||||
connect(this, &MainWindow::initRendererMonitor, this, &MainWindow::initRendererMonitorSlot);
|
||||
connect(this, &MainWindow::initRendererMonitorForNonQtThread, this, &MainWindow::initRendererMonitorSlot, Qt::BlockingQueuedConnection);
|
||||
connect(this, &MainWindow::destroyRendererMonitor, this, &MainWindow::destroyRendererMonitorSlot);
|
||||
connect(this, &MainWindow::destroyRendererMonitorForNonQtThread, this, &MainWindow::destroyRendererMonitorSlot, Qt::BlockingQueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
@@ -527,18 +554,74 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
window_x = this->geometry().x();
|
||||
window_y = this->geometry().y();
|
||||
}
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i]) {
|
||||
monitor_settings[i].mon_window_w = renderers[i]->geometry().width();
|
||||
monitor_settings[i].mon_window_h = renderers[i]->geometry().height();
|
||||
if (!QApplication::platformName().contains("wayland")) continue;
|
||||
monitor_settings[i].mon_window_x = renderers[i]->geometry().x();
|
||||
monitor_settings[i].mon_window_y = renderers[i]->geometry().y();
|
||||
}
|
||||
}
|
||||
}
|
||||
qt_nvr_save();
|
||||
config_save();
|
||||
|
||||
if (ui->stackedWidget->mouse_exit_func)
|
||||
ui->stackedWidget->mouse_exit_func();
|
||||
|
||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
|
||||
|
||||
qt_nvr_save();
|
||||
config_save();
|
||||
QApplication::processEvents();
|
||||
cpu_thread_run = 0;
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void MainWindow::initRendererMonitorSlot(int monitor_index)
|
||||
{
|
||||
auto& secondaryRenderer = this->renderers[monitor_index];
|
||||
secondaryRenderer.reset(new RendererStack(nullptr, monitor_index));
|
||||
if (secondaryRenderer) {
|
||||
connect(this, &MainWindow::pollMouse, secondaryRenderer.get(), &RendererStack::mousePoll, Qt::DirectConnection);
|
||||
connect(secondaryRenderer.get(), &RendererStack::rendererChanged, this, [this, monitor_index]
|
||||
{
|
||||
this->renderers[monitor_index]->show();
|
||||
});
|
||||
secondaryRenderer->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||
secondaryRenderer->setWindowTitle(QObject::tr("86Box Monitor #") + QString::number(monitor_index + 1));
|
||||
|
||||
if (vid_resize == 2) {
|
||||
secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y);
|
||||
}
|
||||
secondaryRenderer->setWindowIcon(this->windowIcon());
|
||||
if (show_second_monitors) {
|
||||
secondaryRenderer->show();
|
||||
if (window_remember) {
|
||||
secondaryRenderer->setGeometry(monitor_settings[monitor_index].mon_window_x < 120 ? 120 : monitor_settings[monitor_index].mon_window_x,
|
||||
monitor_settings[monitor_index].mon_window_y < 120 ? 120 : monitor_settings[monitor_index].mon_window_y,
|
||||
monitor_settings[monitor_index].mon_window_w > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_w,
|
||||
monitor_settings[monitor_index].mon_window_h > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_h);
|
||||
}
|
||||
secondaryRenderer->switchRenderer((RendererStack::Renderer)vid_api);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::destroyRendererMonitorSlot(int monitor_index)
|
||||
{
|
||||
if (this->renderers[monitor_index]) {
|
||||
if (window_remember) {
|
||||
monitor_settings[monitor_index].mon_window_w = renderers[monitor_index]->geometry().width();
|
||||
monitor_settings[monitor_index].mon_window_h = renderers[monitor_index]->geometry().height();
|
||||
monitor_settings[monitor_index].mon_window_x = renderers[monitor_index]->geometry().x();
|
||||
monitor_settings[monitor_index].mon_window_y = renderers[monitor_index]->geometry().y();
|
||||
}
|
||||
config_save();
|
||||
this->renderers[monitor_index].release()->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
delete ui;
|
||||
}
|
||||
@@ -546,6 +629,7 @@ MainWindow::~MainWindow() {
|
||||
void MainWindow::showEvent(QShowEvent *event) {
|
||||
if (shownonce) return;
|
||||
shownonce = true;
|
||||
if (window_remember) resize(window_w, window_h + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height()));
|
||||
if (window_remember && !QApplication::platformName().contains("wayland")) {
|
||||
setGeometry(window_x, window_y, window_w, window_h + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height()));
|
||||
}
|
||||
@@ -555,15 +639,8 @@ void MainWindow::showEvent(QShowEvent *event) {
|
||||
+ (hide_status_bar ? 0 : statusBar()->height())
|
||||
+ (hide_tool_bar ? 0 : ui->toolBar->height()));
|
||||
|
||||
scrnsz_x = fixed_size_x;
|
||||
scrnsz_y = fixed_size_y;
|
||||
}
|
||||
else if (window_remember && vid_resize == 1) {
|
||||
ui->stackedWidget->setFixedSize(window_w, window_h);
|
||||
adjustSize();
|
||||
ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
scrnsz_x = window_w;
|
||||
scrnsz_y = window_h;
|
||||
monitors[0].mon_scrnsz_x = fixed_size_x;
|
||||
monitors[0].mon_scrnsz_y = fixed_size_y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1361,7 +1438,7 @@ void MainWindow::on_actionFullscreen_triggered() {
|
||||
+ (!hide_status_bar ? statusBar()->height() : 0)
|
||||
+ (!hide_tool_bar ? ui->toolBar->height() : 0));
|
||||
|
||||
emit resizeContents(scrnsz_x, scrnsz_y);
|
||||
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
|
||||
}
|
||||
} else {
|
||||
if (video_fullscreen_first)
|
||||
@@ -1495,9 +1572,13 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void MainWindow::blitToWidget(int x, int y, int w, int h)
|
||||
void MainWindow::blitToWidget(int x, int y, int w, int h, int monitor_index)
|
||||
{
|
||||
ui->stackedWidget->blit(x, y, w, h);
|
||||
if (monitor_index >= 1) {
|
||||
if (renderers[monitor_index]) renderers[monitor_index]->blit(x, y, w, h);
|
||||
else video_blit_complete_monitor(monitor_index);
|
||||
}
|
||||
else ui->stackedWidget->blit(x, y, w, h);
|
||||
}
|
||||
|
||||
void MainWindow::keyReleaseEvent(QKeyEvent* event)
|
||||
@@ -1536,16 +1617,34 @@ void MainWindow::on_actionResizable_window_triggered(bool checked) {
|
||||
setWindowFlag(Qt::WindowMaximizeButtonHint);
|
||||
setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false);
|
||||
setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (monitors[i].target_buffer) {
|
||||
renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint);
|
||||
renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vid_resize = 0;
|
||||
setWindowFlag(Qt::WindowMaximizeButtonHint, false);
|
||||
setWindowFlag(Qt::MSWindowsFixedSizeDialogHint);
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (monitors[i].target_buffer) {
|
||||
renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, false);
|
||||
emit resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
show();
|
||||
ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api);
|
||||
|
||||
ui->menuWindow_scale_factor->setEnabled(! checked);
|
||||
emit resizeContents(scrnsz_x, scrnsz_y);
|
||||
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
|
||||
ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api);
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (monitors[i].target_buffer && show_second_monitors) {
|
||||
renderers[i]->show();
|
||||
renderers[i]->switchRenderer((RendererStack::Renderer)vid_api);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1558,6 +1657,9 @@ video_toggle_option(QAction* action, int *val)
|
||||
endblit();
|
||||
config_save();
|
||||
device_force_redraw();
|
||||
for (int i = 0; i < MONITORS_NUM; i++) {
|
||||
if (monitors[i].target_buffer) video_force_resize_set_monitor(1, i);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionInverted_VGA_monitor_triggered() {
|
||||
@@ -1572,8 +1674,9 @@ static void update_scaled_checkboxes(Ui::MainWindow* ui, QAction* selected) {
|
||||
|
||||
reset_screen_size();
|
||||
device_force_redraw();
|
||||
video_force_resize_set(1);
|
||||
atomic_flag_clear(&doresize);
|
||||
for (int i = 0; i < MONITORS_NUM; i++) {
|
||||
if (monitors[i].target_buffer) video_force_resize_set_monitor(1, i);
|
||||
}
|
||||
config_save();
|
||||
}
|
||||
|
||||
@@ -1752,7 +1855,6 @@ void MainWindow::on_actionChange_contrast_for_monochrome_display_triggered() {
|
||||
|
||||
void MainWindow::on_actionForce_4_3_display_ratio_triggered() {
|
||||
video_toggle_option(ui->actionForce_4_3_display_ratio, &force_43);
|
||||
video_force_resize_set(1);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRemember_size_and_position_triggered()
|
||||
@@ -1764,6 +1866,14 @@ void MainWindow::on_actionRemember_size_and_position_triggered()
|
||||
window_x = geometry().x();
|
||||
window_y = geometry().y();
|
||||
}
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (window_remember && renderers[i]) {
|
||||
monitor_settings[i].mon_window_w = renderers[i]->geometry().width();
|
||||
monitor_settings[i].mon_window_h = renderers[i]->geometry().height();
|
||||
monitor_settings[i].mon_window_x = renderers[i]->geometry().x();
|
||||
monitor_settings[i].mon_window_y = renderers[i]->geometry().y();
|
||||
}
|
||||
}
|
||||
ui->actionRemember_size_and_position->setChecked(window_remember);
|
||||
}
|
||||
|
||||
@@ -1778,7 +1888,10 @@ void MainWindow::on_actionHiDPI_scaling_triggered()
|
||||
{
|
||||
dpi_scale ^= 1;
|
||||
ui->actionHiDPI_scaling->setChecked(dpi_scale);
|
||||
emit resizeContents(scrnsz_x, scrnsz_y);
|
||||
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i]) emit resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionHide_status_bar_triggered()
|
||||
@@ -1794,7 +1907,7 @@ void MainWindow::on_actionHide_status_bar_triggered()
|
||||
} else {
|
||||
int vid_resize_orig = vid_resize;
|
||||
vid_resize = 0;
|
||||
emit resizeContents(scrnsz_x, scrnsz_y);
|
||||
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
|
||||
vid_resize = vid_resize_orig;
|
||||
}
|
||||
}
|
||||
@@ -1812,7 +1925,7 @@ void MainWindow::on_actionHide_tool_bar_triggered()
|
||||
} else {
|
||||
int vid_resize_orig = vid_resize;
|
||||
vid_resize = 0;
|
||||
emit resizeContents(scrnsz_x, scrnsz_y);
|
||||
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
|
||||
vid_resize = vid_resize_orig;
|
||||
}
|
||||
}
|
||||
@@ -1826,7 +1939,8 @@ void MainWindow::on_actionUpdate_status_bar_icons_triggered()
|
||||
void MainWindow::on_actionTake_screenshot_triggered()
|
||||
{
|
||||
startblit();
|
||||
screenshots++;
|
||||
for (int i = 0; i < MONITORS_NUM; i++)
|
||||
monitors[i].mon_screenshots++;
|
||||
endblit();
|
||||
device_force_redraw();
|
||||
}
|
||||
@@ -1892,8 +2006,13 @@ void MainWindow::on_actionRenderer_options_triggered()
|
||||
{
|
||||
auto dlg = ui->stackedWidget->getOptions(this);
|
||||
|
||||
if (dlg)
|
||||
dlg->exec();
|
||||
if (dlg) {
|
||||
if (dlg->exec() == QDialog::Accepted) {
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i] && renderers[i]->hasOptions()) renderers[i]->reloadOptions();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionMCA_devices_triggered()
|
||||
@@ -1904,3 +2023,36 @@ void MainWindow::on_actionMCA_devices_triggered()
|
||||
dlg->exec();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionShow_non_primary_monitors_triggered()
|
||||
{
|
||||
show_second_monitors ^= 1;
|
||||
|
||||
if (show_second_monitors) {
|
||||
for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) {
|
||||
auto& secondaryRenderer = renderers[monitor_index];
|
||||
if (!renderers[monitor_index]) continue;
|
||||
secondaryRenderer->show();
|
||||
if (window_remember) {
|
||||
secondaryRenderer->setGeometry(monitor_settings[monitor_index].mon_window_x < 120 ? 120 : monitor_settings[monitor_index].mon_window_x,
|
||||
monitor_settings[monitor_index].mon_window_y < 120 ? 120 : monitor_settings[monitor_index].mon_window_y,
|
||||
monitor_settings[monitor_index].mon_window_w > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_w,
|
||||
monitor_settings[monitor_index].mon_window_h > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_h);
|
||||
}
|
||||
secondaryRenderer->switchRenderer((RendererStack::Renderer)vid_api);
|
||||
}
|
||||
} else {
|
||||
for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) {
|
||||
auto& secondaryRenderer = renderers[monitor_index];
|
||||
if (!renderers[monitor_index]) continue;
|
||||
secondaryRenderer->hide();
|
||||
if (window_remember && renderers[monitor_index]) {
|
||||
monitor_settings[monitor_index].mon_window_w = renderers[monitor_index]->geometry().width();
|
||||
monitor_settings[monitor_index].mon_window_h = renderers[monitor_index]->geometry().height();
|
||||
monitor_settings[monitor_index].mon_window_x = renderers[monitor_index]->geometry().x();
|
||||
monitor_settings[monitor_index].mon_window_y = renderers[monitor_index]->geometry().y();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
|
||||
class MediaMenu;
|
||||
class RendererStack;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
@@ -26,12 +27,13 @@ public:
|
||||
|
||||
void showMessage(int flags, const QString& header, const QString& message);
|
||||
void getTitle(wchar_t* title);
|
||||
void blitToWidget(int x, int y, int w, int h);
|
||||
void blitToWidget(int x, int y, int w, int h, int monitor_index);
|
||||
QSize getRenderWidgetSize();
|
||||
void setSendKeyboardInput(bool enabled);
|
||||
signals:
|
||||
void paint(const QImage& image);
|
||||
void resizeContents(int w, int h);
|
||||
void resizeContentsMonitor(int w, int h, int monitor_index);
|
||||
void pollMouse();
|
||||
void statusBarMessage(const QString& msg);
|
||||
void updateStatusBarPanes();
|
||||
@@ -40,6 +42,10 @@ signals:
|
||||
void updateStatusBarTip(int tag);
|
||||
void updateMenuResizeOptions();
|
||||
void updateWindowRememberOption();
|
||||
void initRendererMonitor(int monitor_index);
|
||||
void destroyRendererMonitor(int monitor_index);
|
||||
void initRendererMonitorForNonQtThread(int monitor_index);
|
||||
void destroyRendererMonitorForNonQtThread(int monitor_index);
|
||||
|
||||
void setTitle(const QString& title);
|
||||
void setFullscreen(bool state);
|
||||
@@ -51,6 +57,8 @@ public slots:
|
||||
void showSettings();
|
||||
void hardReset();
|
||||
void togglePause();
|
||||
void initRendererMonitorSlot(int monitor_index);
|
||||
void destroyRendererMonitorSlot(int monitor_index);
|
||||
private slots:
|
||||
void on_actionFullscreen_triggered();
|
||||
void on_actionSettings_triggered();
|
||||
@@ -115,9 +123,13 @@ protected:
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
void changeEvent(QEvent* event) override;
|
||||
|
||||
private slots:
|
||||
void on_actionShow_non_primary_monitors_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
std::unique_ptr<MachineStatus> status;
|
||||
std::array<std::unique_ptr<RendererStack>, 8> renderers;
|
||||
std::shared_ptr<MediaMenu> mm;
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>724</width>
|
||||
<height>21</height>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuAction">
|
||||
@@ -161,6 +161,7 @@
|
||||
<addaction name="actionHide_tool_bar"/>
|
||||
<addaction name="actionHide_status_bar"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionShow_non_primary_monitors"/>
|
||||
<addaction name="actionResizable_window"/>
|
||||
<addaction name="actionRemember_size_and_position"/>
|
||||
<addaction name="separator"/>
|
||||
@@ -757,6 +758,14 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_non_primary_monitors">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show non-primary monitors</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
OpenGLRenderer::OpenGLRenderer(QWidget *parent)
|
||||
: QWindow(parent->windowHandle())
|
||||
, renderTimer(new QTimer(this))
|
||||
, options(nullptr)
|
||||
{
|
||||
renderTimer->setTimerType(Qt::PreciseTimer);
|
||||
/* TODO: need's more accuracy, maybe target 1ms earlier and spin yield */
|
||||
@@ -165,9 +166,7 @@ OpenGLRenderer::initialize()
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, QOpenGLTexture::RGBA8_UNorm, INIT_WIDTH, INIT_HEIGHT, 0, QOpenGLTexture::BGRA, QOpenGLTexture::UInt32_RGBA8_Rev, NULL);
|
||||
|
||||
options = new OpenGLOptions(this, true, glslVersion);
|
||||
|
||||
applyOptions();
|
||||
reloadOptions();
|
||||
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
|
||||
@@ -304,6 +303,15 @@ OpenGLRenderer::applyOptions()
|
||||
currentFilter = options->filter();
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLRenderer::reloadOptions()
|
||||
{
|
||||
if (options) { delete options; options = nullptr; }
|
||||
options = new OpenGLOptions(this, true, glslVersion);
|
||||
|
||||
applyOptions();
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLRenderer::applyShader(const OpenGLShaderPass &shader)
|
||||
{
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
void finalize() override final;
|
||||
bool hasOptions() const override { return true; }
|
||||
QDialog *getOptions(QWidget *parent) override;
|
||||
void reloadOptions() override;
|
||||
|
||||
signals:
|
||||
void initialized();
|
||||
|
||||
@@ -52,7 +52,7 @@ extern MainWindow* main_window;
|
||||
QElapsedTimer elapsed_timer;
|
||||
|
||||
static std::atomic_int blitmx_contention = 0;
|
||||
static std::mutex blitmx;
|
||||
static std::recursive_mutex blitmx;
|
||||
|
||||
class CharPointer {
|
||||
public:
|
||||
|
||||
@@ -28,6 +28,8 @@ public:
|
||||
virtual bool hasOptions() const { return false; }
|
||||
/* Returns options dialog for renderer */
|
||||
virtual QDialog *getOptions(QWidget *parent) { return nullptr; }
|
||||
/* Reloads options of renderer */
|
||||
virtual void reloadOptions() {}
|
||||
|
||||
virtual bool hasBlitFunc() { return false; }
|
||||
virtual void blit(int x, int y, int w, int h) {}
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/video.h>
|
||||
@@ -51,14 +52,21 @@ extern "C" {
|
||||
double mouse_sensitivity = 1.0;
|
||||
}
|
||||
|
||||
struct mouseinputdata {
|
||||
int deltax, deltay, deltaz;
|
||||
int mousebuttons;
|
||||
};
|
||||
static mouseinputdata mousedata;
|
||||
|
||||
extern "C" void macos_poll_mouse();
|
||||
extern MainWindow *main_window;
|
||||
RendererStack::RendererStack(QWidget *parent)
|
||||
RendererStack::RendererStack(QWidget *parent, int monitor_index)
|
||||
: QStackedWidget(parent)
|
||||
, ui(new Ui::RendererStack)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_monitor_index = monitor_index;
|
||||
#if defined __unix__ && !defined __HAIKU__
|
||||
char *mouse_type = getenv("EMU86BOX_MOUSE"), auto_mouse_type[16];
|
||||
if (!mouse_type || (mouse_type[0] == '\0') || !stricmp(mouse_type, "auto")) {
|
||||
@@ -313,7 +321,7 @@ RendererStack::createRenderer(Renderer renderer)
|
||||
case Renderer::Direct3D9:
|
||||
{
|
||||
this->createWinId();
|
||||
auto hw = new D3D9Renderer(this);
|
||||
auto hw = new D3D9Renderer(this, m_monitor_index);
|
||||
rendererWindow = hw;
|
||||
connect(hw, &D3D9Renderer::error, this, [this](QString str)
|
||||
{
|
||||
@@ -398,14 +406,14 @@ RendererStack::createRenderer(Renderer renderer)
|
||||
void
|
||||
RendererStack::blitDummy(int x, int y, int w, int h)
|
||||
{
|
||||
video_blit_complete();
|
||||
video_blit_complete_monitor(m_monitor_index);
|
||||
blitDummied = true;
|
||||
}
|
||||
|
||||
void
|
||||
RendererStack::blitRenderer(int x, int y, int w, int h)
|
||||
{
|
||||
if (blitDummied) { blitDummied = false; video_blit_complete(); return; }
|
||||
if (blitDummied) { blitDummied = false; video_blit_complete_monitor(m_monitor_index); return; }
|
||||
directBlitting = true;
|
||||
rendererWindow->blit(x, y, w, h);
|
||||
directBlitting = false;
|
||||
@@ -415,8 +423,8 @@ RendererStack::blitRenderer(int x, int y, int w, int h)
|
||||
void
|
||||
RendererStack::blitCommon(int x, int y, int w, int h)
|
||||
{
|
||||
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || imagebufs.empty() || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set() || blitDummied) {
|
||||
video_blit_complete();
|
||||
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || imagebufs.empty() || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set() || blitDummied) {
|
||||
video_blit_complete_monitor(m_monitor_index);
|
||||
return;
|
||||
}
|
||||
sx = x;
|
||||
@@ -426,13 +434,21 @@ RendererStack::blitCommon(int x, int y, int w, int h)
|
||||
uint8_t *imagebits = std::get<uint8_t *>(imagebufs[currentBuf]);
|
||||
for (int y1 = y; y1 < (y + h); y1++) {
|
||||
auto scanline = imagebits + (y1 * rendererWindow->getBytesPerRow()) + (x * 4);
|
||||
video_copy(scanline, &(buffer32->line[y1][x]), w * 4);
|
||||
video_copy(scanline, &(monitors[m_monitor_index].target_buffer->line[y1][x]), w * 4);
|
||||
}
|
||||
|
||||
if (screenshots) {
|
||||
video_screenshot((uint32_t *) imagebits, x, y, 2048);
|
||||
if (monitors[m_monitor_index].mon_screenshots) {
|
||||
video_screenshot_monitor((uint32_t *) imagebits, x, y, 2048, m_monitor_index);
|
||||
}
|
||||
video_blit_complete();
|
||||
video_blit_complete_monitor(m_monitor_index);
|
||||
emit blitToRenderer(currentBuf, sx, sy, sw, sh);
|
||||
currentBuf = (currentBuf + 1) % imagebufs.size();
|
||||
}
|
||||
|
||||
void RendererStack::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
if (cpu_thread_run == 0 || is_quit == 1) { event->accept(); return; }
|
||||
event->ignore();
|
||||
main_window->close();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class RendererStack : public QStackedWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RendererStack(QWidget *parent = nullptr);
|
||||
explicit RendererStack(QWidget *parent = nullptr, int monitor_index = 0);
|
||||
~RendererStack();
|
||||
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override
|
||||
{
|
||||
event->ignore();
|
||||
@@ -52,6 +53,8 @@ public:
|
||||
|
||||
/* Does current renderer implement options dialog */
|
||||
bool hasOptions() const { return rendererWindow ? rendererWindow->hasOptions() : false; }
|
||||
/* Reloads options of current renderer */
|
||||
void reloadOptions() const { return rendererWindow->reloadOptions(); }
|
||||
/* Returns options dialog for current renderer */
|
||||
QDialog *getOptions(QWidget *parent) { return rendererWindow ? rendererWindow->getOptions(parent) : nullptr; }
|
||||
|
||||
@@ -87,16 +90,11 @@ private:
|
||||
|
||||
Ui::RendererStack *ui;
|
||||
|
||||
struct mouseinputdata {
|
||||
int deltax, deltay, deltaz;
|
||||
int mousebuttons;
|
||||
};
|
||||
mouseinputdata mousedata;
|
||||
|
||||
int x, y, w, h, sx, sy, sw, sh;
|
||||
|
||||
int currentBuf = 0;
|
||||
int isMouseDown = 0;
|
||||
int m_monitor_index = 0;
|
||||
|
||||
std::vector<std::tuple<uint8_t *, std::atomic_flag *>> imagebufs;
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ SettingsDisplay::~SettingsDisplay()
|
||||
|
||||
void SettingsDisplay::save() {
|
||||
gfxcard = ui->comboBoxVideo->currentData().toInt();
|
||||
gfxcard_2 = ui->comboBoxVideoSecondary->currentData().toInt();
|
||||
voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0;
|
||||
ibm8514_enabled = ui->checkBox8514->isChecked() ? 1 : 0;
|
||||
xga_enabled = ui->checkBoxXga->isChecked() ? 1 : 0;
|
||||
@@ -87,11 +88,16 @@ void SettingsDisplay::onCurrentMachineChanged(int machineId) {
|
||||
|
||||
if (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0) {
|
||||
ui->comboBoxVideo->setEnabled(false);
|
||||
ui->comboBoxVideoSecondary->setEnabled(false);
|
||||
ui->pushButtonConfigureSecondary->setEnabled(false);
|
||||
selectedRow = 1;
|
||||
} else {
|
||||
ui->comboBoxVideo->setEnabled(true);
|
||||
ui->comboBoxVideoSecondary->setEnabled(true);
|
||||
ui->pushButtonConfigureSecondary->setEnabled(true);
|
||||
}
|
||||
ui->comboBoxVideo->setCurrentIndex(selectedRow);
|
||||
if (gfxcard_2 == 0) ui->pushButtonConfigureSecondary->setEnabled(false);
|
||||
}
|
||||
|
||||
void SettingsDisplay::on_pushButtonConfigure_clicked() {
|
||||
@@ -137,6 +143,41 @@ void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) {
|
||||
ui->checkBoxXga->setChecked(xga_enabled);
|
||||
|
||||
ui->pushButtonConfigureXga->setEnabled((hasIsa16 || has_MCA) && ui->checkBoxXga->isChecked());
|
||||
|
||||
int c = 2;
|
||||
|
||||
ui->comboBoxVideoSecondary->clear();
|
||||
ui->comboBoxVideoSecondary->addItem(QObject::tr("None"), 0);
|
||||
|
||||
ui->comboBoxVideoSecondary->setCurrentIndex(0);
|
||||
// TODO: Implement support for selecting non-MDA secondary cards properly when MDA cards are the primary ones.
|
||||
if (video_card_get_flags(videoCard) == VIDEO_FLAG_TYPE_MDA) {
|
||||
ui->comboBoxVideoSecondary->setCurrentIndex(0);
|
||||
return;
|
||||
}
|
||||
while (true) {
|
||||
const device_t* video_dev = video_card_getdevice(c);
|
||||
QString name = DeviceConfig::DeviceName(video_dev, video_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (video_card_available(c) &&
|
||||
device_is_valid(video_dev, machineId) &&
|
||||
!(video_card_get_flags(c) == video_card_get_flags(videoCard))) {
|
||||
ui->comboBoxVideoSecondary->addItem(name, c);
|
||||
if (c == gfxcard_2)
|
||||
ui->comboBoxVideoSecondary->setCurrentIndex(ui->comboBoxVideoSecondary->count() - 1);
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
if (gfxcard_2 == 0 || (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0))
|
||||
{
|
||||
ui->comboBoxVideoSecondary->setCurrentIndex(0);
|
||||
ui->pushButtonConfigureSecondary->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) {
|
||||
@@ -146,3 +187,21 @@ void SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) {
|
||||
void SettingsDisplay::on_checkBoxXga_stateChanged(int state) {
|
||||
ui->pushButtonConfigureXga->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void SettingsDisplay::on_comboBoxVideoSecondary_currentIndexChanged(int index)
|
||||
{
|
||||
if (index < 0) {
|
||||
ui->pushButtonConfigureSecondary->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
int videoCard = ui->comboBoxVideoSecondary->currentData().toInt();
|
||||
ui->pushButtonConfigureSecondary->setEnabled(index != 0 && video_card_has_config(videoCard) > 0);
|
||||
}
|
||||
|
||||
|
||||
void SettingsDisplay::on_pushButtonConfigureSecondary_clicked()
|
||||
{
|
||||
auto* device = video_card_getdevice(ui->comboBoxVideoSecondary->currentData().toInt());
|
||||
DeviceConfig::ConfigureDevice(device, 0, qobject_cast<Settings*>(Settings::settings));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,12 @@ public:
|
||||
public slots:
|
||||
void onCurrentMachineChanged(int machineId);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonConfigureSecondary_clicked();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxVideoSecondary_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_checkBoxVoodoo_stateChanged(int state);
|
||||
void on_checkBoxXga_stateChanged(int state);
|
||||
|
||||
@@ -26,16 +26,29 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxVideo"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBox8514">
|
||||
<property name="text">
|
||||
<string>Video:</string>
|
||||
<string>8514/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxVideo"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigure">
|
||||
<property name="sizePolicy">
|
||||
@@ -49,53 +62,57 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureVoodoo">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxVoodoo">
|
||||
<property name="text">
|
||||
<string>Voodoo Graphics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBox8514">
|
||||
<property name="text">
|
||||
<string>8514/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureXga">
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureVoodoo">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Video:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxXga">
|
||||
<property name="text">
|
||||
<string>XGA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<item row="4" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureXga">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Video #2:</string>
|
||||
</property>
|
||||
</spacer>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxVideoSecondary"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureSecondary">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -20,9 +20,12 @@
|
||||
#include "qt_mainwindow.hpp"
|
||||
#include "ui_qt_mainwindow.h"
|
||||
|
||||
#include "qt_util.hpp"
|
||||
|
||||
#include <QStatusBar>
|
||||
#include <QMenuBar>
|
||||
#include <QTimer>
|
||||
#include <QScreen>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -44,6 +47,11 @@ SpecifyDimensions::SpecifyDimensions(QWidget *parent) :
|
||||
ui->spinBoxWidth->setValue(main_window->getRenderWidgetSize().width());
|
||||
ui->spinBoxHeight->setRange(16, 2048);
|
||||
ui->spinBoxHeight->setValue(main_window->getRenderWidgetSize().height());
|
||||
|
||||
if (dpi_scale == 0) {
|
||||
ui->spinBoxWidth->setValue(main_window->getRenderWidgetSize().width() * util::screenOfWidget(main_window)->devicePixelRatio());
|
||||
ui->spinBoxHeight->setValue(main_window->getRenderWidgetSize().height() * util::screenOfWidget(main_window)->devicePixelRatio());
|
||||
}
|
||||
}
|
||||
|
||||
SpecifyDimensions::~SpecifyDimensions()
|
||||
@@ -62,14 +70,21 @@ void SpecifyDimensions::on_SpecifyDimensions_accepted()
|
||||
fixed_size_x = ui->spinBoxWidth->value();
|
||||
fixed_size_y = ui->spinBoxHeight->value();
|
||||
|
||||
main_window->setFixedSize(ui->spinBoxWidth->value(),
|
||||
ui->spinBoxHeight->value()
|
||||
+ (!hide_status_bar ? main_window->statusBar()->height() : 0)
|
||||
+ (!hide_tool_bar ? main_window->ui->toolBar->height() : 0)
|
||||
+ main_window->menuBar()->height());
|
||||
main_window->resizeContents(fixed_size_x, fixed_size_y);
|
||||
|
||||
emit main_window->updateMenuResizeOptions();
|
||||
main_window->show();
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (main_window->renderers[i]) {
|
||||
main_window->renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, false);
|
||||
main_window->renderers[i]->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint);
|
||||
emit main_window->resizeContentsMonitor(fixed_size_x, fixed_size_y, i);
|
||||
if (show_second_monitors) {
|
||||
main_window->renderers[i]->show();
|
||||
main_window->renderers[i]->switchRenderer((RendererStack::Renderer)vid_api);
|
||||
}
|
||||
}
|
||||
}
|
||||
main_window->ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api);
|
||||
}
|
||||
else
|
||||
@@ -83,6 +98,16 @@ void SpecifyDimensions::on_SpecifyDimensions_accepted()
|
||||
window_h = ui->spinBoxHeight->value();
|
||||
main_window->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
emit main_window->resizeContents(ui->spinBoxWidth->value(), ui->spinBoxHeight->value());
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (main_window->renderers[i]) {
|
||||
main_window->renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint);
|
||||
main_window->renderers[i]->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false);
|
||||
emit main_window->resizeContentsMonitor(ui->spinBoxWidth->value(), ui->spinBoxHeight->value(), i);
|
||||
main_window->renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
if (show_second_monitors) { main_window->renderers[i]->show();
|
||||
main_window->renderers[i]->switchRenderer((RendererStack::Renderer)vid_api); }
|
||||
}
|
||||
}
|
||||
vid_resize = 1;
|
||||
emit main_window->updateMenuResizeOptions();
|
||||
}
|
||||
|
||||
@@ -55,17 +55,18 @@ wchar_t* ui_window_title(wchar_t* str)
|
||||
return str;
|
||||
}
|
||||
|
||||
extern "C" void qt_blit(int x, int y, int w, int h)
|
||||
extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index)
|
||||
{
|
||||
main_window->blitToWidget(x, y, w, h);
|
||||
main_window->blitToWidget(x, y, w, h, monitor_index);
|
||||
}
|
||||
|
||||
void mouse_poll() {
|
||||
main_window->pollMouse();
|
||||
}
|
||||
|
||||
void plat_resize(int w, int h) {
|
||||
main_window->resizeContents(w, h);
|
||||
void plat_resize_monitor(int w, int h, int monitor_index) {
|
||||
if (monitor_index >= 1) main_window->resizeContentsMonitor(w, h, monitor_index);
|
||||
else main_window->resizeContents(w, h);
|
||||
}
|
||||
|
||||
void plat_setfullscreen(int on) {
|
||||
@@ -98,6 +99,20 @@ int ui_msgbox_header(int flags, void *header, void* message) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ui_init_monitor(int monitor_index) {
|
||||
if (QThread::currentThread() == main_window->thread()) {
|
||||
emit main_window->initRendererMonitor(monitor_index);
|
||||
}
|
||||
else emit main_window->initRendererMonitorForNonQtThread(monitor_index);
|
||||
}
|
||||
|
||||
void ui_deinit_monitor(int monitor_index) {
|
||||
if (QThread::currentThread() == main_window->thread()) {
|
||||
emit main_window->destroyRendererMonitor(monitor_index);
|
||||
}
|
||||
else emit main_window->destroyRendererMonitorForNonQtThread(monitor_index);
|
||||
}
|
||||
|
||||
int ui_msgbox(int flags, void *message) {
|
||||
return ui_msgbox_header(flags, nullptr, message);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ static zwp_pointer_constraints_v1* conf_pointer_interface = nullptr;
|
||||
static zwp_locked_pointer_v1* conf_pointer = nullptr;
|
||||
|
||||
static int rel_mouse_x = 0, rel_mouse_y = 0;
|
||||
static bool wl_init_ok = false;
|
||||
|
||||
void rel_mouse_event(void* data, zwp_relative_pointer_v1* zwp_relative_pointer_v1, uint32_t tstmp, uint32_t tstmpl, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_real, wl_fixed_t dy_real)
|
||||
{
|
||||
@@ -92,15 +93,18 @@ static const struct wl_registry_listener registry_listener = {
|
||||
|
||||
void wl_init()
|
||||
{
|
||||
wl_display* display = (wl_display*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display");
|
||||
if (display)
|
||||
{
|
||||
auto registry = wl_display_get_registry(display);
|
||||
if (registry)
|
||||
if (!wl_init_ok) {
|
||||
wl_display* display = (wl_display*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display");
|
||||
if (display)
|
||||
{
|
||||
wl_registry_add_listener(registry, ®istry_listener, nullptr);
|
||||
wl_display_roundtrip(display);
|
||||
auto registry = wl_display_get_registry(display);
|
||||
if (registry)
|
||||
{
|
||||
wl_registry_add_listener(registry, ®istry_listener, nullptr);
|
||||
wl_display_roundtrip(display);
|
||||
}
|
||||
}
|
||||
wl_init_ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user