X-Git-Url: https://git.saurik.com/veency.git/blobdiff_plain/778b122c8efdb5cb561e7319a5877940dc5f79b7..1c6eb1765c7dac2819bfe7fe48ef619edbc1b792:/Tweak.mm diff --git a/Tweak.mm b/Tweak.mm index 28ff1b2..1b99b5b 100644 --- a/Tweak.mm +++ b/Tweak.mm @@ -26,33 +26,138 @@ #define _unlikely(expr) \ __builtin_expect(expr, 0) -#include +#include #include #include -#include +#include +#include + #include #include -#import -#import +#undef assert +#include #import #import #import -#import -#import #import -#import -#import -#import +#include +#include +extern "C" { #include "SpringBoardAccess.h" +} + +MSClassHook(BKAccessibility) +MSClassHook(UIApplication) + +@interface UIApplication (Apple) +- (void) addStatusBarImageNamed:(NSString *)name; +- (void) removeStatusBarImageNamed:(NSString *)name; +@end + +@interface CAWindowServerDisplay : NSObject +- (mach_port_t) clientPortAtPosition:(CGPoint)position; +- (unsigned) contextIdAtPosition:(CGPoint)position; +- (mach_port_t) taskPortOfContextId:(unsigned)context; +@end + +@interface CAWindowServer : NSObject ++ (CAWindowServer *) serverIfRunning; +- (NSArray *) displays; +@end + +@interface UIModalView : UIView +- (id) addButtonWithTitle:(NSString *)title; +- (void) setBodyText:(NSString *)text; +- (void) setDelegate:(id)delegate; +- (void) setTitle:(NSString *)title; +@end + +@interface SBAlertItem : NSObject +- (void) dismiss; +- (UIModalView *) alertSheet; +@end + +@interface SBAlertItemsController : NSObject ++ (SBAlertItemsController *) sharedInstance; +- (void) activateAlertItem:(SBAlertItem *)item; +@end + +@interface SBStatusBarController : NSObject ++ (SBStatusBarController *) sharedStatusBarController; +- (void) addStatusBarItem:(NSString *)item; +- (void) removeStatusBarItem:(NSString *)item; +@end + +@interface BKHIDClientConnectionManager : NSObject +- () clientForTaskPort:(mach_port_t)port; +@end + +@interface BKAccessibility : NSObject ++ (BKHIDClientConnectionManager *) _eventRoutingClientConnectionManager; +@end + +typedef void *CoreSurfaceBufferRef; + +extern CFStringRef kCoreSurfaceBufferGlobal; +extern CFStringRef kCoreSurfaceBufferMemoryRegion; +extern CFStringRef kCoreSurfaceBufferPitch; +extern CFStringRef kCoreSurfaceBufferWidth; +extern CFStringRef kCoreSurfaceBufferHeight; +extern CFStringRef kCoreSurfaceBufferPixelFormat; +extern CFStringRef kCoreSurfaceBufferAllocSize; + +extern "C" CoreSurfaceBufferRef CoreSurfaceBufferCreate(CFDictionaryRef dict); +extern "C" int CoreSurfaceBufferLock(CoreSurfaceBufferRef surface, unsigned int lockType); +extern "C" int CoreSurfaceBufferUnlock(CoreSurfaceBufferRef surface); +extern "C" void *CoreSurfaceBufferGetBaseAddress(CoreSurfaceBufferRef surface); extern "C" void CoreSurfaceBufferFlushProcessorCaches(CoreSurfaceBufferRef buffer); +typedef void *CoreSurfaceAcceleratorRef; + +extern "C" int CoreSurfaceAcceleratorCreate(CFAllocatorRef allocator, void *type, CoreSurfaceAcceleratorRef *accel); +extern "C" unsigned int CoreSurfaceAcceleratorTransferSurface(CoreSurfaceAcceleratorRef accelerator, CoreSurfaceBufferRef dest, CoreSurfaceBufferRef src, CFDictionaryRef options/*, void *, void *, void **/); + +typedef void *IOMobileFramebufferRef; + +extern "C" kern_return_t IOMobileFramebufferSwapSetLayer( + IOMobileFramebufferRef fb, + int layer, + CoreSurfaceBufferRef buffer, + CGRect bounds, + CGRect frame, + int flags +); + +extern "C" void IOMobileFramebufferGetDisplaySize(IOMobileFramebufferRef connect, CGSize *size); +extern "C" void IOMobileFramebufferIsMainDisplay(IOMobileFramebufferRef connect, int *main); + +typedef CFTypeRef IOHIDEventRef; +typedef CFTypeRef IOHIDEventSystemClientRef; +typedef CFTypeRef IOHIDEventSystemConnectionRef; + +extern "C" { + IOHIDEventRef IOHIDEventCreateKeyboardEvent(CFAllocatorRef allocator, uint64_t time, uint16_t page, uint16_t usage, Boolean down, IOHIDEventOptionBits flags); + + IOHIDEventRef IOHIDEventCreateDigitizerEvent(CFAllocatorRef allocator, uint64_t timeStamp, IOHIDDigitizerTransducerType type, uint32_t index, uint32_t identity, uint32_t eventMask, uint32_t buttonMask, IOHIDFloat x, IOHIDFloat y, IOHIDFloat z, IOHIDFloat tipPressure, IOHIDFloat barrelPressure, Boolean range, Boolean touch, IOOptionBits options); + IOHIDEventRef IOHIDEventCreateDigitizerFingerEvent(CFAllocatorRef allocator, uint64_t timeStamp, uint32_t index, uint32_t identity, uint32_t eventMask, IOHIDFloat x, IOHIDFloat y, IOHIDFloat z, IOHIDFloat tipPressure, IOHIDFloat twist, Boolean range, Boolean touch, IOOptionBits options); + + IOHIDEventSystemClientRef IOHIDEventSystemClientCreate(CFAllocatorRef allocator); + + void IOHIDEventAppendEvent(IOHIDEventRef parent, IOHIDEventRef child); + void IOHIDEventSetIntegerValue(IOHIDEventRef event, IOHIDEventField field, int value); + void IOHIDEventSetSenderID(IOHIDEventRef event, uint64_t sender); + + void IOHIDEventSystemClientDispatchEvent(IOHIDEventSystemClientRef client, IOHIDEventRef event); + void IOHIDEventSystemConnectionDispatchEvent(IOHIDEventSystemConnectionRef connection, IOHIDEventRef event); +} + static size_t width_; static size_t height_; static NSUInteger ratio_ = 0; @@ -136,7 +241,9 @@ MSClassHook(SBAlertItem) MSClassHook(SBAlertItemsController) MSClassHook(SBStatusBarController) -@class VNCAlertItem; +@interface VNCAlertItem : SBAlertItem +@end + static Class $VNCAlertItem; static NSString *DialogTitle(@"Remote Access Request"); @@ -153,6 +260,8 @@ static rfbClientPtr client_; static void VNCSetup(); static void VNCEnabled(); +float (*$GSMainScreenScaleFactor)(); + static void OnUserNotification(CFUserNotificationRef notification, CFOptionFlags flags) { [condition_ lock]; @@ -216,18 +325,17 @@ static void OnUserNotification(CFUserNotificationRef notification, CFOptionFlags SBA_removeStatusBarImage(const_cast("Veency")); else if ($SBStatusBarController != nil) [[$SBStatusBarController sharedStatusBarController] removeStatusBarItem:@"Veency"]; - else if (UIApplication *app = [UIApplication sharedApplication]) + else if (UIApplication *app = [$UIApplication sharedApplication]) [app removeStatusBarImageNamed:@"Veency"]; } + (void) registerClient { // XXX: this could find a better home if (ratio_ == 0) { - UIScreen *screen([UIScreen mainScreen]); - if ([screen respondsToSelector:@selector(scale)]) - ratio_ = [screen scale]; + if ($GSMainScreenScaleFactor == NULL) + ratio_ = 1.0f; else - ratio_ = 1; + ratio_ = $GSMainScreenScaleFactor(); } ++clients_; @@ -237,7 +345,7 @@ static void OnUserNotification(CFUserNotificationRef notification, CFOptionFlags SBA_addStatusBarImage(const_cast("Veency")); else if ($SBStatusBarController != nil) [[$SBStatusBarController sharedStatusBarController] addStatusBarItem:@"Veency"]; - else if (UIApplication *app = [UIApplication sharedApplication]) + else if (UIApplication *app = [$UIApplication sharedApplication]) [app addStatusBarImageNamed:@"Veency"]; } @@ -356,6 +464,9 @@ struct VeencyEvent { } data; }; +static void VNCPointerOld(int buttons, int x, int y, CGPoint location, int diff, bool twas, bool tis); +static void VNCPointerNew(int buttons, int x, int y, CGPoint location, int diff, bool twas, bool tis); + static void VNCPointer(int buttons, int x, int y, rfbClientPtr client) { if (ratio_ == 0) return; @@ -389,6 +500,13 @@ static void VNCPointer(int buttons, int x, int y, rfbClientPtr client) { return; } + if (kCFCoreFoundationVersionNumber >= 800) + return VNCPointerNew(buttons, x, y, location, diff, twas, tis); + else + return VNCPointerOld(buttons, x, y, location, diff, twas, tis); +} + +static void VNCPointerOld(int buttons, int x, int y, CGPoint location, int diff, bool twas, bool tis) { mach_port_t purple(0); if ((diff & 0x10) != 0) { @@ -489,10 +607,169 @@ static void VNCPointer(int buttons, int x, int y, rfbClientPtr client) { mach_port_deallocate(mach_task_self(), purple); } +static void VNCSetSender(IOHIDEventRef event) { + IOHIDEventSetSenderID(event, 0xDEFACEDBEEFFECE5); +} + +static void VNCSendHIDEvent(IOHIDEventRef event) { + static IOHIDEventSystemClientRef client_(NULL); + if (client_ == NULL) + client_ = IOHIDEventSystemClientCreate(kCFAllocatorDefault); + + VNCSetSender(event); + IOHIDEventSystemClientDispatchEvent(client_, event); + CFRelease(event); +} + +static void VNCPointerNew(int buttons, int x, int y, CGPoint location, int diff, bool twas, bool tis) { + if ((diff & 0x10) != 0) + VNCSendHIDEvent(IOHIDEventCreateKeyboardEvent(kCFAllocatorDefault, mach_absolute_time(), kHIDPage_Telephony, kHIDUsage_Tfon_Flash, (buttons & 0x10) != 0, 0)); + if ((diff & 0x04) != 0) + VNCSendHIDEvent(IOHIDEventCreateKeyboardEvent(kCFAllocatorDefault, mach_absolute_time(), kHIDPage_Consumer, kHIDUsage_Csmr_Menu, (buttons & 0x04) != 0, 0)); + if ((diff & 0x02) != 0) + VNCSendHIDEvent(IOHIDEventCreateKeyboardEvent(kCFAllocatorDefault, mach_absolute_time(), kHIDPage_Consumer, kHIDUsage_Csmr_Power, (buttons & 0x02) != 0, 0)); + + uint32_t handm; + uint32_t fingerm; + + if (twas == 0 && tis == 1) { + handm = kIOHIDDigitizerEventRange | kIOHIDDigitizerEventTouch | kIOHIDDigitizerEventIdentity; + fingerm = kIOHIDDigitizerEventRange | kIOHIDDigitizerEventTouch; + } else if (twas == 1 && tis == 1) { + handm = kIOHIDDigitizerEventPosition; + fingerm = kIOHIDDigitizerEventPosition; + } else if (twas == 1 && tis == 0) { + handm = kIOHIDDigitizerEventRange | kIOHIDDigitizerEventTouch | kIOHIDDigitizerEventIdentity | kIOHIDDigitizerEventPosition; + fingerm = kIOHIDDigitizerEventRange | kIOHIDDigitizerEventTouch; + } else return; + + CAWindowServer *server([CAWindowServer serverIfRunning]); + if (server == nil) + return; + + CAWindowServerDisplay *display([[server displays] objectAtIndex:0]); + if (display == nil) + return; + + unsigned context([display contextIdAtPosition:CGPointMake(x, y)]); + mach_port_t port([display taskPortOfContextId:context]); + if (port == MACH_PORT_NULL) + return; + + IOHIDEventSystemConnectionRef connection([[$BKAccessibility _eventRoutingClientConnectionManager] clientForTaskPort:port]); + if (connection == NULL) + return; + + // XXX: I guess this isn't ambiguous, and it works + IOHIDFloat xf(x); + IOHIDFloat yf(y); + + IOHIDEventRef hand(IOHIDEventCreateDigitizerEvent(kCFAllocatorDefault, mach_absolute_time(), kIOHIDDigitizerTransducerTypeHand, 1<<22, 1, handm, 0, xf, yf, 0, 0, 0, 0, 0, 0)); + IOHIDEventSetIntegerValue(hand, kIOHIDEventFieldIsBuiltIn, true); + IOHIDEventSetIntegerValue(hand, kIOHIDEventFieldDigitizerIsDisplayIntegrated, true); + + IOHIDEventRef finger(IOHIDEventCreateDigitizerFingerEvent(kCFAllocatorDefault, mach_absolute_time(), 3, 2, fingerm, xf, yf, 0, 0, 0, tis, tis, 0)); + IOHIDEventAppendEvent(hand, finger); + CFRelease(finger); + + VNCSetSender(hand); + IOHIDEventSystemConnectionDispatchEvent(connection, hand); + CFRelease(hand); +} + GSEventRef (*$GSEventCreateKeyEvent)(int, CGPoint, CFStringRef, CFStringRef, id, UniChar, short, short); GSEventRef (*$GSCreateSyntheticKeyEvent)(UniChar, BOOL, BOOL); +static void VNCKeyboardNew(rfbBool down, rfbKeySym key, rfbClientPtr client) { + //NSLog(@"VNC d:%u k:%04x", down, key); + + uint16_t usage; + + switch (key) { + case XK_exclam: case XK_1: usage = kHIDUsage_Keyboard1; break; + case XK_at: case XK_2: usage = kHIDUsage_Keyboard2; break; + case XK_numbersign: case XK_3: usage = kHIDUsage_Keyboard3; break; + case XK_dollar: case XK_4: usage = kHIDUsage_Keyboard4; break; + case XK_percent: case XK_5: usage = kHIDUsage_Keyboard5; break; + case XK_asciicircum: case XK_6: usage = kHIDUsage_Keyboard6; break; + case XK_ampersand: case XK_7: usage = kHIDUsage_Keyboard7; break; + case XK_asterisk: case XK_8: usage = kHIDUsage_Keyboard8; break; + case XK_parenleft: case XK_9: usage = kHIDUsage_Keyboard9; break; + case XK_parenright: case XK_0: usage = kHIDUsage_Keyboard0; break; + + case XK_A: case XK_a: usage = kHIDUsage_KeyboardA; break; + case XK_B: case XK_b: usage = kHIDUsage_KeyboardB; break; + case XK_C: case XK_c: usage = kHIDUsage_KeyboardC; break; + case XK_D: case XK_d: usage = kHIDUsage_KeyboardD; break; + case XK_E: case XK_e: usage = kHIDUsage_KeyboardE; break; + case XK_F: case XK_f: usage = kHIDUsage_KeyboardF; break; + case XK_G: case XK_g: usage = kHIDUsage_KeyboardG; break; + case XK_H: case XK_h: usage = kHIDUsage_KeyboardH; break; + case XK_I: case XK_i: usage = kHIDUsage_KeyboardI; break; + case XK_J: case XK_j: usage = kHIDUsage_KeyboardJ; break; + case XK_K: case XK_k: usage = kHIDUsage_KeyboardK; break; + case XK_L: case XK_l: usage = kHIDUsage_KeyboardL; break; + case XK_M: case XK_m: usage = kHIDUsage_KeyboardM; break; + case XK_N: case XK_n: usage = kHIDUsage_KeyboardN; break; + case XK_O: case XK_o: usage = kHIDUsage_KeyboardO; break; + case XK_P: case XK_p: usage = kHIDUsage_KeyboardP; break; + case XK_Q: case XK_q: usage = kHIDUsage_KeyboardQ; break; + case XK_R: case XK_r: usage = kHIDUsage_KeyboardR; break; + case XK_S: case XK_s: usage = kHIDUsage_KeyboardS; break; + case XK_T: case XK_t: usage = kHIDUsage_KeyboardT; break; + case XK_U: case XK_u: usage = kHIDUsage_KeyboardU; break; + case XK_V: case XK_v: usage = kHIDUsage_KeyboardV; break; + case XK_W: case XK_w: usage = kHIDUsage_KeyboardW; break; + case XK_X: case XK_x: usage = kHIDUsage_KeyboardX; break; + case XK_Y: case XK_y: usage = kHIDUsage_KeyboardY; break; + case XK_Z: case XK_z: usage = kHIDUsage_KeyboardZ; break; + + case XK_underscore: case XK_minus: usage = kHIDUsage_KeyboardHyphen; break; + case XK_plus: case XK_equal: usage = kHIDUsage_KeyboardEqualSign; break; + case XK_braceleft: case XK_bracketleft: usage = kHIDUsage_KeyboardOpenBracket; break; + case XK_braceright: case XK_bracketright: usage = kHIDUsage_KeyboardCloseBracket; break; + case XK_bar: case XK_backslash: usage = kHIDUsage_KeyboardBackslash; break; + case XK_colon: case XK_semicolon: usage = kHIDUsage_KeyboardSemicolon; break; + case XK_quotedbl: case XK_apostrophe: usage = kHIDUsage_KeyboardQuote; break; + case XK_asciitilde: case XK_grave: usage = kHIDUsage_KeyboardGraveAccentAndTilde; break; + case XK_less: case XK_comma: usage = kHIDUsage_KeyboardComma; break; + case XK_greater: case XK_period: usage = kHIDUsage_KeyboardPeriod; break; + case XK_question: case XK_slash: usage = kHIDUsage_KeyboardSlash; break; + + case XK_Return: usage = kHIDUsage_KeyboardReturnOrEnter; break; + case XK_BackSpace: usage = kHIDUsage_KeyboardDeleteOrBackspace; break; + case XK_Tab: usage = kHIDUsage_KeyboardTab; break; + case XK_space: usage = kHIDUsage_KeyboardSpacebar; break; + + case XK_Shift_L: usage = kHIDUsage_KeyboardLeftShift; break; + case XK_Shift_R: usage = kHIDUsage_KeyboardRightShift; break; + case XK_Control_L: usage = kHIDUsage_KeyboardLeftControl; break; + case XK_Control_R: usage = kHIDUsage_KeyboardRightControl; break; + case XK_Meta_L: usage = kHIDUsage_KeyboardLeftAlt; break; + case XK_Meta_R: usage = kHIDUsage_KeyboardRightAlt; break; + case XK_Alt_L: usage = kHIDUsage_KeyboardLeftGUI; break; + case XK_Alt_R: usage = kHIDUsage_KeyboardRightGUI; break; + + case XK_Up: usage = kHIDUsage_KeyboardUpArrow; break; + case XK_Down: usage = kHIDUsage_KeyboardDownArrow; break; + case XK_Left: usage = kHIDUsage_KeyboardLeftArrow; break; + case XK_Right: usage = kHIDUsage_KeyboardRightArrow; break; + + case XK_Home: case XK_Begin: usage = kHIDUsage_KeyboardHome; break; + case XK_End: usage = kHIDUsage_KeyboardEnd; break; + case XK_Page_Up: usage = kHIDUsage_KeyboardPageUp; break; + case XK_Page_Down: usage = kHIDUsage_KeyboardPageDown; break; + + default: return; + } + + VNCSendHIDEvent(IOHIDEventCreateKeyboardEvent(kCFAllocatorDefault, mach_absolute_time(), kHIDPage_KeyboardOrKeypad, usage, down, 0)); +} + static void VNCKeyboard(rfbBool down, rfbKeySym key, rfbClientPtr client) { + if (kCFCoreFoundationVersionNumber >= 800) + return VNCKeyboardNew(down, key, client); + if (!down) return; @@ -587,6 +864,7 @@ extern "C" bool GSSystemHasCapability(NSString *); static CFTypeRef (*$GSSystemCopyCapability)(CFStringRef); static CFTypeRef (*$GSSystemGetCapability)(CFStringRef); +static BOOL (*$MGGetBoolAnswer)(CFStringRef); static void VNCSetup() { rfbLogEnable(false); @@ -613,6 +891,7 @@ static void VNCSetup() { $GSSystemCopyCapability = reinterpret_cast(dlsym(RTLD_DEFAULT, "GSSystemCopyCapability")); $GSSystemGetCapability = reinterpret_cast(dlsym(RTLD_DEFAULT, "GSSystemGetCapability")); + $MGGetBoolAnswer = reinterpret_cast(dlsym(RTLD_DEFAULT, "MGGetBoolAnswer")); CFTypeRef opengles2; @@ -622,6 +901,9 @@ static void VNCSetup() { opengles2 = (*$GSSystemGetCapability)(CFSTR("opengles-2")); if (opengles2 != NULL) CFRetain(opengles2); + } else if ($MGGetBoolAnswer != NULL) { + opengles2 = $MGGetBoolAnswer(CFSTR("opengles-2")) ? kCFBooleanTrue : kCFBooleanFalse; + CFRetain(opengles2); } else opengles2 = NULL; @@ -662,6 +944,9 @@ static void VNCSetup() { } static void VNCEnabled() { + if (screen_ == NULL) + return; + [lock_ lock]; bool enabled(true); @@ -828,6 +1113,7 @@ MSInitialize { sysctlbyname("hw.machine", machine, &size, NULL, 0); iPad1_ = strcmp(machine, "iPad1,1") == 0; + dlset($GSMainScreenScaleFactor, "GSMainScreenScaleFactor"); dlset($GSEventCreateKeyEvent, "GSEventCreateKeyEvent"); dlset($GSCreateSyntheticKeyEvent, "_GSCreateSyntheticKeyEvent"); dlset($IOMobileFramebufferIsMainDisplay, "IOMobileFramebufferIsMainDisplay");