fix(mac): Remove Cocoa app loop and fix macOS event tap for Qt threading
This commit is contained in:
parent
29352d97b3
commit
aaef600ffa
7 changed files with 30 additions and 44 deletions
|
|
@ -23,7 +23,6 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
#include "platform/OSXCocoaApp.h"
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -172,7 +171,4 @@ void App::handleScreenError() const
|
||||||
void App::runEventsLoop(const void *)
|
void App::runEventsLoop(const void *)
|
||||||
{
|
{
|
||||||
m_events->loop();
|
m_events->loop();
|
||||||
#if defined(Q_OS_MAC)
|
|
||||||
stopCocoaLoop();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
#include "base/TMethodJob.h"
|
|
||||||
#include "mt/Thread.h"
|
|
||||||
#include "platform/OSXCocoaApp.h"
|
|
||||||
#include "platform/OSXScreen.h"
|
#include "platform/OSXScreen.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -330,17 +327,7 @@ int ClientApp::mainLoop()
|
||||||
// later. the timer installed by startClient() will take care of
|
// later. the timer installed by startClient() will take care of
|
||||||
// that.
|
// that.
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
|
||||||
Thread thread(new TMethodJob<ClientApp>(this, &ClientApp::runEventsLoop, nullptr));
|
|
||||||
|
|
||||||
// wait until carbon loop is ready
|
|
||||||
OSXScreen *screen = dynamic_cast<OSXScreen *>(m_clientScreen->getPlatformScreen());
|
|
||||||
screen->waitForCarbonLoop();
|
|
||||||
|
|
||||||
runCocoaApp();
|
|
||||||
#else
|
|
||||||
getEvents()->loop();
|
getEvents()->loop();
|
||||||
#endif
|
|
||||||
|
|
||||||
// close down
|
// close down
|
||||||
LOG_DEBUG("stopping client");
|
LOG_DEBUG("stopping client");
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
#include "base/TMethodJob.h"
|
|
||||||
#include "mt/Thread.h"
|
|
||||||
#include "platform/OSXCocoaApp.h"
|
|
||||||
#include "platform/OSXScreen.h"
|
#include "platform/OSXScreen.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -541,18 +538,7 @@ int ServerApp::mainLoop()
|
||||||
// later. the timer installed by startServer() will take care of
|
// later. the timer installed by startServer() will take care of
|
||||||
// that.
|
// that.
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
|
||||||
|
|
||||||
Thread thread(new TMethodJob<ServerApp>(this, &ServerApp::runEventsLoop, nullptr));
|
|
||||||
|
|
||||||
// wait until carbon loop is ready
|
|
||||||
OSXScreen *screen = dynamic_cast<OSXScreen *>(m_serverScreen->getPlatformScreen());
|
|
||||||
screen->waitForCarbonLoop();
|
|
||||||
|
|
||||||
runCocoaApp();
|
|
||||||
#else
|
|
||||||
getEvents()->loop();
|
getEvents()->loop();
|
||||||
#endif
|
|
||||||
|
|
||||||
// close down
|
// close down
|
||||||
LOG_DEBUG("stopping server");
|
LOG_DEBUG("stopping server");
|
||||||
|
|
|
||||||
|
|
@ -58,16 +58,11 @@ IEventQueueBuffer::Type OSXEventQueueBuffer::getEvent(Event &event, uint32_t &da
|
||||||
|
|
||||||
bool OSXEventQueueBuffer::addEvent(uint32_t dataID)
|
bool OSXEventQueueBuffer::addEvent(uint32_t dataID)
|
||||||
{
|
{
|
||||||
// Use GCD to dispatch event addition on the main queue
|
std::scoped_lock lock{m_mutex};
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
LOG_DEBUG2("adding user event with dataID: %u", dataID);
|
||||||
std::scoped_lock lock{this->m_mutex};
|
m_dataQueue.push(dataID);
|
||||||
LOG_DEBUG2("adding user event with dataID: %u", dataID);
|
m_cond.notify_one();
|
||||||
this->m_dataQueue.push(dataID);
|
LOG_DEBUG2("user event added to queue, dataID=%u", dataID);
|
||||||
this->m_cond.notify_one();
|
|
||||||
LOG_DEBUG2("user event added to queue, dataID=%u", dataID);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Always return true since dispatch_async does not fail under normal conditions
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
#include "base/IEventQueueBuffer.h"
|
#include "base/IEventQueueBuffer.h"
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <dispatch/dispatch.h>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
|
@ -292,6 +293,8 @@ private:
|
||||||
// Quartz input event support
|
// Quartz input event support
|
||||||
CFMachPortRef m_eventTapPort;
|
CFMachPortRef m_eventTapPort;
|
||||||
CFRunLoopSourceRef m_eventTapRLSR;
|
CFRunLoopSourceRef m_eventTapRLSR;
|
||||||
|
std::thread m_eventTapThread;
|
||||||
|
CFRunLoopRef m_eventTapRunLoop = nullptr;
|
||||||
|
|
||||||
// for double click coalescing.
|
// for double click coalescing.
|
||||||
double m_lastClickTime;
|
double m_lastClickTime;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include <AppKit/NSEvent.h>
|
#include <AppKit/NSEvent.h>
|
||||||
#include <AvailabilityMacros.h>
|
#include <AvailabilityMacros.h>
|
||||||
#include <IOKit/hidsystem/event_status_driver.h>
|
#include <IOKit/hidsystem/event_status_driver.h>
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
#include <libproc.h>
|
#include <libproc.h>
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
@ -686,7 +687,20 @@ void OSXScreen::enable()
|
||||||
if (m_eventTapPort) {
|
if (m_eventTapPort) {
|
||||||
m_eventTapRLSR = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPort, 0);
|
m_eventTapRLSR = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPort, 0);
|
||||||
if (m_eventTapRLSR) {
|
if (m_eventTapRLSR) {
|
||||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode);
|
// Run the event tap on a dedicated thread with its own CFRunLoop so it fires
|
||||||
|
// independently of whatever event loop the calling thread runs (e.g. QCoreApplication).
|
||||||
|
// Use a semaphore to ensure m_eventTapRunLoop is set before enable() returns.
|
||||||
|
auto sem = dispatch_semaphore_create(0);
|
||||||
|
m_eventTapThread = std::thread([this, sem]() {
|
||||||
|
m_eventTapRunLoop = CFRunLoopGetCurrent();
|
||||||
|
CFRunLoopAddSource(m_eventTapRunLoop, m_eventTapRLSR, kCFRunLoopDefaultMode);
|
||||||
|
dispatch_semaphore_signal(sem);
|
||||||
|
CFRunLoopRun();
|
||||||
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode);
|
||||||
|
m_eventTapRunLoop = nullptr;
|
||||||
|
});
|
||||||
|
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
|
||||||
|
dispatch_release(sem);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERR("failed to create a CFRunLoopSourceRef for the quartz event tap");
|
LOG_ERR("failed to create a CFRunLoopSourceRef for the quartz event tap");
|
||||||
}
|
}
|
||||||
|
|
@ -701,8 +715,14 @@ void OSXScreen::disable()
|
||||||
|
|
||||||
// FIXME -- stop watching jump zones, stop capturing input
|
// FIXME -- stop watching jump zones, stop capturing input
|
||||||
|
|
||||||
|
if (m_eventTapRunLoop) {
|
||||||
|
CFRunLoopStop(m_eventTapRunLoop);
|
||||||
|
}
|
||||||
|
if (m_eventTapThread.joinable()) {
|
||||||
|
m_eventTapThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_eventTapRLSR) {
|
if (m_eventTapRLSR) {
|
||||||
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode);
|
|
||||||
CFRelease(m_eventTapRLSR);
|
CFRelease(m_eventTapRLSR);
|
||||||
m_eventTapRLSR = nullptr;
|
m_eventTapRLSR = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue