diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index f87a76fcc..a9c1f1697 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -121,7 +121,12 @@ if (APPLE) endif() if (WIN32) - target_sources(ui PRIVATE qt_winrawinputfilter.hpp qt_winrawinputfilter.cpp) + target_sources(ui PRIVATE + qt_winrawinputfilter.hpp + qt_winrawinputfilter.cpp + qt_winmanagerfilter.hpp + qt_winmanagerfilter.cpp + ) endif() target_link_libraries( diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 292045bfe..5dc99afb5 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -20,6 +20,8 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin) #ifdef Q_OS_WINDOWS #include "qt_winrawinputfilter.hpp" +#include "qt_winmanagerfilter.hpp" +#include <86box/win.h> #endif #include <86box/86box.h> @@ -30,6 +32,7 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin) #include #include +#include #include "qt_mainwindow.hpp" #include "qt_progsettings.hpp" @@ -102,7 +105,7 @@ main_thread_fn() } int main(int argc, char* argv[]) { - QApplication app(argc, argv); + QApplication app(argc, argv); qt_set_sequence_auto_mnemonic(false); Q_INIT_RESOURCE(qt_resources); Q_INIT_RESOURCE(qt_translations); @@ -137,6 +140,30 @@ int main(int argc, char* argv[]) { app.installEventFilter(main_window); #ifdef Q_OS_WINDOWS + /* Setup VM-manager messages */ + std::unique_ptr wmfilter; + if (source_hwnd) + { + wmfilter.reset(new WindowsManagerFilter()); + QObject::connect(wmfilter.get(), WindowsManagerFilter::showsettings, main_window, MainWindow::showSettings); + QObject::connect(wmfilter.get(), WindowsManagerFilter::pause, [](){ plat_pause(dopause ^ 1); }); + QObject::connect(wmfilter.get(), WindowsManagerFilter::reset, main_window, MainWindow::hardReset); + QObject::connect(wmfilter.get(), WindowsManagerFilter::shutdown, [](){ plat_power_off(); }); + QObject::connect(wmfilter.get(), WindowsManagerFilter::ctrlaltdel, [](){ pc_send_cad(); }); + app.installNativeEventFilter(wmfilter.get()); + + HWND main_hwnd = (HWND)main_window->winId(); + + /* Send main window HWND to manager */ + PostMessage((HWND)(uintptr_t)source_hwnd, WM_SENDHWND, (WPARAM)unique_id, (LPARAM)main_hwnd); + + /* Send shutdown message to manager */ + QObject::connect(&app, &QApplication::destroyed, [main_hwnd](QObject*) { + PostMessage((HWND)(uintptr_t)source_hwnd, WM_HAS_SHUTDOWN, (WPARAM)0, (LPARAM)main_hwnd); + }); + } + + /* Setup raw input */ auto rawInputFilter = WindowsRawInputFilter::Register(main_window); if (rawInputFilter) { @@ -144,7 +171,7 @@ int main(int argc, char* argv[]) { QObject::disconnect(main_window, &MainWindow::pollMouse, 0, 0); QObject::connect(main_window, &MainWindow::pollMouse, (WindowsRawInputFilter*)rawInputFilter.get(), &WindowsRawInputFilter::mousePoll, Qt::DirectConnection); main_window->setSendKeyboardInput(false); - } + } #endif pc_reset_hard_init(); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index e75eb0501..81489113c 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1491,3 +1491,13 @@ void MainWindow::on_actionEnable_Discord_integration_triggered(bool checked) discord_close(); } +void MainWindow::showSettings() +{ + if (findChild() == nullptr) + ui->actionSettings->trigger(); +} + +void MainWindow::hardReset() +{ + ui->actionHard_Reset->trigger(); +} \ No newline at end of file diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 4d3335618..c9f22ede2 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -47,6 +47,9 @@ signals: void showMessageForNonQtThread(const QString& header, const QString& message); void getTitleForNonQtThread(wchar_t* title); +public slots: + void showSettings(); + void hardReset(); private slots: void on_actionFullscreen_triggered(); void on_actionSettings_triggered(); diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 5cdefc7f7..b210ab69d 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -56,6 +56,7 @@ extern "C" { #ifdef Q_OS_WINDOWS #define NOMINMAX #include +#include <86box/win.h> #else #include #endif @@ -289,6 +290,11 @@ plat_pause(int p) ui_window_title(oldtitle); } discord_update_activity(dopause); + +#ifdef Q_OS_WINDOWS + if (source_hwnd) + PostMessage((HWND)(uintptr_t)source_hwnd, WM_SENDSTATUS, (WPARAM)!!p, (LPARAM)(HWND)main_window->winId()); +#endif } // because we can't include nvr.h because it's got fields named new diff --git a/src/qt/qt_winmanagerfilter.cpp b/src/qt/qt_winmanagerfilter.cpp new file mode 100644 index 000000000..205d4ea16 --- /dev/null +++ b/src/qt/qt_winmanagerfilter.cpp @@ -0,0 +1,62 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Windows VM-managers native messages filter + * + * Authors: + * Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "qt_winmanagerfilter.hpp" + +#include <86box/win.h> + +bool WindowsManagerFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +{ + if (eventType == "windows_generic_MSG") + { + MSG *msg = static_cast(message); + + switch (msg->message) + { + case WM_SHOWSETTINGS: + emit showsettings(); + return true; + case WM_PAUSE: + emit pause(); + return true; + case WM_HARDRESET: + emit reset(); + return true; + case WM_SHUTDOWN: + emit shutdown(); + return true; + case WM_CTRLALTDEL: + emit ctrlaltdel(); + return true; + } + } + + return false; +} \ No newline at end of file diff --git a/src/qt/qt_winmanagerfilter.hpp b/src/qt/qt_winmanagerfilter.hpp new file mode 100644 index 000000000..9f43e1b5c --- /dev/null +++ b/src/qt/qt_winmanagerfilter.hpp @@ -0,0 +1,58 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Header file for Windows VM-managers native messages filter + * + * Authors: + * Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef QT_WINDOWSMANAGERFILTER_HPP +#define QT_WINDOWSMANAGERFILTER_HPP + +#include +#include + +#if QT_VERSION_MAJOR >= 6 +#define result_t qintptr +#else +#define result_t long +#endif + +class WindowsManagerFilter : public QObject, public QAbstractNativeEventFilter +{ + Q_OBJECT + +public: + bool nativeEventFilter(const QByteArray &eventType, void *message, result_t *result) override; + +signals: + void pause(); + void ctrlaltdel(); + void showsettings(); + void reset(); + void shutdown(); +}; + +#endif