feat: Convert daemon to Qt app and introduce Qt local server
This commit is contained in:
@ -14,6 +14,8 @@ if(WIN32)
|
||||
|
||||
add_executable(${target} WIN32 ${target}.cpp ${CMAKE_CURRENT_BINARY_DIR}/${target}.rc)
|
||||
|
||||
find_package(Qt6 COMPONENTS Core Network)
|
||||
|
||||
target_link_libraries(
|
||||
${target}
|
||||
arch
|
||||
@ -24,7 +26,8 @@ if(WIN32)
|
||||
net
|
||||
platform
|
||||
app
|
||||
${libs})
|
||||
${libs}
|
||||
Qt6::Core)
|
||||
|
||||
install(
|
||||
TARGETS ${target}
|
||||
|
||||
@ -41,8 +41,8 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
Log log;
|
||||
EventQueue events;
|
||||
|
||||
DaemonApp app(&events);
|
||||
return app.run(__argc, __argv);
|
||||
DaemonApp app(&events, __argc, __argv);
|
||||
return DaemonApp::exec();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -49,6 +49,8 @@ endif()
|
||||
####################Start Making Library#########################
|
||||
set(lib_name app)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
# arch
|
||||
if(WIN32)
|
||||
set(PLATFORM_CODE
|
||||
@ -143,8 +145,12 @@ add_library(${lib_name} STATIC ${PLATFORM_CODE}
|
||||
XScreen.h
|
||||
languages/LanguageManager.cpp
|
||||
languages/LanguageManager.h
|
||||
ipc/IpcServer2.cpp
|
||||
ipc/IpcServer2.h
|
||||
)
|
||||
|
||||
find_package(Qt6 COMPONENTS Core Network)
|
||||
target_link_libraries(${lib_name} PRIVATE Qt6::Core Qt6::Network)
|
||||
|
||||
if(WIN32)
|
||||
target_compile_definitions(${lib_name} PUBLIC HAVE_WINTOAST)
|
||||
@ -161,6 +167,7 @@ target_include_directories(
|
||||
if(UNIX)
|
||||
target_link_libraries(
|
||||
${lib_name}
|
||||
PRIVATE
|
||||
arch
|
||||
client
|
||||
ipc
|
||||
@ -174,12 +181,13 @@ if(UNIX)
|
||||
)
|
||||
|
||||
if(NOT APPLE)
|
||||
target_link_libraries(${lib_name} pugixml)
|
||||
target_link_libraries(${lib_name} PRIVATE pugixml)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
target_link_libraries(${lib_name} PkgConfig::lib_glib
|
||||
PkgConfig::lib_gdkpixbuf PkgConfig::lib_notify)
|
||||
target_link_libraries(${lib_name}
|
||||
PRIVATE
|
||||
PkgConfig::lib_glib PkgConfig::lib_gdkpixbuf PkgConfig::lib_notify)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include "ipc/IpcClientProxy.h"
|
||||
#include "ipc/IpcLogOutputter.h"
|
||||
#include "ipc/IpcMessage.h"
|
||||
#include "ipc/IpcServer2.h"
|
||||
#include "ipc/IpcSettingMessage.h"
|
||||
#include "net/SocketMultiplexer.h"
|
||||
|
||||
@ -95,8 +96,16 @@ int winMainLoopStatic(int, const char **)
|
||||
}
|
||||
#endif
|
||||
|
||||
DaemonApp::DaemonApp(IEventQueue *events) : m_events(events)
|
||||
DaemonApp::DaemonApp(IEventQueue *events, int argc, char **argv)
|
||||
: QCoreApplication(argc, argv),
|
||||
m_events(events),
|
||||
m_ipcServer2{new deskflow::ipc::IpcServer2(this)}
|
||||
{
|
||||
// HACK: init used to be run, which was the main loop.
|
||||
// now it's used for arg parsing, install/uninstall, etc.
|
||||
if (init(argc, argv) != kExitSuccess) {
|
||||
exit(kExitFailed);
|
||||
}
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
@ -105,7 +114,14 @@ DaemonApp::~DaemonApp()
|
||||
s_instance = nullptr;
|
||||
}
|
||||
|
||||
int DaemonApp::run(int argc, char **argv)
|
||||
void DaemonApp::startAsync()
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
m_watchdog->startAsync();
|
||||
#endif
|
||||
}
|
||||
|
||||
int DaemonApp::init(int argc, char **argv)
|
||||
{
|
||||
bool uninstall = false;
|
||||
try {
|
||||
@ -141,27 +157,11 @@ int DaemonApp::run(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
if (!foreground) {
|
||||
#if SYSAPI_WIN32
|
||||
// Only use MS debug outputter when the process is daemonized, since stdout won't be accessible
|
||||
// in that case, but is accessible when running in the foreground.
|
||||
CLOG->insert(new MSWindowsDebugOutputter()); // NOSONAR -- Adopted by `Log`
|
||||
}
|
||||
#endif
|
||||
|
||||
if (foreground) {
|
||||
LOG((CLOG_NOTE "starting daemon in foreground"));
|
||||
|
||||
// run process in foreground instead of daemonizing.
|
||||
// useful for debugging.
|
||||
mainLoop(false, foreground);
|
||||
} else {
|
||||
#if SYSAPI_WIN32
|
||||
LOG((CLOG_PRINT "daemonizing windows service"));
|
||||
ARCH->daemonize(kAppName, winMainLoopStatic);
|
||||
#elif SYSAPI_UNIX
|
||||
LOG((CLOG_PRINT "daemonizing unix service"));
|
||||
ARCH->daemonize(kAppName, unixMainLoopStatic);
|
||||
CLOG->insert(new MSWindowsDebugOutputter()); // NOSONAR - Adopted by `Log`
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -255,7 +255,7 @@ void DaemonApp::mainLoop(bool logToFile, bool foreground)
|
||||
void DaemonApp::foregroundError(const char *message)
|
||||
{
|
||||
#if SYSAPI_WIN32
|
||||
MessageBox(NULL, message, "Deskflow Service", MB_OK | MB_ICONERROR);
|
||||
MessageBoxA(NULL, message, "Deskflow Service", MB_OK | MB_ICONERROR);
|
||||
#elif SYSAPI_UNIX
|
||||
cerr << message << endl;
|
||||
#endif
|
||||
|
||||
@ -11,9 +11,16 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
class Event;
|
||||
class IpcLogOutputter;
|
||||
class FileLogOutputter;
|
||||
class QLocalServer;
|
||||
|
||||
namespace deskflow::ipc {
|
||||
class IpcServer2;
|
||||
}
|
||||
|
||||
#if SYSAPI_WIN32
|
||||
class MSWindowsWatchdog;
|
||||
@ -21,16 +28,16 @@ class MSWindowsWatchdog;
|
||||
|
||||
extern const char *const kLogFilename;
|
||||
|
||||
class DaemonApp
|
||||
class DaemonApp : public QCoreApplication
|
||||
{
|
||||
|
||||
public:
|
||||
DaemonApp(IEventQueue *events);
|
||||
DaemonApp(IEventQueue *events, int argc, char **argv);
|
||||
~DaemonApp();
|
||||
int run(int argc, char **argv);
|
||||
void startAsync();
|
||||
void mainLoop(bool logToFile, bool foreground = false);
|
||||
|
||||
private:
|
||||
int init(int argc, char **argv);
|
||||
void daemonize();
|
||||
void foregroundError(const char *message);
|
||||
std::string logFilename();
|
||||
@ -48,4 +55,5 @@ private:
|
||||
std::unique_ptr<IpcLogOutputter> m_ipcLogOutputter;
|
||||
IEventQueue *m_events = nullptr;
|
||||
FileLogOutputter *m_fileLogOutputter = nullptr;
|
||||
std::unique_ptr<deskflow::ipc::IpcServer2> m_ipcServer2;
|
||||
};
|
||||
|
||||
29
src/lib/deskflow/ipc/IpcServer2.cpp
Normal file
29
src/lib/deskflow/ipc/IpcServer2.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "IpcServer2.h"
|
||||
|
||||
#include "base/Log.h"
|
||||
|
||||
#include <QLocalServer>
|
||||
|
||||
namespace deskflow::ipc {
|
||||
|
||||
const auto kServerName = QStringLiteral("deskflow-daemon");
|
||||
|
||||
IpcServer2::IpcServer2(QObject *parent) : QObject(parent), m_server{new QLocalServer(this)}
|
||||
{
|
||||
m_server->removeServer(kServerName);
|
||||
m_server->listen(kServerName);
|
||||
LOG_INFO("ipc server listening on %s", kServerName.toStdString().c_str());
|
||||
}
|
||||
|
||||
IpcServer2::~IpcServer2()
|
||||
{
|
||||
m_server->close();
|
||||
}
|
||||
|
||||
} // namespace deskflow::ipc
|
||||
27
src/lib/deskflow/ipc/IpcServer2.h
Normal file
27
src/lib/deskflow/ipc/IpcServer2.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QLocalServer;
|
||||
|
||||
namespace deskflow::ipc {
|
||||
|
||||
class IpcServer2 : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IpcServer2(QObject *parent);
|
||||
~IpcServer2();
|
||||
|
||||
private:
|
||||
QLocalServer *m_server;
|
||||
};
|
||||
|
||||
} // namespace deskflow::ipc
|
||||
Reference in New Issue
Block a user