146 lines
4 KiB
C++
146 lines
4 KiB
C++
/*
|
|
* Deskflow -- mouse and keyboard sharing utility
|
|
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
|
* SPDX-FileCopyrightText: (C) 2012 - 2016, 2025 - 2026 Synergy App 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>
|
|
#include <QFileInfo>
|
|
#include <QSharedMemory>
|
|
#include <QTextStream>
|
|
#include <QThread>
|
|
|
|
void qtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
|
{
|
|
const auto utf8 = message.toUtf8();
|
|
switch (type) {
|
|
case QtDebugMsg:
|
|
CLOG->print(context.file, context.line, CLOG_TAG_DEBUG "%s", utf8.constData());
|
|
break;
|
|
case QtInfoMsg:
|
|
CLOG->print(context.file, context.line, CLOG_TAG_INFO "%s", utf8.constData());
|
|
break;
|
|
case QtWarningMsg:
|
|
CLOG->print(context.file, context.line, CLOG_TAG_WARN "%s", utf8.constData());
|
|
break;
|
|
case QtCriticalMsg:
|
|
CLOG->print(context.file, context.line, CLOG_TAG_ERR "%s", utf8.constData());
|
|
break;
|
|
case QtFatalMsg:
|
|
CLOG->print(context.file, context.line, CLOG_TAG_CRIT "%s", utf8.constData());
|
|
break;
|
|
}
|
|
if (type == QtFatalMsg) {
|
|
abort();
|
|
}
|
|
}
|
|
|
|
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)
|
|
ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
|
|
#endif
|
|
|
|
Arch arch;
|
|
arch.init();
|
|
|
|
Log log;
|
|
qInstallMessageHandler(qtMessageHandler);
|
|
|
|
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;
|
|
const auto processName = QFileInfo(argv[0]).fileName();
|
|
|
|
App *coreApp = createApp(parser, events, processName);
|
|
QApplication::setApplicationName(QStringLiteral("%1 Core").arg(kAppName));
|
|
QApplication app(argc, argv);
|
|
|
|
const auto ipcServer = new deskflow::core::ipc::CoreIpcServer(&app); // NOSONAR - Qt managed
|
|
QObject::connect(
|
|
ipcServer, &deskflow::core::ipc::IpcServer::stopProcessRequested, coreApp, &App::quit, Qt::DirectConnection
|
|
);
|
|
ipcServer->listen();
|
|
|
|
QThread coreThread;
|
|
QObject::connect(&coreThread, &QThread::finished, &app, &QApplication::quit);
|
|
coreApp->run(coreThread);
|
|
|
|
int exitCode = QApplication::exec();
|
|
coreThread.wait();
|
|
|
|
if (exitCode == s_exitSuccess) {
|
|
exitCode = coreApp->getExitCode();
|
|
}
|
|
|
|
LOG_DEBUG("core exited, code: %d", exitCode);
|
|
return exitCode;
|
|
}
|