diff --git a/src/apps/deskflow-core/deskflow-core.cpp b/src/apps/deskflow-core/deskflow-core.cpp index 052b380e8..e4d1b37ea 100644 --- a/src/apps/deskflow-core/deskflow-core.cpp +++ b/src/apps/deskflow-core/deskflow-core.cpp @@ -1,7 +1,7 @@ /* * Deskflow -- mouse and keyboard sharing utility * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello - * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. + * SPDX-FileCopyrightText: (C) 2012 - 2016, 2025 - 2026 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ @@ -21,15 +21,27 @@ #include #endif +#include #include #include #include +#include void showHelp(const CoreArgParser &parser) { QTextStream(stdout) << parser.helpText(); } +App *createApp(const CoreArgParser &parser, EventQueue &events, const QString &processName) +{ + if (parser.serverMode()) { + return new ServerApp(&events, processName); + } else if (parser.clientMode()) { + return new ClientApp(&events, processName); + } + return nullptr; +} + int main(int argc, char **argv) { #if defined(Q_OS_WIN) @@ -86,13 +98,18 @@ int main(int argc, char **argv) EventQueue events; const auto processName = QFileInfo(argv[0]).fileName(); - if (parser.serverMode()) { - ServerApp app(&events, processName); - return app.run(); - } else if (parser.clientMode()) { - ClientApp app(&events, processName); - return app.run(); - } + App *coreApp = createApp(parser, events, processName); - return s_exitSuccess; + QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName(QStringLiteral("%1 Core").arg(kAppName)); + + QThread coreThread; + QObject::connect(&coreThread, &QThread::finished, &app, &QCoreApplication::quit); + coreApp->run(coreThread); + + const auto exitCode = QCoreApplication::exec(); + coreThread.wait(); + + LOG_DEBUG("core exited, code: %d", exitCode); + return exitCode; } diff --git a/src/lib/deskflow/App.cpp b/src/lib/deskflow/App.cpp index 454896067..f6e23b60a 100644 --- a/src/lib/deskflow/App.cpp +++ b/src/lib/deskflow/App.cpp @@ -1,6 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd. + * SPDX-FileCopyrightText: (C) 2012 - 2026 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ @@ -57,48 +57,69 @@ App::~App() s_instance = nullptr; } -int App::run() +void App::run(QThread &coreThread) { + LOG_NOTE("starting core"); + + // Important: Move the daemon app to the daemon thread before creating any more Qt objects + // owned by the daemon app, as they will be created on the daemon thread. + moveToThread(&coreThread); + + connect(&coreThread, &QThread::started, this, [this, &coreThread]() { + LOG_DEBUG("core thread started"); + #if MAC_OS_X_VERSION_10_7 - // dock hide only supported on lion :( - ProcessSerialNumber psn = {0, kCurrentProcess}; + // dock hide only supported on lion :( + ProcessSerialNumber psn = {0, kCurrentProcess}; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - GetCurrentProcess(&psn); + GetCurrentProcess(&psn); #pragma GCC diagnostic pop - TransformProcessType(&psn, kProcessTransformToBackgroundApplication); + TransformProcessType(&psn, kProcessTransformToBackgroundApplication); #endif - // install application in to arch - appUtil().adoptApp(this); + // install application in to arch + appUtil().adoptApp(this); - // HACK: fail by default (saves us setting result in each catch) - int result = s_exitFailed; + // HACK: fail by default (saves us setting result in each catch) + int result = s_exitFailed; - try { - result = appUtil().run(); - } catch (ExitAppException &e) { - // instead of showing a nasty error, just exit with the error code. - // not sure if i like this behaviour, but it's probably better than - // using the exit(int) function! - result = e.getCode(); - } catch (DisplayInvalidException &die) { - LOG_CRIT("a display invalid exception error occurred: %s\n", die.what()); - // display invalid exceptions can occur when going to sleep. When this - // process exits, the UI will restart us instantly. We don't really want - // that behevior, so we quies for a bit - Arch::sleep(10); - } catch (std::runtime_error &re) { - LOG_CRIT("a runtime error occurred: %s\n", re.what()); - } catch (std::exception &e) { - LOG_CRIT("an error occurred: %s\n", e.what()); - } catch (...) { - LOG_CRIT("an unknown error occurred\n"); - } + try { + result = appUtil().run(); + } catch (ExitAppException &e) { + // instead of showing a nasty error, just exit with the error code. + // not sure if i like this behaviour, but it's probably better than + // using the exit(int) function! + result = e.getCode(); + } catch (DisplayInvalidException &die) { + LOG_CRIT("a display invalid exception error occurred: %s\n", die.what()); + // display invalid exceptions can occur when going to sleep. When this + // process exits, the UI will restart us instantly. We don't really want + // that behevior, so we quies for a bit + Arch::sleep(10); + } catch (std::runtime_error &re) { + LOG_CRIT("a runtime error occurred: %s\n", re.what()); + } catch (std::exception &e) { + LOG_CRIT("an error occurred: %s\n", e.what()); + } catch (...) { + LOG_CRIT("an unknown error occurred\n"); + } - return result; + if (result == s_exitSuccess) { + LOG_INFO("core stopped successfully"); + } else { + // TODO: surface error code to main thread somehow + LOG_ERR("core stopped with error code: %d", result); + } + + coreThread.quit(); + LOG_DEBUG("core thread finished"); + }); + + LOG_DEBUG("starting core thread"); + coreThread.start(); } void App::setupFileLogging() diff --git a/src/lib/deskflow/App.h b/src/lib/deskflow/App.h index 52baded3f..c3846d8fe 100644 --- a/src/lib/deskflow/App.h +++ b/src/lib/deskflow/App.h @@ -1,7 +1,7 @@ /* * Deskflow -- mouse and keyboard sharing utility * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers - * SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd. + * SPDX-FileCopyrightText: (C) 2012 - 2026 Symless Ltd. * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ @@ -19,6 +19,9 @@ #include "deskflow/unix/AppUtilUnix.h" #endif +#include +#include + #include #include @@ -30,7 +33,7 @@ class FileLogOutputter; class IEventQueue; class SocketMultiplexer; -class App : public IApp +class App : public QObject, private IApp { public: class XNoEiSupport : public std::runtime_error @@ -72,7 +75,7 @@ public: return m_appUtil; } - int run(); + void run(QThread &coreThread); void setupFileLogging(); void loggingFilterWarning() const; void initApp() override;