fix(mac): quit core if accessibility permissions are revoked

This commit is contained in:
Luiz Sardinha 2026-03-30 20:39:03 +02:00 committed by Chris Rizzitello
parent 9025ab8fb7
commit 5a028c12d4
2 changed files with 33 additions and 4 deletions

View file

@ -157,6 +157,8 @@ private:
void handleConfirmSleep(const Event &event);
bool checkAXPermissions();
// global hotkey operating mode
static bool isGlobalHotKeyOperatingModeAvailable();
static void setGlobalHotKeysEnabled(bool enabled);
@ -261,6 +263,8 @@ private:
bool m_ownClipboard;
EventQueueTimer *m_clipboardTimer;
EventQueueTimer *m_axTimer;
// window object that gets user input events when the server
// has focus.
WindowRef m_hiddenWindow;

View file

@ -10,11 +10,13 @@
#include "arch/Arch.h"
#include "arch/ArchException.h"
#include "base/Event.h"
#include "base/EventQueue.h"
#include "base/IEventQueue.h"
#include "base/Log.h"
#include "base/TMethodJob.h"
#include "client/Client.h"
#include "common/ExitCodes.h"
#include "common/Settings.h"
#include "deskflow/ClientApp.h"
#include "deskflow/Clipboard.h"
@ -88,6 +90,7 @@ OSXScreen::OSXScreen(IEventQueue *events, bool isPrimary, bool enableLangSync)
m_screensaverNotify(false),
m_ownClipboard(false),
m_clipboardTimer(nullptr),
m_axTimer(nullptr),
m_hiddenWindow(nullptr),
m_userInputWindow(nullptr),
m_switchEventHandlerRef(0),
@ -659,6 +662,9 @@ void OSXScreen::enable()
m_clipboardTimer = m_events->newTimer(1.0, nullptr);
m_events->addHandler(EventTypes::Timer, m_clipboardTimer, [this](const auto &) { checkClipboards(); });
m_axTimer = m_events->newTimer(1.0, nullptr);
m_events->addHandler(EventTypes::Timer, m_axTimer, [this](const auto &) { checkAXPermissions(); });
if (m_isPrimary) {
// FIXME -- start watching jump zones
@ -734,13 +740,18 @@ void OSXScreen::disable()
}
// FIXME -- allow system to enter power saving mode
// uninstall clipboard timer
if (m_clipboardTimer != nullptr) {
m_events->removeHandler(EventTypes::Timer, m_clipboardTimer);
m_events->deleteTimer(m_clipboardTimer);
m_clipboardTimer = nullptr;
}
if (m_axTimer != nullptr) {
m_events->removeHandler(EventTypes::Timer, m_axTimer);
m_events->deleteTimer(m_axTimer);
m_axTimer = nullptr;
}
m_isOnScreen = m_isPrimary;
}
@ -1491,6 +1502,18 @@ void OSXScreen::handleConfirmSleep(const Event &event)
}
}
bool OSXScreen::checkAXPermissions()
{
if (AXIsProcessTrusted()) {
return true;
}
LOG_CRIT("process is not trusted anymore, quitting");
disable();
App &app = App::instance();
app.getEvents()->addEvent(Event(EventTypes::Quit, nullptr, new ExitEventData(s_exitFailed)));
return false;
}
#pragma mark -
//
@ -1679,9 +1702,11 @@ CGEventRef OSXScreen::handleCGInputEvent(CGEventTapProxy proxy, CGEventType type
screen->onKey(event);
break;
case kCGEventTapDisabledByTimeout:
// Re-enable our event-tap
// Re-enable our event-tap if we still have accessibility permissions
if (screen->checkAXPermissions()) {
CGEventTapEnable(screen->m_eventTapPort, true);
LOG_INFO("quartz event tap was disabled by timeout, re-enabling");
}
break;
case kCGEventTapDisabledByUserInput:
LOG_ERR("quartz event tap was disabled by user input");