1919#include <config.h>
2020#endif
2121
22+ // FIXME Move to osx_input_helper.h after testing.
23+ #ifndef USE_WEAK_IMPORT
24+ #include <dlfcn.h>
25+ #endif
26+
2227#include <ApplicationServices/ApplicationServices.h>
2328#include <pthread.h>
2429#include <stdbool.h>
@@ -38,19 +43,27 @@ pthread_mutex_t hook_control_mutex = PTHREAD_MUTEX_INITIALIZER;
3843static pthread_t hook_thread_id ; // TODO = 0; ?
3944static pthread_attr_t hook_thread_attr ;
4045
41- // Required to dynamically check for AXIsProcessTrustedWithOptions availability.
4246// FIXME Move to osx_input_helper.h after testing.
47+ #ifdef USE_WEAK_IMPORT
48+ // Required to dynamically check for AXIsProcessTrustedWithOptions availability.
4349extern Boolean AXIsProcessTrustedWithOptions (CFDictionaryRef options ) __attribute__((weak_import ));
4450extern CFStringRef kAXTrustedCheckOptionPrompt __attribute__((weak_import ));
51+ #else
52+ typedef Boolean (* AXIsProcessTrustedWithOptions_t )(CFDictionaryRef options );
53+ typedef Boolean (* AXAPIEnabled_t )(void );
54+ #endif
4555
4656static void * hook_thread_proc (void * arg ) {
4757 int * status = (int * ) arg ;
4858 * status = UIOHOOK_FAILURE ;
4959
5060 bool accessibilityEnabled = false;
61+
62+ // FIXME Move to osx_input_helper.h after testing.
63+ #ifdef USE_WEAK_IMPORT
5164 // Check and make sure assistive devices is enabled.
5265 if (AXIsProcessTrustedWithOptions != NULL ) {
53- // 10.9 and later
66+ // New accessibility API 10.9 and later.
5467 const void * keys [] = { kAXTrustedCheckOptionPrompt };
5568 const void * values [] = { kCFBooleanTrue };
5669
@@ -65,9 +78,58 @@ static void *hook_thread_proc(void *arg) {
6578 accessibilityEnabled = AXIsProcessTrustedWithOptions (options );
6679 }
6780 else {
68- // 10.8 and older
81+ // Old accessibility check 10.8 and older.
6982 accessibilityEnabled = AXAPIEnabled ();
7083 }
84+ #else
85+ const char * dlError = NULL ;
86+ void * libApplicaitonServices = dlopen ("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices" , RTLD_LAZY );
87+ dlError = dlerror ();
88+ if (libApplicaitonServices != NULL && dlError == NULL ) {
89+ // Check for the new function AXIsProcessTrustedWithOptions().
90+ AXIsProcessTrustedWithOptions_t fpAXIsProcessTrustedWithOptions = (AXIsProcessTrustedWithOptions_t ) dlsym (libApplicaitonServices , "AXIsProcessTrustedWithOptions" );
91+ dlError = dlerror ();
92+ if (fpAXIsProcessTrustedWithOptions != NULL && dlError == NULL ) {
93+ // New accessibility API 10.9 and later.
94+ const void * keys [] = { kAXTrustedCheckOptionPrompt };
95+ const void * values [] = { kCFBooleanTrue };
96+
97+ CFDictionaryRef options = CFDictionaryCreate (
98+ kCFAllocatorDefault ,
99+ keys ,
100+ values ,
101+ sizeof (keys ) / sizeof (* keys ),
102+ & kCFCopyStringDictionaryKeyCallBacks ,
103+ & kCFTypeDictionaryValueCallBacks );
104+
105+ accessibilityEnabled = (* fpAXIsProcessTrustedWithOptions )(options );
106+ }
107+ else {
108+ logger (LOG_LEVEL_DEBUG , "%s [%u]: Failed to locate AXIsProcessTrustedWithOptions(). (%s)\n" ,
109+ __FUNCTION__ , __LINE__ , dlError );
110+
111+ // Check for the fallback function AXAPIEnabled().
112+ AXAPIEnabled_t fpAXAPIEnabled = (AXAPIEnabled_t ) dlsym (libApplicaitonServices , "AXAPIEnabled" );
113+ dlError = dlerror ();
114+ if (fpAXAPIEnabled != NULL && dlError == NULL ) {
115+ // Old accessibility check 10.8 and older.
116+ accessibilityEnabled = (* fpAXAPIEnabled )();
117+ }
118+ else {
119+ // Could not load the AXAPIEnabled function!
120+ logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to locate AXAPIEnabled()! (%s)\n" ,
121+ __FUNCTION__ , __LINE__ , dlError );
122+ }
123+ }
124+
125+ dlclose (libApplicaitonServices );
126+ }
127+ else {
128+ // Could not load the ApplicationServices framework!
129+ logger (LOG_LEVEL_ERROR , "%s [%u]: Failed to lazy load the ApplicationServices framework! (%s)\n" ,
130+ __FUNCTION__ , __LINE__ , dlError );
131+ }
132+ #endif
71133
72134 if (accessibilityEnabled == true) {
73135 logger (LOG_LEVEL_DEBUG , "%s [%u]: Accessibility API is enabled.\n" ,
0 commit comments