├── .gitignore ├── Classes ├── HAXApplication.h ├── HAXApplication.m ├── HAXButton.h ├── HAXButton.m ├── HAXElement+Protected.h ├── HAXElement.h ├── HAXElement.m ├── HAXSystem.h ├── HAXSystem.m ├── HAXView.h ├── HAXView.m ├── HAXWindow.h ├── HAXWindow.m ├── NSScreen+HAXPointConvert.h └── NSScreen+HAXPointConvert.m ├── Haxcessibility.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── LICENSE ├── Other Sources ├── Haxcessibility.h └── Haxcessibility.pch ├── README.mdown ├── Resources ├── English.lproj │ └── InfoPlist.strings └── Info.plist └── TODO.mdown /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata 3 | *.mode* 4 | *.pbxuser 5 | *.xcuserdatad 6 | *.xccheckout -------------------------------------------------------------------------------- /Classes/HAXApplication.h: -------------------------------------------------------------------------------- 1 | // HAXApplication.h 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import 6 | 7 | @class HAXWindow; 8 | 9 | @interface HAXApplication : HAXElement 10 | 11 | @property (nonatomic, readonly) HAXWindow *focusedWindow; 12 | @property (nonatomic, readonly) NSArray *windows; 13 | @property (nonatomic, copy, readonly) NSString *localizedName; 14 | @property (nonatomic, readonly) pid_t processIdentifier; 15 | 16 | +(instancetype)applicationWithPID:(pid_t)pid; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/HAXApplication.m: -------------------------------------------------------------------------------- 1 | // HAXApplication.m 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import "HAXApplication.h" 6 | #import "HAXElement+Protected.h" 7 | #import "HAXWindow.h" 8 | 9 | @implementation HAXApplication 10 | 11 | +(instancetype)applicationWithPID:(pid_t)pid { 12 | AXUIElementRef app = AXUIElementCreateApplication(pid); 13 | id result = nil; 14 | if (app) { 15 | result = [self elementWithElementRef:app]; 16 | CFRelease(app); 17 | } 18 | return result; 19 | } 20 | 21 | -(HAXWindow *)focusedWindow { 22 | return [self elementOfClass:[HAXWindow class] forKey:(NSString *)kAXFocusedWindowAttribute error:NULL]; 23 | } 24 | 25 | -(NSArray *)windows { 26 | NSArray *axWindowObjects = [self getAttributeValueForKey:(NSString *)kAXWindowsAttribute error:NULL]; 27 | NSMutableArray *result = [NSMutableArray arrayWithCapacity:[axWindowObjects count]]; 28 | for (id axObject in axWindowObjects) { 29 | [result addObject:[HAXWindow elementWithElementRef:(AXUIElementRef)axObject]]; 30 | } 31 | return result; 32 | } 33 | 34 | -(NSString *)localizedName { 35 | return [self getAttributeValueForKey:(NSString *)kAXTitleAttribute error:NULL]; 36 | } 37 | 38 | -(pid_t)processIdentifier { 39 | pid_t processIdentifier = 0; 40 | AXUIElementGetPid(self.elementRef, &processIdentifier); 41 | return processIdentifier; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Classes/HAXButton.h: -------------------------------------------------------------------------------- 1 | // HAXButton.h 2 | // Created by Kocsis Olivér on 2014-05-21 3 | // Copyright 2014 Joinect Technologies 4 | 5 | #import 6 | 7 | @interface HAXButton : HAXView 8 | 9 | -(void)press; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Classes/HAXButton.m: -------------------------------------------------------------------------------- 1 | // HAXButton.m 2 | // Created by Kocsis Olivér on 2014-05-21 3 | // Copyright 2014 Joinect Technologies 4 | 5 | #import "HAXButton.h" 6 | #import "HAXElement+Protected.h" 7 | 8 | @implementation HAXButton 9 | 10 | -(void)press { 11 | [self performAction:(__bridge NSString *)kAXPressAction error:NULL]; 12 | } 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Classes/HAXElement+Protected.h: -------------------------------------------------------------------------------- 1 | // HAXElement+Protected.h 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import 6 | 7 | @interface HAXElement () 8 | 9 | +(instancetype)elementWithElementRef:(AXUIElementRef)elementRef __attribute__((nonnull(1))); 10 | -(instancetype)initWithElementRef:(AXUIElementRef)elementRef __attribute__((nonnull(1))); 11 | 12 | @property (nonatomic, readonly) AXUIElementRef elementRef __attribute__((NSObject)); 13 | 14 | -(id)getAttributeValueForKey:(NSString *)key error:(NSError **)error __attribute__((nonnull(1))); 15 | -(CFTypeRef)copyAttributeValueForKey:(NSString *)key error:(NSError **)error __attribute__((nonnull(1))); 16 | -(BOOL)setAttributeValue:(CFTypeRef)value forKey:(NSString *)key error:(NSError **)error __attribute__((nonnull(1,2))); 17 | -(BOOL)performAction:(NSString *)action error:(NSError **)error __attribute__((nonnull(1))); 18 | 19 | -(id)elementOfClass:(Class)klass forKey:(NSString *)key error:(NSError **)error __attribute__((nonnull(1,2))); 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/HAXElement.h: -------------------------------------------------------------------------------- 1 | // HAXElement.h 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import 6 | 7 | @protocol HAXElementDelegate; 8 | 9 | @interface HAXElement : NSObject 10 | 11 | @property (nonatomic, weak) id delegate; 12 | @property (nonatomic, readonly) NSString *title; 13 | @property (nonatomic, readonly) NSString *role; 14 | @property (nonatomic, readonly) BOOL hasChildren; 15 | @property (nonatomic, readonly) NSArray *children; 16 | @property (nonatomic, readonly) NSArray *attributeNames; 17 | @property (nonatomic, readonly) NSArray *buttons; 18 | 19 | -(BOOL)isEqualToElement:(HAXElement *)other; 20 | 21 | @end 22 | 23 | @protocol HAXElementDelegate 24 | @optional 25 | -(void)elementWasDestroyed:(HAXElement *)element; 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/HAXElement.m: -------------------------------------------------------------------------------- 1 | // HAXElement.m 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import "HAXElement+Protected.h" 6 | #import "HAXButton.h" 7 | 8 | 9 | @interface HAXElement () 10 | 11 | @property (nonatomic, strong) AXObserverRef observer __attribute__((NSObject)); 12 | 13 | @end 14 | 15 | 16 | @implementation HAXElement 17 | 18 | +(instancetype)elementWithElementRef:(AXUIElementRef)elementRef { 19 | return [[self alloc] initWithElementRef:elementRef]; 20 | } 21 | 22 | -(instancetype)initWithElementRef:(AXUIElementRef)elementRef { 23 | if((self = [super init])) { 24 | _elementRef = CFRetain(elementRef); 25 | } 26 | return self; 27 | } 28 | 29 | -(void)dealloc { 30 | if (_observer) { 31 | [self removeAXObserver]; 32 | } 33 | if (_elementRef) { 34 | CFRelease(_elementRef); 35 | _elementRef = NULL; 36 | } 37 | } 38 | 39 | -(BOOL)isEqualToElement:(HAXElement *)other { 40 | return 41 | [other isKindOfClass:self.class] 42 | && CFEqual(self.elementRef, other.elementRef); 43 | } 44 | 45 | -(BOOL)isEqual:(id)object { 46 | return [self isEqualToElement:object]; 47 | } 48 | 49 | -(NSUInteger)hash { 50 | return CFHash(self.elementRef); 51 | } 52 | 53 | -(void)setDelegate:(id)delegate { 54 | if (delegate && !_observer) { 55 | [self addAXObserver]; 56 | } 57 | _delegate = delegate; 58 | } 59 | 60 | -(id)getAttributeValueForKey:(NSString *)key error:(NSError **)error { 61 | CFTypeRef result = [self copyAttributeValueForKey:key error:error]; 62 | return result ? CFBridgingRelease(result) : nil; 63 | } 64 | 65 | -(CFTypeRef)copyAttributeValueForKey:(NSString *)key error:(NSError **)error { 66 | NSParameterAssert(key != nil); 67 | CFTypeRef attributeRef = NULL; 68 | AXError result = AXUIElementCopyAttributeValue(self.elementRef, (__bridge CFStringRef)key, &attributeRef); 69 | if((result != kAXErrorSuccess) && error) { 70 | *error = [NSError errorWithDomain:NSStringFromClass(self.class) code:result userInfo:@{ 71 | @"key": key, 72 | @"elementRef": (id)self.elementRef} 73 | ]; 74 | } 75 | return attributeRef; 76 | } 77 | 78 | -(BOOL)setAttributeValue:(CFTypeRef)value forKey:(NSString *)key error:(NSError **)error { 79 | NSParameterAssert(value != nil); 80 | NSParameterAssert(key != nil); 81 | AXError result = AXUIElementSetAttributeValue(self.elementRef, (__bridge CFStringRef)key, value); 82 | if((result != kAXErrorSuccess) && error) { 83 | *error = [NSError errorWithDomain:NSStringFromClass(self.class) code:result userInfo:@{ 84 | @"key": key, 85 | @"elementRef": (id)self.elementRef 86 | }]; 87 | } 88 | return result == kAXErrorSuccess; 89 | } 90 | 91 | -(BOOL)performAction:(NSString *)action error:(NSError **)error { 92 | NSParameterAssert(action != nil); 93 | AXError result = AXUIElementPerformAction(self.elementRef, (__bridge CFStringRef)action); 94 | if ((result != kAXErrorSuccess) && error) { 95 | *error = [NSError errorWithDomain:NSStringFromClass(self.class) code:result userInfo:@{ 96 | @"action": action, 97 | @"elementRef": (id)self.elementRef 98 | }]; 99 | } 100 | 101 | return result == kAXErrorSuccess; 102 | } 103 | 104 | 105 | -(id)elementOfClass:(Class)klass forKey:(NSString *)key error:(NSError **)error { 106 | AXUIElementRef subelementRef = (AXUIElementRef)[self copyAttributeValueForKey:key error:error]; 107 | id result = nil; 108 | if (subelementRef) { 109 | result = [klass elementWithElementRef:subelementRef]; 110 | CFRelease(subelementRef); 111 | subelementRef = NULL; 112 | } 113 | return result; 114 | } 115 | 116 | 117 | -(void)addAXObserver { 118 | if (self.observer) { return; } 119 | 120 | AXObserverRef observer; 121 | AXError err; 122 | pid_t pid; 123 | 124 | err = AXUIElementGetPid(self.elementRef, &pid); 125 | if (err != kAXErrorSuccess) { return; } 126 | 127 | err = AXObserverCreate(pid, axCallback, &observer); 128 | if (err != kAXErrorSuccess) { return; } 129 | 130 | err = AXObserverAddNotification(observer, self.elementRef, kAXUIElementDestroyedNotification, (__bridge void *)(self)); 131 | if (err != kAXErrorSuccess) { 132 | CFRelease(observer); 133 | observer = NULL; 134 | return; 135 | } 136 | 137 | CFRunLoopAddSource([[NSRunLoop mainRunLoop] getCFRunLoop], AXObserverGetRunLoopSource(observer), kCFRunLoopDefaultMode); 138 | 139 | self.observer = observer; 140 | CFRelease(observer); 141 | } 142 | 143 | static void axCallback(AXObserverRef observer, AXUIElementRef element, CFStringRef notification, void *refcon) { 144 | [(__bridge HAXElement *)refcon didObserveNotification:(__bridge NSString *)notification]; 145 | } 146 | 147 | -(void)didObserveNotification:(NSString *)notification { 148 | id delegate = self.delegate; 149 | 150 | if ([notification isEqualToString:(__bridge NSString *)kAXUIElementDestroyedNotification] && [delegate respondsToSelector:@selector(elementWasDestroyed:)]) { 151 | [delegate elementWasDestroyed:self]; 152 | } 153 | } 154 | 155 | -(void)removeAXObserver { 156 | if (!self.observer) { return; } 157 | 158 | (void)AXObserverRemoveNotification(self.observer, self.elementRef, kAXUIElementDestroyedNotification); 159 | 160 | CFRunLoopSourceRef observerRunLoopSource = AXObserverGetRunLoopSource(self.observer); 161 | if (observerRunLoopSource) { 162 | CFRunLoopRemoveSource([[NSRunLoop mainRunLoop] getCFRunLoop], observerRunLoopSource, kCFRunLoopDefaultMode); 163 | } 164 | 165 | self.observer = NULL; 166 | } 167 | 168 | -(BOOL)hasChildren { 169 | return (self.children.count > 0); 170 | } 171 | 172 | -(NSArray *)children { 173 | NSArray * axUIElements = nil; 174 | NSMutableArray * result = nil; 175 | 176 | axUIElements = [self getAttributeValueForKey:(__bridge NSString *)kAXChildrenAttribute error:NULL]; 177 | if (axUIElements != nil) { 178 | result = [NSMutableArray arrayWithCapacity:[axUIElements count]]; 179 | for (id elementI in axUIElements) { 180 | [result addObject:[HAXElement elementWithElementRef:(AXUIElementRef)(elementI)]]; 181 | } 182 | } 183 | 184 | return result; 185 | } 186 | 187 | -(NSString *)role { 188 | NSString * result = [self getAttributeValueForKey:(__bridge NSString *)kAXRoleAttribute error:NULL]; 189 | if ([result isKindOfClass:[NSString class]] == NO) { 190 | result = nil; 191 | } 192 | return result; 193 | } 194 | 195 | -(NSArray *) buttons { 196 | NSArray *axChildren = self.children; 197 | NSMutableArray *result = [NSMutableArray array]; 198 | 199 | NSString * axRole; 200 | for (HAXElement *haxElementI in axChildren) { 201 | axRole = CFBridgingRelease([haxElementI copyAttributeValueForKey:(__bridge NSString *)kAXRoleAttribute error:NULL]); 202 | if (axRole == nil) { 203 | result = nil; 204 | break; 205 | } 206 | if ([axRole isEqualToString:(__bridge NSString *)kAXButtonRole]) { 207 | HAXButton *button = [HAXButton elementWithElementRef:(AXUIElementRef)haxElementI.elementRef]; 208 | [result addObject:button]; 209 | } 210 | } 211 | 212 | return result; 213 | } 214 | 215 | -(NSString *)title { 216 | NSString * result = [self getAttributeValueForKey:NSAccessibilityTitleAttribute error:NULL]; 217 | if ([result isKindOfClass:[NSString class]] == NO) { 218 | result = nil; 219 | } 220 | return result; 221 | } 222 | 223 | -(NSArray *)attributeNames { 224 | CFArrayRef attrNamesRef = NULL; 225 | AXUIElementCopyAttributeNames(_elementRef, &attrNamesRef); 226 | return attrNamesRef ? CFBridgingRelease(attrNamesRef) : nil; 227 | } 228 | 229 | @end 230 | -------------------------------------------------------------------------------- /Classes/HAXSystem.h: -------------------------------------------------------------------------------- 1 | // HAXSystem.h 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import 6 | 7 | @class HAXApplication; 8 | 9 | @interface HAXSystem : HAXElement 10 | 11 | +(instancetype)system; 12 | 13 | @property (nonatomic, readonly) HAXApplication *focusedApplication; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/HAXSystem.m: -------------------------------------------------------------------------------- 1 | // HAXSystem.m 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import "HAXApplication.h" 6 | #import "HAXSystem.h" 7 | #import "HAXElement+Protected.h" 8 | 9 | @implementation HAXSystem 10 | 11 | +(instancetype)system { 12 | AXUIElementRef element = AXUIElementCreateSystemWide(); 13 | HAXSystem *result = [self elementWithElementRef:element]; 14 | CFRelease(element); 15 | return result; 16 | } 17 | 18 | 19 | -(HAXApplication *)focusedApplication { 20 | return [self elementOfClass:[HAXApplication class] forKey:(NSString *)kAXFocusedApplicationAttribute error:NULL]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/HAXView.h: -------------------------------------------------------------------------------- 1 | // HAXView.h 2 | // Created by Kocsis Olivér on 2014-05-12 3 | // Copyright 2014 Joinect Technologies 4 | 5 | #import 6 | #import 7 | 8 | @interface HAXView : HAXElement 9 | 10 | @property (nonatomic, assign) CGPoint carbonOrigin; 11 | @property (nonatomic, assign, readonly) NSPoint origin; 12 | @property (nonatomic, assign) NSSize size; 13 | @property (nonatomic, assign) CGRect carbonFrame; 14 | @property (nonatomic, assign, readonly) NSRect frame; 15 | @property (nonatomic, readonly) NSString *title; 16 | @property (nonatomic, readonly) NSScreen *screen; 17 | @property (nonatomic, readonly, getter=isFullscreen) BOOL fullscreen; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Classes/HAXView.m: -------------------------------------------------------------------------------- 1 | // HAXView.m 2 | // Created by Kocsis Olivér on 2014-05-12 3 | // Copyright 2014 Joinect Technologies 4 | 5 | #import "HAXView.h" 6 | #import "HAXElement+Protected.h" 7 | #import "NSScreen+HAXPointConvert.h" 8 | 9 | @implementation HAXView 10 | 11 | -(CGPoint)carbonOrigin { 12 | CGPoint origin = {0}; 13 | AXValueRef originRef = (AXValueRef)[self copyAttributeValueForKey:(__bridge NSString *)kAXPositionAttribute error:NULL]; 14 | if(originRef) { 15 | AXValueGetValue(originRef, kAXValueCGPointType, &origin); 16 | CFRelease(originRef); 17 | originRef = NULL; 18 | } 19 | return origin; 20 | } 21 | 22 | -(void)setCarbonOrigin:(CGPoint)carbonOrigin { 23 | AXValueRef originRef = AXValueCreate(kAXValueCGPointType, &carbonOrigin); 24 | [self setAttributeValue:originRef forKey:(__bridge NSString *)kAXPositionAttribute error:NULL]; 25 | CFRelease(originRef); 26 | } 27 | 28 | -(NSPoint)origin { 29 | return [NSScreen hax_cocoaScreenFrameFromCarbonScreenFrame:self.carbonFrame].origin; 30 | } 31 | 32 | -(NSSize)size { 33 | CGSize size = {0}; 34 | AXValueRef sizeRef = (AXValueRef)[self copyAttributeValueForKey:(__bridge NSString *)kAXSizeAttribute error:NULL]; 35 | if(sizeRef) { 36 | AXValueGetValue(sizeRef, kAXValueCGSizeType, &size); 37 | CFRelease(sizeRef); 38 | sizeRef = NULL; 39 | } 40 | return size; 41 | } 42 | 43 | -(void)setSize:(NSSize)size { 44 | AXValueRef sizeRef = AXValueCreate(kAXValueCGSizeType, &size); 45 | [self setAttributeValue:sizeRef forKey:(__bridge NSString *)kAXSizeAttribute error:NULL]; 46 | CFRelease(sizeRef); 47 | } 48 | 49 | -(CGRect)carbonFrame { 50 | return (CGRect){ .origin = self.carbonOrigin, .size = self.size }; 51 | } 52 | 53 | -(void)setCarbonFrame:(CGRect)carbonFrame { 54 | self.carbonOrigin = carbonFrame.origin; 55 | self.size = carbonFrame.size; 56 | } 57 | 58 | -(NSRect)frame { 59 | return [NSScreen hax_cocoaScreenFrameFromCarbonScreenFrame:self.carbonFrame]; 60 | } 61 | 62 | -(NSString *)title { 63 | return [self getAttributeValueForKey:(__bridge NSString *)kAXTitleAttribute error:NULL]; 64 | } 65 | 66 | -(NSScreen *)screen { 67 | NSScreen *matchingScreen = nil; 68 | NSRect viewFrame = self.frame; 69 | NSUInteger bestOverlap = 0; 70 | for (NSScreen * screenI in [NSScreen screens]) { 71 | NSRect intersection = NSIntersectionRect(screenI.frame, viewFrame); 72 | NSUInteger intersectionOverlap = intersection.size.width * intersection.size.height; 73 | if(intersectionOverlap > bestOverlap) { 74 | matchingScreen = screenI; 75 | bestOverlap = intersectionOverlap; 76 | } 77 | } 78 | return matchingScreen; 79 | } 80 | 81 | -(BOOL)isFullscreen { 82 | BOOL isFullScreen = NO; 83 | NSArray * sceenArray = [NSScreen screens]; 84 | NSRect windowFrame = self.frame; 85 | 86 | for (NSScreen * screenI in sceenArray) { 87 | NSRect screenFrame; 88 | screenFrame = [screenI frame]; 89 | if(NSEqualRects(screenFrame, windowFrame)) { 90 | isFullScreen = YES; 91 | break; 92 | } 93 | } 94 | 95 | return isFullScreen; 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /Classes/HAXWindow.h: -------------------------------------------------------------------------------- 1 | // HAXWindow.h 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import 6 | #import 7 | 8 | @interface HAXWindow : HAXView 9 | 10 | @property (nonatomic, readonly) NSArray *views; 11 | 12 | -(BOOL)raise; 13 | -(BOOL)close; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/HAXWindow.m: -------------------------------------------------------------------------------- 1 | // HAXWindow.m 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import "HAXWindow.h" 6 | #import "HAXElement+Protected.h" 7 | 8 | @implementation HAXWindow 9 | 10 | -(NSArray *)views { 11 | NSArray *axChildren = self.children; 12 | NSMutableArray *result = [NSMutableArray array]; 13 | 14 | NSString * axRole; 15 | for (HAXElement * haxElementI in axChildren) { 16 | axRole = [haxElementI getAttributeValueForKey:(__bridge NSString *)kAXRoleAttribute error:NULL]; 17 | if ([axRole isEqualToString:@"AXView"]) { 18 | HAXView * haxView = [HAXView elementWithElementRef:(AXUIElementRef)haxElementI.elementRef]; 19 | [result addObject:haxView]; 20 | } 21 | } 22 | return result; 23 | } 24 | 25 | -(BOOL)raise { 26 | return [self performAction:(__bridge NSString *)kAXRaiseAction error:NULL]; 27 | } 28 | 29 | -(BOOL)close { 30 | HAXElement *element = [self elementOfClass:[HAXElement class] forKey:(__bridge NSString *)kAXCloseButtonAttribute error:NULL]; 31 | return [element performAction:(__bridge NSString *)kAXPressAction error:NULL]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/NSScreen+HAXPointConvert.h: -------------------------------------------------------------------------------- 1 | // NSScreen+HAXPointConvert.h 2 | // Created by Kocsis Olivér on 2014-05-05 3 | // Copyright 2014 Joinect Technologies 4 | 5 | #import 6 | 7 | @interface NSScreen (HAXPointConvert) 8 | 9 | - (NSRect)hax_frameCarbon; 10 | + (NSScreen*)hax_screenWithPoint:(NSPoint)p; 11 | + (NSRect)hax_cocoaScreenFrameFromCarbonScreenFrame:(CGRect)carbonPoint; 12 | + (CGPoint)hax_carbonScreenPointFromCocoaScreenPoint:(NSPoint)cocoaPoint; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Classes/NSScreen+HAXPointConvert.m: -------------------------------------------------------------------------------- 1 | // NSScreen+HAXPointConvert.m 2 | // Created by Kocsis Olivér on 2014-05-05 3 | // Copyright 2014 Joinect Technologies 4 | 5 | #import "NSScreen+HAXPointConvert.h" 6 | 7 | @implementation NSScreen (HAXPointConvert) 8 | 9 | + (NSScreen*)hax_screenWithPoint:(NSPoint)p { 10 | NSScreen *screen = nil; 11 | for (NSScreen *screenI in [NSScreen screens]) { 12 | if (NSPointInRect(p, [screenI frame])) { 13 | screen = screenI; 14 | break; 15 | } 16 | } 17 | return screen; 18 | } 19 | 20 | - (NSRect)hax_frameCarbon { 21 | NSRect originScreenFrame = ((NSScreen *)[NSScreen screens][0]).frame; 22 | 23 | NSRect carbonFrame; 24 | carbonFrame.origin= NSMakePoint([self frame].origin.x, 25 | originScreenFrame.size.height - 26 | [self frame].origin.y - 27 | [self frame].size.height );; 28 | carbonFrame.size = [self frame].size; 29 | return carbonFrame; 30 | } 31 | 32 | + (NSRect)hax_cocoaScreenFrameFromCarbonScreenFrame:(CGRect)carbonPoint { 33 | NSRect originScreenFrame = ((NSScreen *)[NSScreen screens][0]).frame; 34 | 35 | NSRect cocoaFrame; 36 | cocoaFrame.origin= NSMakePoint(carbonPoint.origin.x, 37 | originScreenFrame.size.height - 38 | carbonPoint.origin.y - 39 | carbonPoint.size.height );; 40 | cocoaFrame.size = carbonPoint.size; 41 | return cocoaFrame; 42 | } 43 | 44 | + (CGPoint)hax_carbonScreenPointFromCocoaScreenPoint:(NSPoint)cocoaPoint { 45 | NSScreen *foundScreen = nil; 46 | CGPoint thePoint; 47 | 48 | for (NSScreen *screen in [NSScreen screens]) { 49 | if (NSPointInRect(cocoaPoint, [screen frame])) { 50 | foundScreen = screen; 51 | } 52 | } 53 | 54 | if (foundScreen) { 55 | CGFloat screenHeight = [foundScreen frame].size.height; 56 | thePoint = CGPointMake(cocoaPoint.x, screenHeight - cocoaPoint.y - 1); 57 | } else { 58 | thePoint = CGPointMake(0.0, 0.0); 59 | } 60 | 61 | return thePoint; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Haxcessibility.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; 11 | 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; }; 12 | BC3B3B76175E9FD4002AD452 /* HAXElement+Protected.h in Headers */ = {isa = PBXBuildFile; fileRef = D44E051312D75B3D00541D6A /* HAXElement+Protected.h */; settings = {ATTRIBUTES = (Private, ); }; }; 13 | C3E21520194F381400C85776 /* HAXButton.h in Headers */ = {isa = PBXBuildFile; fileRef = C3E2151C194F381400C85776 /* HAXButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14 | C3E21521194F381400C85776 /* HAXButton.m in Sources */ = {isa = PBXBuildFile; fileRef = C3E2151D194F381400C85776 /* HAXButton.m */; }; 15 | C3E21526194F38BE00C85776 /* NSScreen+HAXPointConvert.h in Headers */ = {isa = PBXBuildFile; fileRef = C3E21524194F38BD00C85776 /* NSScreen+HAXPointConvert.h */; }; 16 | C3E21527194F38BE00C85776 /* NSScreen+HAXPointConvert.m in Sources */ = {isa = PBXBuildFile; fileRef = C3E21525194F38BD00C85776 /* NSScreen+HAXPointConvert.m */; }; 17 | C3E2152A194F38FB00C85776 /* HAXView.h in Headers */ = {isa = PBXBuildFile; fileRef = C3E21528194F38FB00C85776 /* HAXView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18 | C3E2152B194F38FB00C85776 /* HAXView.m in Sources */ = {isa = PBXBuildFile; fileRef = C3E21529194F38FB00C85776 /* HAXView.m */; }; 19 | D4D2103412D6957000509E57 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4D2103312D6957000509E57 /* Carbon.framework */; }; 20 | D4D2103712D6959400509E57 /* HAXElement.h in Headers */ = {isa = PBXBuildFile; fileRef = D4D2103512D6959400509E57 /* HAXElement.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | D4D2103812D6959400509E57 /* HAXElement.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D2103612D6959400509E57 /* HAXElement.m */; }; 22 | D4D2105512D698F400509E57 /* HAXSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D2105412D698F400509E57 /* HAXSystem.m */; }; 23 | D4D2105912D6991900509E57 /* HAXSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = D4D2105312D698F200509E57 /* HAXSystem.h */; settings = {ATTRIBUTES = (Public, ); }; }; 24 | D4D2106D12D69C8B00509E57 /* HAXApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D2106C12D69C8B00509E57 /* HAXApplication.m */; }; 25 | D4D2108212D6A08800509E57 /* HAXWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D2108112D6A08800509E57 /* HAXWindow.m */; }; 26 | D4D2113D12D6AAF000509E57 /* Haxcessibility.h in Headers */ = {isa = PBXBuildFile; fileRef = D4D2113C12D6AAF000509E57 /* Haxcessibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27 | D4D2113E12D6AB0400509E57 /* HAXApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = D4D2106B12D69C8900509E57 /* HAXApplication.h */; settings = {ATTRIBUTES = (Public, ); }; }; 28 | D4D2113F12D6AB0400509E57 /* HAXWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = D4D2108012D6A08600509E57 /* HAXWindow.h */; settings = {ATTRIBUTES = (Public, ); }; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 33 | 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 34 | 32DBCF5E0370ADEE00C91783 /* Haxcessibility.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Haxcessibility.pch; sourceTree = ""; }; 35 | 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 8DC2EF5B0486A6940098B216 /* Haxcessibility.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Haxcessibility.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | C3E2151C194F381400C85776 /* HAXButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HAXButton.h; sourceTree = ""; }; 38 | C3E2151D194F381400C85776 /* HAXButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HAXButton.m; sourceTree = ""; }; 39 | C3E21524194F38BD00C85776 /* NSScreen+HAXPointConvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSScreen+HAXPointConvert.h"; sourceTree = ""; }; 40 | C3E21525194F38BD00C85776 /* NSScreen+HAXPointConvert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSScreen+HAXPointConvert.m"; sourceTree = ""; }; 41 | C3E21528194F38FB00C85776 /* HAXView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HAXView.h; sourceTree = ""; }; 42 | C3E21529194F38FB00C85776 /* HAXView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HAXView.m; sourceTree = ""; }; 43 | D44E051312D75B3D00541D6A /* HAXElement+Protected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HAXElement+Protected.h"; sourceTree = ""; }; 44 | D4D2103312D6957000509E57 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; 45 | D4D2103512D6959400509E57 /* HAXElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HAXElement.h; sourceTree = ""; }; 46 | D4D2103612D6959400509E57 /* HAXElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = HAXElement.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 47 | D4D2105312D698F200509E57 /* HAXSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HAXSystem.h; sourceTree = ""; }; 48 | D4D2105412D698F400509E57 /* HAXSystem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HAXSystem.m; sourceTree = ""; }; 49 | D4D2106B12D69C8900509E57 /* HAXApplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HAXApplication.h; sourceTree = ""; }; 50 | D4D2106C12D69C8B00509E57 /* HAXApplication.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HAXApplication.m; sourceTree = ""; }; 51 | D4D2108012D6A08600509E57 /* HAXWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HAXWindow.h; sourceTree = ""; }; 52 | D4D2108112D6A08800509E57 /* HAXWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HAXWindow.m; sourceTree = ""; }; 53 | D4D2113C12D6AAF000509E57 /* Haxcessibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Haxcessibility.h; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 8DC2EF560486A6940098B216 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */, 62 | D4D2103412D6957000509E57 /* Carbon.framework in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 034768DFFF38A50411DB9C8B /* Products */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 8DC2EF5B0486A6940098B216 /* Haxcessibility.framework */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | 0867D691FE84028FC02AAC07 /* Haxcessibility */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | D4D2102E12D6947D00509E57 /* Classes */, 81 | 32C88DFF0371C24200C91783 /* Other Sources */, 82 | 089C1665FE841158C02AAC07 /* Resources */, 83 | 0867D69AFE84028FC02AAC07 /* Frameworks */, 84 | 034768DFFF38A50411DB9C8B /* Products */, 85 | ); 86 | name = Haxcessibility; 87 | sourceTree = ""; 88 | }; 89 | 0867D69AFE84028FC02AAC07 /* Frameworks */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | D4D2103312D6957000509E57 /* Carbon.framework */, 93 | 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */, 94 | ); 95 | name = Frameworks; 96 | sourceTree = ""; 97 | }; 98 | 089C1665FE841158C02AAC07 /* Resources */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 8DC2EF5A0486A6940098B216 /* Info.plist */, 102 | 089C1666FE841158C02AAC07 /* InfoPlist.strings */, 103 | ); 104 | path = Resources; 105 | sourceTree = ""; 106 | }; 107 | 32C88DFF0371C24200C91783 /* Other Sources */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | D4D2113C12D6AAF000509E57 /* Haxcessibility.h */, 111 | 32DBCF5E0370ADEE00C91783 /* Haxcessibility.pch */, 112 | ); 113 | path = "Other Sources"; 114 | sourceTree = ""; 115 | }; 116 | D4D2102E12D6947D00509E57 /* Classes */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | C3E21524194F38BD00C85776 /* NSScreen+HAXPointConvert.h */, 120 | C3E21525194F38BD00C85776 /* NSScreen+HAXPointConvert.m */, 121 | D4D2106B12D69C8900509E57 /* HAXApplication.h */, 122 | D4D2106C12D69C8B00509E57 /* HAXApplication.m */, 123 | C3E2151C194F381400C85776 /* HAXButton.h */, 124 | C3E2151D194F381400C85776 /* HAXButton.m */, 125 | D4D2103512D6959400509E57 /* HAXElement.h */, 126 | D44E051312D75B3D00541D6A /* HAXElement+Protected.h */, 127 | D4D2103612D6959400509E57 /* HAXElement.m */, 128 | D4D2105312D698F200509E57 /* HAXSystem.h */, 129 | D4D2105412D698F400509E57 /* HAXSystem.m */, 130 | C3E21528194F38FB00C85776 /* HAXView.h */, 131 | C3E21529194F38FB00C85776 /* HAXView.m */, 132 | D4D2108012D6A08600509E57 /* HAXWindow.h */, 133 | D4D2108112D6A08800509E57 /* HAXWindow.m */, 134 | ); 135 | path = Classes; 136 | sourceTree = ""; 137 | }; 138 | /* End PBXGroup section */ 139 | 140 | /* Begin PBXHeadersBuildPhase section */ 141 | 8DC2EF500486A6940098B216 /* Headers */ = { 142 | isa = PBXHeadersBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | D4D2105912D6991900509E57 /* HAXSystem.h in Headers */, 146 | C3E2152A194F38FB00C85776 /* HAXView.h in Headers */, 147 | D4D2103712D6959400509E57 /* HAXElement.h in Headers */, 148 | D4D2113E12D6AB0400509E57 /* HAXApplication.h in Headers */, 149 | C3E21520194F381400C85776 /* HAXButton.h in Headers */, 150 | D4D2113F12D6AB0400509E57 /* HAXWindow.h in Headers */, 151 | C3E21526194F38BE00C85776 /* NSScreen+HAXPointConvert.h in Headers */, 152 | D4D2113D12D6AAF000509E57 /* Haxcessibility.h in Headers */, 153 | BC3B3B76175E9FD4002AD452 /* HAXElement+Protected.h in Headers */, 154 | ); 155 | runOnlyForDeploymentPostprocessing = 0; 156 | }; 157 | /* End PBXHeadersBuildPhase section */ 158 | 159 | /* Begin PBXNativeTarget section */ 160 | 8DC2EF4F0486A6940098B216 /* Haxcessibility */ = { 161 | isa = PBXNativeTarget; 162 | buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Haxcessibility" */; 163 | buildPhases = ( 164 | 8DC2EF500486A6940098B216 /* Headers */, 165 | 8DC2EF540486A6940098B216 /* Sources */, 166 | 8DC2EF560486A6940098B216 /* Frameworks */, 167 | 8DC2EF520486A6940098B216 /* Resources */, 168 | ); 169 | buildRules = ( 170 | ); 171 | dependencies = ( 172 | ); 173 | name = Haxcessibility; 174 | productInstallPath = "$(HOME)/Library/Frameworks"; 175 | productName = Haxcessibility; 176 | productReference = 8DC2EF5B0486A6940098B216 /* Haxcessibility.framework */; 177 | productType = "com.apple.product-type.framework"; 178 | }; 179 | /* End PBXNativeTarget section */ 180 | 181 | /* Begin PBXProject section */ 182 | 0867D690FE84028FC02AAC07 /* Project object */ = { 183 | isa = PBXProject; 184 | attributes = { 185 | CLASSPREFIX = HAX; 186 | LastUpgradeCheck = 0600; 187 | ORGANIZATIONNAME = "Rob Rix"; 188 | }; 189 | buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Haxcessibility" */; 190 | compatibilityVersion = "Xcode 3.2"; 191 | developmentRegion = English; 192 | hasScannedForEncodings = 1; 193 | knownRegions = ( 194 | English, 195 | Japanese, 196 | French, 197 | German, 198 | ); 199 | mainGroup = 0867D691FE84028FC02AAC07 /* Haxcessibility */; 200 | productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; 201 | projectDirPath = ""; 202 | projectRoot = ""; 203 | targets = ( 204 | 8DC2EF4F0486A6940098B216 /* Haxcessibility */, 205 | ); 206 | }; 207 | /* End PBXProject section */ 208 | 209 | /* Begin PBXResourcesBuildPhase section */ 210 | 8DC2EF520486A6940098B216 /* Resources */ = { 211 | isa = PBXResourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */, 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | }; 218 | /* End PBXResourcesBuildPhase section */ 219 | 220 | /* Begin PBXSourcesBuildPhase section */ 221 | 8DC2EF540486A6940098B216 /* Sources */ = { 222 | isa = PBXSourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | C3E2152B194F38FB00C85776 /* HAXView.m in Sources */, 226 | D4D2103812D6959400509E57 /* HAXElement.m in Sources */, 227 | C3E21521194F381400C85776 /* HAXButton.m in Sources */, 228 | D4D2105512D698F400509E57 /* HAXSystem.m in Sources */, 229 | D4D2106D12D69C8B00509E57 /* HAXApplication.m in Sources */, 230 | D4D2108212D6A08800509E57 /* HAXWindow.m in Sources */, 231 | C3E21527194F38BE00C85776 /* NSScreen+HAXPointConvert.m in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXSourcesBuildPhase section */ 236 | 237 | /* Begin PBXVariantGroup section */ 238 | 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = { 239 | isa = PBXVariantGroup; 240 | children = ( 241 | 089C1667FE841158C02AAC07 /* English */, 242 | ); 243 | name = InfoPlist.strings; 244 | sourceTree = ""; 245 | }; 246 | /* End PBXVariantGroup section */ 247 | 248 | /* Begin XCBuildConfiguration section */ 249 | 1DEB91AE08733DA50010E9CD /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | COMBINE_HIDPI_IMAGES = YES; 253 | COPY_PHASE_STRIP = NO; 254 | DYLIB_COMPATIBILITY_VERSION = 1; 255 | DYLIB_CURRENT_VERSION = 1; 256 | FRAMEWORK_VERSION = A; 257 | GCC_DYNAMIC_NO_PIC = NO; 258 | GCC_OPTIMIZATION_LEVEL = 0; 259 | INFOPLIST_FILE = Resources/Info.plist; 260 | INSTALL_PATH = "@rpath"; 261 | PRODUCT_NAME = Haxcessibility; 262 | WRAPPER_EXTENSION = framework; 263 | }; 264 | name = Debug; 265 | }; 266 | 1DEB91AF08733DA50010E9CD /* Release */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | COMBINE_HIDPI_IMAGES = YES; 270 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 271 | DYLIB_COMPATIBILITY_VERSION = 1; 272 | DYLIB_CURRENT_VERSION = 1; 273 | FRAMEWORK_VERSION = A; 274 | INFOPLIST_FILE = Resources/Info.plist; 275 | INSTALL_PATH = "@rpath"; 276 | PRODUCT_NAME = Haxcessibility; 277 | WRAPPER_EXTENSION = framework; 278 | }; 279 | name = Release; 280 | }; 281 | 1DEB91B208733DA50010E9CD /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | CLANG_ENABLE_OBJC_ARC = YES; 285 | GCC_C_LANGUAGE_STANDARD = gnu99; 286 | GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; 287 | GCC_OPTIMIZATION_LEVEL = 0; 288 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 289 | GCC_PREFIX_HEADER = "Other Sources/Haxcessibility.pch"; 290 | GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 292 | GCC_WARN_UNUSED_VARIABLE = YES; 293 | MACOSX_DEPLOYMENT_TARGET = 10.7; 294 | ONLY_ACTIVE_ARCH = YES; 295 | SDKROOT = macosx; 296 | }; 297 | name = Debug; 298 | }; 299 | 1DEB91B308733DA50010E9CD /* Release */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | CLANG_ENABLE_OBJC_ARC = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu99; 304 | GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; 305 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 306 | GCC_PREFIX_HEADER = "Other Sources/Haxcessibility.pch"; 307 | GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; 308 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | MACOSX_DEPLOYMENT_TARGET = 10.7; 311 | SDKROOT = macosx; 312 | }; 313 | name = Release; 314 | }; 315 | /* End XCBuildConfiguration section */ 316 | 317 | /* Begin XCConfigurationList section */ 318 | 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Haxcessibility" */ = { 319 | isa = XCConfigurationList; 320 | buildConfigurations = ( 321 | 1DEB91AE08733DA50010E9CD /* Debug */, 322 | 1DEB91AF08733DA50010E9CD /* Release */, 323 | ); 324 | defaultConfigurationIsVisible = 0; 325 | defaultConfigurationName = Release; 326 | }; 327 | 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Haxcessibility" */ = { 328 | isa = XCConfigurationList; 329 | buildConfigurations = ( 330 | 1DEB91B208733DA50010E9CD /* Debug */, 331 | 1DEB91B308733DA50010E9CD /* Release */, 332 | ); 333 | defaultConfigurationIsVisible = 0; 334 | defaultConfigurationName = Release; 335 | }; 336 | /* End XCConfigurationList section */ 337 | }; 338 | rootObject = 0867D690FE84028FC02AAC07 /* Project object */; 339 | } 340 | -------------------------------------------------------------------------------- /Haxcessibility.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2013, Rob Rix 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | Neither the name of Monochrome Industries nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Other Sources/Haxcessibility.h: -------------------------------------------------------------------------------- 1 | // Haxcessibility.h 2 | // Created by Rob Rix on 2011-01-06 3 | // Copyright 2011 Rob Rix 4 | 5 | #import 6 | #import 7 | #import 8 | #import 9 | #import 10 | #import 11 | -------------------------------------------------------------------------------- /Other Sources/Haxcessibility.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | -------------------------------------------------------------------------------- /README.mdown: -------------------------------------------------------------------------------- 1 | # Haxcessibility 2 | 3 | Haxcessibility is, above all, a horrible pun on Mac OS X’s Accessibility framework and its AX prefix. I am shameless. 4 | 5 | Second to that, Haxcessibility is a use case–driven remote control for Mac apps by Mac apps. It enables hacks like moving and resizing another app’s windows, and there’s loads more that the AX APIs make possible that Haxcessibility could make convenient with a method or two. 6 | 7 | 8 | # Use it 9 | 10 | Resize the focused app’s focused window to fullscreen on a 27" iMac: 11 | 12 | [HAXSystem system].focusedApplication.focusedWindow.size = NSMakeRect(0, 0, 2560, 1440); 13 | 14 | Close all windows in the focused app: 15 | 16 | [[HAXSystem system].focusedApplication.windows makeObjectsPerformSelector:@selector(close)]; 17 | 18 | # Improve it 19 | 20 | Don’t see the feature you want? Fortunately, it’s pretty easy to add your own convenience methods. [Fork Haxcessibility](https://github.com/robrix/Haxcessibility/fork) and send me a pull request with your code. 21 | 22 | You’ll want to pay special attention to the HAXElement+Protected.h private header. `HAXElement` is the root of most functionality in Haxcessibility, and this header declares the conveniences defined for wrapping more of the Accessibility APIs’ functionality. 23 | 24 | # Thanks to 25 | 26 | This framework would not be what it is without the help of: 27 | 28 | - [Decimus Software](http://decimus.net) for DTerm, which showed us what you can do with the Accessibility APIs 29 | 30 | - [DEVONtechnologies, LLC](http://devontechnologies.com/) for their patronage of [Grid](https://github.com/robrix/Grid), the original _raison d’être_ of this framework 31 | 32 | - [Scott Perry](https://github.com/numist) for his industrious work on Haxcessibility, which modernized it and increased its functionality greatly; and also for his project [Switch](https://github.com/numist/Switch), a window-based context switcher that motivated a lot of this effort -------------------------------------------------------------------------------- /Resources/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.antitypical.${PRODUCT_NAME:rfc1034Identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 2 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /TODO.mdown: -------------------------------------------------------------------------------- 1 | # To-do 2 | 3 | - HAXWindow 4 | - window elements should subclass a general widget class of some description 5 | - animate size/position/frame changes? 6 | - Maybe something like the NSWindow -setFrame:animate: method for that. 7 | 8 | - Overall 9 | - wrap AXAPIEnabled/AXIsProcessTrusted 10 | - handle AX trust authorization 11 | - getting auth 12 | - setting the trust bit or whatever 13 | - relaunching the app at the client’s request (so they can in turn ask the user, if they deem it necessary) 14 | --------------------------------------------------------------------------------