Skip to content
Merged

a #2

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6a1e8f3
chore: remove unused QMessageBox includes and Foward Declaration
sithlord48 Apr 6, 2026
632b64f
chore: MainWindow remove unused forward declariations
sithlord48 Apr 6, 2026
0474516
refactor: Messages::showFirstConnectionMessage check the settings for…
sithlord48 Apr 4, 2026
d8e9ac2
refactor: Messages::showNewClientPrompt check if server auth is neede…
sithlord48 Apr 4, 2026
8a77e5f
refactor(core): Convert app to Qt app
nbolton Dec 5, 2025
29352d9
fix(core): Destroy temporary QCoreApplication before creating the rea…
nbolton Mar 26, 2026
aaef600
fix(mac): Remove Cocoa app loop and fix macOS event tap for Qt threading
nbolton Mar 30, 2026
b0985a2
fix(unix): Add foreign Qt threds in legacy POSIX thread impl
nbolton Mar 26, 2026
eebe5fd
refactor(win32): Rename Windows thread finding methods for consistency
nbolton Mar 26, 2026
e4bafaf
refactor(win32): More consistent Windows desk switch log line
nbolton Mar 31, 2026
2e13074
refactor(ipc): Abstract IPC server logic
nbolton Dec 5, 2025
1ec3664
refactor(ipc): Abstract IPC client logic
nbolton Dec 5, 2025
62ccb54
feat(ipc): Core IPC server and connected client
nbolton Dec 5, 2025
66c9b66
feat(ipc): Messaging for connection states via IPC (async client)
nbolton Mar 26, 2026
59a4747
feat(ipc): Unrecognised IPC client, retry messages, and TLS fingerprint
nbolton Mar 26, 2026
682966f
feat(ipc): Handle missing keyboard layouts with IPC
nbolton Mar 30, 2026
25f3eb3
feat(ipc): Differentiate between Daemon and Core IPC logs
nbolton Mar 31, 2026
77bee2d
feat(ipc): Log more detail on IPC error handling
nbolton Mar 31, 2026
7c30add
feat(ipc): Error handling for missing version in IPC handshake
nbolton Apr 7, 2026
7f2953d
ci: Remove stale action
sithlord48 Apr 6, 2026
bdb7309
refactor(ipcClient): declare values in if statement where possible
sithlord48 Apr 7, 2026
d1074f6
refactor(ipc): use more QStringLiterals
sithlord48 Apr 8, 2026
e293d4e
refactor(ipc): add missing use of at for lists
sithlord48 Apr 8, 2026
1922f91
refactor: Move -> deskflow/languages/LanguageManager -> deskflow/Keyb…
sithlord48 Apr 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions .github/workflows/issue-check-stale.yml

This file was deleted.

46 changes: 34 additions & 12 deletions src/apps/deskflow-core/deskflow-core.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
* 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
*/
Expand All @@ -15,27 +15,41 @@
#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"
#include <QCoreApplication>
#endif

#include <QCoreApplication>
#include <QFileInfo>
#include <QSharedMemory>
#include <QTextStream>
#include <QThread>

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)
// HACK to make sure settings gets the correct qApp path
QCoreApplication m(argc, argv);
m.deleteLater();
{
// HACK to make sure settings gets the correct qApp path
QCoreApplication m(argc, argv);
}

ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
#endif
Expand Down Expand Up @@ -86,13 +100,21 @@ 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);

QCoreApplication app(argc, argv);
QCoreApplication::setApplicationName(QStringLiteral("%1 Core").arg(kAppName));

const auto ipcServer = new deskflow::core::ipc::CoreIpcServer(&app); // NOSONAR - Qt managed
ipcServer->listen();

QThread coreThread;
QObject::connect(&coreThread, &QThread::finished, &app, &QCoreApplication::quit);
coreApp->run(coreThread);

const auto exitCode = QCoreApplication::exec();
coreThread.wait();

return s_exitSuccess;
LOG_DEBUG("core exited, code: %d", exitCode);
return exitCode;
}
16 changes: 15 additions & 1 deletion src/lib/arch/unix/ArchMultithreadPosix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,13 +517,27 @@ void ArchMultithreadPosix::startSignalHandler()

ArchThreadImpl *ArchMultithreadPosix::find(pthread_t thread)
{
ArchThreadImpl *impl = findNoRef(thread);
ArchThreadImpl *impl = findNoRefOrInsert(thread);
if (impl != nullptr) {
refThread(impl);
}
return impl;
}

ArchThreadImpl *ArchMultithreadPosix::findNoRefOrInsert(pthread_t thread)
{
ArchThreadImpl *impl = findNoRef(thread);
if (impl == nullptr) {
// create thread for calling thread which isn't in our list and
// add it to the list. this can happen when a foreign thread
// (e.g. a Qt thread) calls into the arch layer.
impl = new ArchThreadImpl;
impl->m_thread = thread;
insert(impl);
}
return impl;
}

ArchThreadImpl *ArchMultithreadPosix::findNoRef(pthread_t thread)
{
// linear search
Expand Down
1 change: 1 addition & 0 deletions src/lib/arch/unix/ArchMultithreadPosix.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class ArchMultithreadPosix : public IArchMultithread

ArchThreadImpl *find(pthread_t thread);
ArchThreadImpl *findNoRef(pthread_t thread);
ArchThreadImpl *findNoRefOrInsert(pthread_t thread);
void insert(ArchThreadImpl *thread);
void erase(const ArchThreadImpl *thread);

Expand Down
39 changes: 19 additions & 20 deletions src/lib/arch/win32/ArchMultithreadWindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ ArchMultithreadWindows::~ArchMultithreadWindows()
void ArchMultithreadWindows::setNetworkDataForCurrentThread(void *data)
{
std::scoped_lock lock{m_threadMutex};
ArchThreadImpl *thread = findNoRef(GetCurrentThreadId());
ArchThreadImpl *thread = findNoRefOrInsert(GetCurrentThreadId());
thread->m_networkData = data;
}

Expand All @@ -121,7 +121,7 @@ void *ArchMultithreadWindows::getNetworkDataForThread(ArchThread thread)
HANDLE ArchMultithreadWindows::getCancelEventForCurrentThread()
{
std::scoped_lock lock{m_threadMutex};
ArchThreadImpl *thread = findNoRef(GetCurrentThreadId());
ArchThreadImpl *thread = findNoRefOrInsert(GetCurrentThreadId());
return thread->m_cancel;
}

Expand Down Expand Up @@ -305,7 +305,7 @@ void ArchMultithreadWindows::closeThread(ArchThread thread)
// remove thread from list
{
std::scoped_lock lock{m_threadMutex};
assert(findNoRefOrCreate(thread->m_id) == thread);
assert(findNoRef(thread->m_id) == thread);
erase(thread);
}

Expand Down Expand Up @@ -390,7 +390,7 @@ void ArchMultithreadWindows::testCancelThread()
{
// find current thread
std::scoped_lock lock{m_threadMutex};
ArchThreadImpl *thread = findNoRef(GetCurrentThreadId());
ArchThreadImpl *thread = findNoRefOrInsert(GetCurrentThreadId());

// test cancel on thread
testCancelThreadImpl(thread);
Expand All @@ -404,7 +404,7 @@ bool ArchMultithreadWindows::wait(ArchThread target, double timeout)
{
std::scoped_lock lock{m_threadMutex};
// find current thread
self = findNoRef(GetCurrentThreadId());
self = findNoRefOrInsert(GetCurrentThreadId());
// ignore wait if trying to wait on ourself
if (target == self) {
return false;
Expand Down Expand Up @@ -497,7 +497,7 @@ void ArchMultithreadWindows::raiseSignal(ThreadSignal signal)

ArchThreadImpl *ArchMultithreadWindows::find(DWORD id)
{
ArchThreadImpl *impl = findNoRef(id);
ArchThreadImpl *impl = findNoRefOrInsert(id);
if (impl != nullptr) {
refThread(impl);
}
Expand All @@ -506,7 +506,17 @@ ArchThreadImpl *ArchMultithreadWindows::find(DWORD id)

ArchThreadImpl *ArchMultithreadWindows::findNoRef(DWORD id)
{
ArchThreadImpl *impl = findNoRefOrCreate(id);
for (ThreadList::const_iterator index = m_threadList.begin(); index != m_threadList.end(); ++index) {
if ((*index)->m_id == id) {
return *index;
}
}
return nullptr;
}

ArchThreadImpl *ArchMultithreadWindows::findNoRefOrInsert(DWORD id)
{
ArchThreadImpl *impl = findNoRef(id);
if (impl == nullptr) {
// create thread for calling thread which isn't in our list and
// add it to the list. this won't normally happen but it can if
Expand All @@ -520,23 +530,12 @@ ArchThreadImpl *ArchMultithreadWindows::findNoRef(DWORD id)
return impl;
}

ArchThreadImpl *ArchMultithreadWindows::findNoRefOrCreate(DWORD id)
{
// linear search
for (ThreadList::const_iterator index = m_threadList.begin(); index != m_threadList.end(); ++index) {
if ((*index)->m_id == id) {
return *index;
}
}
return nullptr;
}

void ArchMultithreadWindows::insert(ArchThreadImpl *thread)
{
assert(thread != nullptr);

// thread shouldn't already be on the list
assert(findNoRefOrCreate(thread->m_id) == nullptr);
assert(findNoRef(thread->m_id) == nullptr);

// append to list
m_threadList.push_back(thread);
Expand All @@ -555,7 +554,7 @@ void ArchMultithreadWindows::erase(ArchThreadImpl *thread)
void ArchMultithreadWindows::refThread(ArchThreadImpl *thread)
{
assert(thread != nullptr);
assert(findNoRefOrCreate(thread->m_id) != nullptr);
assert(findNoRef(thread->m_id) != nullptr);
++thread->m_refCount;
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/arch/win32/ArchMultithreadWindows.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class ArchMultithreadWindows : public IArchMultithread
private:
ArchThreadImpl *find(DWORD id);
ArchThreadImpl *findNoRef(DWORD id);
ArchThreadImpl *findNoRefOrCreate(DWORD id);
ArchThreadImpl *findNoRefOrInsert(DWORD id);
void insert(ArchThreadImpl *thread);
void erase(ArchThreadImpl *thread);

Expand Down
2 changes: 0 additions & 2 deletions src/lib/base/Log.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ otherwise it expands to a call that doesn't.
// end, then we resort to using non-numerical chars. this still works (since
// to deduce the number we subtract octal \060, so '/' is -1, and ':' is 10

#define CLOG_IPC CLOG_TRACE "%z\056" // char is '' ?
#define CLOG_PRINT CLOG_TRACE "%z\057" // char is '/'
#define CLOG_CRIT CLOG_TRACE "%z\060" // char is '0'
#define CLOG_ERR CLOG_TRACE "%z\061"
Expand All @@ -210,7 +209,6 @@ otherwise it expands to a call that doesn't.
#define CLOG_DEBUG1 CLOG_TRACE "%z\066"
#define CLOG_DEBUG2 CLOG_TRACE "%z\067"

#define LOG_IPC(...) LOG((CLOG_IPC __VA_ARGS__))
#define LOG_PRINT(...) LOG((CLOG_PRINT __VA_ARGS__))
#define LOG_CRIT(...) LOG((CLOG_CRIT __VA_ARGS__))
#define LOG_ERR(...) LOG((CLOG_ERR __VA_ARGS__))
Expand Down
11 changes: 9 additions & 2 deletions src/lib/client/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
#include "deskflow/ProtocolUtil.h"
#include "deskflow/Screen.h"
#include "deskflow/StreamChunker.h"
#include "deskflow/ipc/CoreIpc.h"
#include "net/IDataSocket.h"
#include "net/ISocketFactory.h"
#include "net/SecureSocket.h"
#include "net/TCPSocket.h"

#include <QMetaEnum>

#include <cstdlib>
#include <cstring>

Expand Down Expand Up @@ -92,10 +95,11 @@ void Client::connect(size_t addressIndex)
// m_serverAddress will be null if the hostname address is not reolved
if (m_serverAddress.getAddress() != nullptr) {
// to help users troubleshoot, show server host name (issue: 60)
LOG_IPC(
LOG_DEBUG(
"connecting to '%s': %s:%i", m_serverAddress.getHostname().c_str(),
ARCH->addrToString(m_serverAddress.getAddress()).c_str(), m_serverAddress.getPort()
);
ipcSendConnectionState(deskflow::core::ConnectionState::Connecting);
}

// create the socket
Expand Down Expand Up @@ -131,8 +135,11 @@ void Client::disconnect(const char *msg)
}
}

void Client::refuseConnection(const char *msg)
void Client::refuseConnection(deskflow::core::ConnectionRefusal reason, const char *msg)
{
const auto metaEnum = QMetaEnum::fromType<deskflow::core::ConnectionRefusal>();
ipcSendToClient("connectionRefused", metaEnum.valueToKey(static_cast<int>(reason)));

cleanup();

if (msg) {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/client/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "deskflow/IClient.h"

#include "base/EventTypes.h"
#include "common/Enums.h"
#include "deskflow/IClipboard.h"
#include "net/NetworkAddress.h"

Expand Down Expand Up @@ -88,7 +89,7 @@ class Client : public IClient
Disconnects from the server with an optional error message.
Unlike disconnect this function doesn't try to use other ip addresses
*/
void refuseConnection(const char *msg);
void refuseConnection(deskflow::core::ConnectionRefusal reason, const char *msg);

//! Notify of handshake complete
/*!
Expand Down
Loading
Loading