deskflow/src/apps/deskflow-core/deskflow-core.cpp

124 lines
3.1 KiB
C++
Raw Normal View History

/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
2025-12-05 18:09:25 +00:00
* 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
*/
#include "CoreArgParser.h"
#include "arch/Arch.h"
#include "base/EventQueue.h"
#include "base/Log.h"
#include "common/Constants.h"
#include "common/ExitCodes.h"
#include "deskflow/ClientApp.h"
#include "deskflow/ServerApp.h"
#include "deskflow/ipc/CoreIpcServer.h"
#if defined(Q_OS_WIN)
#include "arch/win32/ArchMiscWindows.h"
#endif
#include <QApplication>
2025-09-25 01:35:20 +00:00
#include <QFileInfo>
#include <QSharedMemory>
#include <QTextStream>
2025-12-05 18:09:25 +00:00
#include <QThread>
void showHelp(const CoreArgParser &parser)
{
QTextStream(stdout) << parser.helpText();
}
2025-12-05 18:09:25 +00:00
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)
{
// HACK to make sure settings gets the correct qApp path
QCoreApplication m(argc, argv);
}
ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
#endif
Arch arch;
arch.init();
Log log;
QStringList args;
for (int i = 0; i < argc; i++)
args.append(argv[i]);
CoreArgParser parser(args);
// Print any parser errors
if (!parser.errorText().isEmpty()) {
QTextStream(stdout) << parser.errorText() << "\n";
}
if (parser.help()) {
showHelp(parser);
return s_exitSuccess;
}
if (parser.version()) {
QTextStream(stdout) << parser.versionText();
return s_exitSuccess;
}
// Before we check any more args we need to check for a duplicate process.
// Create a shared memory segment with a unique key
// This is to prevent a new instance from running if one is already running
QSharedMemory sharedMemory(kCoreBinName);
// Attempt to attach first and detach in order to clean up stale shm chunks
// This can happen if the previous instance was killed or crashed
if (sharedMemory.attach())
sharedMemory.detach();
if (!sharedMemory.create(1) && parser.singleInstanceOnly()) {
LOG_WARN("an instance of deskflow core is already running");
return s_exitDuplicate;
}
parser.parse();
EventQueue events;
2025-09-25 01:35:20 +00:00
const auto processName = QFileInfo(argv[0]).fileName();
2025-12-05 18:09:25 +00:00
App *coreApp = createApp(parser, events, processName);
QApplication app(argc, argv);
QApplication::setApplicationName(QStringLiteral("%1 Core").arg(kAppName));
2025-12-05 18:09:25 +00:00
const auto ipcServer = new deskflow::core::ipc::CoreIpcServer(&app); // NOSONAR - Qt managed
ipcServer->listen();
2025-12-05 18:09:25 +00:00
QThread coreThread;
QObject::connect(&coreThread, &QThread::finished, &app, &QApplication::quit);
2025-12-05 18:09:25 +00:00
coreApp->run(coreThread);
int exitCode = QApplication::exec();
2025-12-05 18:09:25 +00:00
coreThread.wait();
if (exitCode == s_exitSuccess) {
exitCode = coreApp->getExitCode();
}
2025-12-05 18:09:25 +00:00
LOG_DEBUG("core exited, code: %d", exitCode);
return exitCode;
}