-
Notifications
You must be signed in to change notification settings - Fork 28
Private Goodies
In researching random things for Parrot, here are some frameworks of note:
- AnnotationKit
- Assistant+Services
- Calendar*
- CharacterPicker
- Contacts*
- CoreDuet
- CoreEmoji
- CoreNameParser
- CoreUI*/CoreThemeDefinition
- CoreTelephony
- ContactsUI/AddressBookUI
- DataDetectors*
- DuetActivityScheduler
- EmojiFoundation
- FlightUtilities
- IMCore
- IMFoundation
- IMSharedUI
- Intents/Core
- InternetAccounts
- Lookup
- MarkupUI
- MessagesKit
- OAuth
- PersonaKit/UI
- PhoneNumbers
- PlugInKit
- ProKit
- SafariSafeBrowsing
- ShareKit/Sharing
- SpotlightIndex/Daemon
- ToneKit/Library
- ViewBridge
WebKit actually exposes some of the private API as SPI headers:
- WebCore Mac SPI
- WebCore iOS SPI
- WebCore CoreFoundation SPI
- WebCore CoreGraphics SPI
- WebCore Cocoa SPI
- WTF Darwin SPI
- WTF Cocoa SPI
- WTF CoreFoundation SPI
- *** custom data --> de/coder --> transports --> endpoint
- custom data: string, number, array, dict, etc.
- de/coders: pblite, protobuf, plist, xml, json, xpc, msgpack, etc
- transports: file, port, mach, xpc, tcp, udp, http/s, etc
- endpoints: com.example.mach_service, google.com/v1/chat/some_function, etc
- XPCService (via NSProxy?)
- RemoteViews (via CARemoteLayer or IOSurface?)
- Extensions
- OAuth
- Calender
- Contacts
- ToneLibrary
- CoreSuggestions
- DataDetectors
- ActivityScheduling
- PhysicsKit
- PluginKit
- ProKit as NSAppearance
- IDS + IDSFoundation?
- IMFoundation+SharedUI+etc.
- Persona/UI
- SMLoginItem
- SMJobSubmit/SMJobBless
- SFAuthorization/SFAuthorizationView
- Keychain/UserDefaults
- MediaLibrary/FilePicker
- SecHostSetHostingPort et al
- NSPopoverColorWell
- NSPopoverToolbar
- NSPreferences+Module
- NSVibrantSplitDividerView
- NSTexturedComboBox
- NSSystemInfoPanel
- NSSecureTextView
- NS*GestureRecognizer
- NSLabelView
- NSKeyboardShortcut
- NSSpellChecker: showCorrectionBubbleOfType
- NSVisualEffectView: _currentSaturationMultiplier + _currentBlurRadius
- _NSWindowAnimator
- NSDrawerWindow
- NSWindowScaleAnimation
- NSCGSWindowBackdrop
- NSTitlebarFloatingWindow
- NSWindowFullScreenController
- _NSWindowTransformAnimation
- NSWindowController
- NSWindow
- NSStatusBarWindow
- NSWindowAuxiliary
- NSDocumentRevisionsWindowTransformAnimation
- NSDocumentRevisionsWindowTransformAnimationGroup
- NSFullScreenAnimation
Here's the anatomy of the NSWindow
titlebar views in some kind of pseudo-visual-code. It can be replicated pretty easily using NSTitlebarAccessoryViewController
.
[self.file ? self.file.icon : nil] [self.title] [self.edited ? " - Edited" : ""] [self.editable ? ▽_button : nil]
button.press = popover(V:[Name][Tags][Where+Locked])
Here's how Notification Center captures the left edge swipe. And yes, I've tried it -- it works.
void -[NCNotificationCenterWindowAnimator _setupDockGestureEvents](void * self, void * _cmd) {
rbx = self;
if (rbx->_dockEventTapPort == 0x0) {
r12 = *objc_ivar_offset_NCNotificationCenterWindowAnimator__dockEventTapPort;
rax = CGEventTapCreate(0x2, 0x0, 0x1, 0x40000000, sub_100057c32, rbx);
*(rbx + r12) = rax;
if (rax != 0x0) {
r14 = CFMachPortCreateRunLoopSource(*_kCFAllocatorDefault, rax, 0x0);
if (r14 != 0x0) {
r15 = CFRunLoopGetCurrent();
CFRunLoopAddSource(r15, r14, *_kCFRunLoopDefaultMode);
CFRunLoopAddSource(r15, r14, @"NSEventTrackingRunLoopMode");
CFRelease(r14);
rdi = *(rbx + r12);
CGEventTapEnable(rdi, 0x1);
}
}
}
return;
}
In case you don't like XPC activities, there's an interface to the bootstrap server.
@interface NSPortNameServer : NSObject
+ (id)defaultPortNameServer;
+ (id)systemDefaultPortNameServer;
- (id)portForName:(id)arg1 onHost:(id)arg2;
- (BOOL)registerPort:(id)arg1 forName:(id)arg2;
- (BOOL)removePortForName:(id)arg1;
- (BOOL)registerPort:(id)arg1 name:(id)arg2;
- (id)portForName:(id)arg1 host:(id)arg2;
- (id)portForName:(id)arg1;
@end
@interface NSMachBootstrapServer : NSPortNameServer
+ (id)sharedInstance;
- (BOOL)removePortForName:(id)arg1;
- (id)portForName:(id)arg1 host:(id)arg2;
- (id)servicePortWithName:(id)arg1;
- (BOOL)registerPort:(id)arg1 name:(id)arg2;
- (id)portForName:(id)arg1;
- (id)portForName:(id)arg1 options:(unsigned long long)arg2;
@end
Here's the internal interface to add a summary (the informativeText
of the notification is used) to the Notification Center. Again, it works.
@interface NSUserNotificationCenter (Summary)
- (void)set_tomorrowSummaryNotifications:(NSArray <NSUserNotification *>*)notifications;
- (NSArray <NSUserNotification *>*)_tomorrowSummaryNotifications;
- (void)set_todaySummaryNotifications:(NSArray <NSUserNotification *>*)notifications;
- (NSArray <NSUserNotification *>*)_todaySummaryNotifications;
@end
Here are some of the transition animators used by Storyboard Segues:
@interface NSViewControllerPresentationAnimatorObject : NSObject <NSViewControllerPresentationAnimator>
@property(copy) CDUnknownBlockType completionHandler;
@property(retain) NSViewController *toViewController;
@property(retain) NSViewController *fromViewController;
@end
@interface NSViewControllerWindowTransition : NSViewControllerPresentationAnimatorObject
@property(readonly, retain) NSWindow *window;
@end
@interface NSViewControllerModalWindowTransition : NSViewControllerWindowTransition
@end
@interface NSViewControllerUtilityWindowTransition : NSViewControllerWindowTransition
@end
@interface NSViewControllerSheetTransition : NSViewControllerPresentationAnimatorObject
@end
@interface NSViewControllerPopoverTransition : NSViewControllerPresentationAnimatorObject
- (id)initWithPositioningRect:(CGRect)arg1 ofView:(id)arg2 preferredEdge:(unsigned long long)arg3 behavior:(long long)arg4;
@end
NSWindow
's cornerMask
property is produced by the following code. In addition, NSVisualEffectView
detects if it is the contentView
of an NSWindow
and applies its maskImage
to this property.
void * -[NSWindow _cornerMaskOrNil](void * self, void * _cmd) {
rax = [self _cornerMask];
rcx = self->_auxiliaryStorage;
if (rcx != 0x0) {
rdi = rcx->_auxWFlags;
rbx = 0xfff7ffff & *(int32_t *)(rcx + *_OBJC_IVAR_$_NSWindowAuxiliary._auxWFlags + 0x8);
rcx->_auxWFlags = rdi;
*(int32_t *)(rcx + *_OBJC_IVAR_$_NSWindowAuxiliary._auxWFlags + 0x8) = ((rax != 0x0 ? 0x1 : 0x0) & 0xff) << 0x13 | rbx;
}
return rax;
}
void * -[NSWindow _cornerMask](void * self, void * _cmd) {
r14 = self;
rbx = *_OBJC_IVAR_$_NSWindow._borderView;
r15 = @selector(_cornerMask);
rdx = r15;
if ([*(r14 + rbx) respondsToSelector:rdx] != 0x0) {
rbx = _objc_msgSend(*(r14 + rbx), r15);
if (rbx == 0x0) {
rbx = 0x0;
if ([r14 _shouldGetCornerMaskFromVisualEffectView] != 0x0) {
rbx = [[r14 contentView] maskImage];
if (rbx == 0x0) {
xmm0 = intrinsic_movsd(xmm0, *0xba64a0, ^ { /* block implemented at ___23-[NSWindow _cornerMask]_block_invoke */ });
intrinsic_movapd(xmm1, xmm0);
rbx = [NSImage imageWithSize:rdx drawHandler:rcx];
xmm0 = intrinsic_movaps(xmm0, *(int128_t *)0xba67f0);
var_-64 = intrinsic_movaps(var_-64, xmm0);
intrinsic_movaps(var_-48, xmm0);
stack[2048] = var_-64;
[rbx setCapInsets:rdx, rcx];
}
}
}
}
else {
rbx = 0x0;
if ([r14 _shouldGetCornerMaskFromVisualEffectView] != 0x0) {
rbx = [[r14 contentView] maskImage];
if (rbx == 0x0) {
xmm0 = intrinsic_movsd(xmm0, *0xba64a0, ^ { /* block implemented at ___23-[NSWindow _cornerMask]_block_invoke */ });
intrinsic_movapd(xmm1, xmm0);
rbx = [NSImage imageWithSize:rdx drawHandler:rcx];
xmm0 = intrinsic_movaps(xmm0, *(int128_t *)0xba67f0);
var_-64 = intrinsic_movaps(var_-64, xmm0);
intrinsic_movaps(var_-48, xmm0);
stack[2048] = var_-64;
[rbx setCapInsets:rdx, rcx];
}
}
}
rax = rbx;
return rax;
}
void * -[NSThemeFrame _cornerMask](void * self, void * _cmd) {
rbx = self;
if (([[self window] _inFullScreen] != 0x0) && ([rbx shouldRoundCornersInFullScreen] != 0x0)) {
rdi = rbx;
rax = [rdi _fullScreenCornerMaskImage];
}
else {
if ([rbx->_window _hasBackgroundColor] != 0x0) {
rax = [rbx->_window backgroundColor];
[rax alphaComponent];
rax = 0x0;
xmm1 = intrinsic_xorpd(xmm1, xmm1);
xmm0 = intrinsic_ucomisd(xmm0, xmm1);
if ((xmm0 != 0x0) || (!CPU_FLAGS & NP)) {
rdx = var_-72;
r8 = var_-32;
rcx = [rbx _createWindowShapeMask:rdx centerRect:var_-64 scale:r8];
rax = 0x0;
if (rcx != 0x0) {
xmm0 = intrinsic_punpckldq(zero_extend_64(CGImageGetWidth(var_-72)), *(int128_t *)0xba6420);
xmm0 = intrinsic_subpd(xmm0, *(int128_t *)0xba6430);
var_-112 = intrinsic_movsd(var_-112, intrinsic_roundsd(intrinsic_divsd(intrinsic_haddpd(xmm0, xmm0), var_-32), 0xa));
xmm0 = intrinsic_punpckldq(zero_extend_64(CGImageGetHeight(var_-72)), *(int128_t *)0xba6420);
xmm0 = intrinsic_subpd(xmm0, *(int128_t *)0xba6430);
xmm0 = intrinsic_haddpd(xmm0, xmm0);
xmm0 = intrinsic_divsd(xmm0, var_-32);
xmm0 = intrinsic_roundsd(xmm0, 0xa);
var_-120 = intrinsic_movsd(var_-120, xmm0);
rax = [NSImage alloc];
xmm0 = intrinsic_movsd(xmm0, var_-112, var_-72);
xmm1 = intrinsic_movsd(xmm1, var_-120);
rbx = [rax initWithCGImage:var_-72 size:rcx, r8];
CGImageRelease(var_-72);
xmm0 = intrinsic_movsd(xmm0, var_-64);
xmm2 = intrinsic_movsd(xmm2, var_-112);
xmm0 = intrinsic_mulsd(xmm0, xmm2);
xmm1 = intrinsic_movsd(xmm1, var_-48);
xmm1 = intrinsic_mulsd(xmm1, xmm2);
xmm2 = intrinsic_subsd(xmm2, xmm1);
xmm2 = intrinsic_subsd(xmm2, xmm0);
xmm3 = intrinsic_movapd(xmm3, xmm2);
xmm1 = intrinsic_movsd(xmm1, var_-56);
xmm4 = intrinsic_movsd(xmm4, var_-120);
xmm1 = intrinsic_mulsd(xmm1, xmm4);
xmm4 = intrinsic_subsd(xmm4, intrinsic_mulsd(intrinsic_movsd(xmm2, var_-40), xmm4));
xmm4 = intrinsic_subsd(xmm4, xmm1);
var_-104 = intrinsic_movsd(var_-104, xmm1);
var_-96 = intrinsic_movsd(var_-96, xmm0);
var_-88 = intrinsic_movsd(var_-88, xmm4);
intrinsic_movsd(var_-80, xmm3);
stack[2048] = var_-104;
[rbx setCapInsets:var_-72, var_-96, r8];
[rbx setResizingMode:0x0, var_-96, r8];
rax = [rbx autorelease];
}
}
}
else {
rdx = var_-72;
r8 = var_-32;
rcx = [rbx _createWindowShapeMask:rdx centerRect:var_-64 scale:r8];
rax = 0x0;
if (rcx != 0x0) {
xmm0 = intrinsic_punpckldq(zero_extend_64(CGImageGetWidth(var_-72)), *(int128_t *)0xba6420);
xmm0 = intrinsic_subpd(xmm0, *(int128_t *)0xba6430);
var_-112 = intrinsic_movsd(var_-112, intrinsic_roundsd(intrinsic_divsd(intrinsic_haddpd(xmm0, xmm0), var_-32), 0xa));
xmm0 = intrinsic_punpckldq(zero_extend_64(CGImageGetHeight(var_-72)), *(int128_t *)0xba6420);
xmm0 = intrinsic_subpd(xmm0, *(int128_t *)0xba6430);
xmm0 = intrinsic_haddpd(xmm0, xmm0);
xmm0 = intrinsic_divsd(xmm0, var_-32);
xmm0 = intrinsic_roundsd(xmm0, 0xa);
var_-120 = intrinsic_movsd(var_-120, xmm0);
rax = [NSImage alloc];
xmm0 = intrinsic_movsd(xmm0, var_-112, var_-72);
xmm1 = intrinsic_movsd(xmm1, var_-120);
rbx = [rax initWithCGImage:var_-72 size:rcx, r8];
CGImageRelease(var_-72);
xmm0 = intrinsic_movsd(xmm0, var_-64);
xmm2 = intrinsic_movsd(xmm2, var_-112);
xmm0 = intrinsic_mulsd(xmm0, xmm2);
xmm1 = intrinsic_movsd(xmm1, var_-48);
xmm1 = intrinsic_mulsd(xmm1, xmm2);
xmm2 = intrinsic_subsd(xmm2, xmm1);
xmm2 = intrinsic_subsd(xmm2, xmm0);
xmm3 = intrinsic_movapd(xmm3, xmm2);
xmm1 = intrinsic_movsd(xmm1, var_-56);
xmm4 = intrinsic_movsd(xmm4, var_-120);
xmm1 = intrinsic_mulsd(xmm1, xmm4);
xmm4 = intrinsic_subsd(xmm4, intrinsic_mulsd(intrinsic_movsd(xmm2, var_-40), xmm4));
xmm4 = intrinsic_subsd(xmm4, xmm1);
var_-104 = intrinsic_movsd(var_-104, xmm1);
var_-96 = intrinsic_movsd(var_-96, xmm0);
var_-88 = intrinsic_movsd(var_-88, xmm4);
intrinsic_movsd(var_-80, xmm3);
stack[2048] = var_-104;
[rbx setCapInsets:var_-72, var_-96, r8];
[rbx setResizingMode:0x0, var_-96, r8];
rax = [rbx autorelease];
}
}
}
return rax;
}
void -[NSWindow _cornerMaskChanged](void * self, void * _cmd) {
r14 = [self _cornerMaskOrNil];
r15 = [self windowNumber];
[self backingScaleFactor];
rdi = r15;
rsi = r14;
__NSSetWindowCornerMask(rdi, rsi);
return;
}
char ___23-[NSWindow _cornerMask]_block_invoke(void * _block, struct CGRect arg1) {
rdi = [NSColor blackColor];
[rdi set];
_NSRectFill(rdi);
return 0x1;
}
void __NSSetWindowCornerMask(int arg0, int arg1) {
r13 = arg1;
var_78 = intrinsic_movsd(var_78, xmm0);
r14 = arg0;
if ((r14 > 0x0) && (__NSGetBoolAppConfig(@"NSUseCornerMasks", 0x1, _sNSUseCornerMasksComputedValue, __NSTrueAppConfigPredicate) != 0x0)) {
if (r13 != 0x0) {
if ([r13 resizingMode] != 0x0) {
r12 = @selector(stringWithUTF8String:);
rbx = _objc_msgSend;
rax = _objc_msgSend(@class(NSString), r12);
r15 = @"<Unknown Function>";
if (rax != 0x0) {
r15 = rax;
}
rdx = "/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1504.75/AppKit.subproj/packagesWraps.m";
rax = (rbx)(@class(NSString), r12, rdx);
r12 = rbx;
rbx = @"<Unknown File>";
if (rax != 0x0) {
rbx = rax;
}
(r12)((r12)(@class(NSAssertionHandler), @selector(currentHandler), rdx), @selector(handleFailureInFunction:file:lineNumber:description:), r15, rbx, 0xa9, @"image returned from _cornerMask must have a resizing mode of NSImageResizingModeStretch");
}
rbx = [NSAffineTransform transform];
xmm0 = intrinsic_movsd(xmm0, var_78);
[rbx scaleBy:rdx];
r15 = [r13 CGImageForProposedRect:0x0 context:0x0 hints:[NSDictionary dictionaryWithObject:rbx forKey:@"NSImageHintCTM"]];
if (r15 != 0x0) {
rdx = @selector(capInsets);
objc_msgSend_stret(var_48, r13, rdx);
rcx = *_NSEdgeInsetsZero;
rcx = var_40;
if (NSEdgeInsetsEqual() != 0x0) {
rcx = *_CGRectNull;
CGSSetWindowCornerMask(r14, 0x0, 0x0, rcx);
}
else {
[r13 size];
var_90 = intrinsic_movapd(var_90, xmm0);
[r13 size];
xmm2 = intrinsic_movsd(xmm2, var_40);
xmm0 = intrinsic_movsd(xmm0, var_30);
xmm2 = intrinsic_movhpd(xmm2, var_48);
xmm3 = intrinsic_movapd(xmm3, var_90);
xmm3 = intrinsic_unpcklpd(xmm3, xmm1);
xmm1 = intrinsic_movapd(xmm1, xmm3);
xmm1 = intrinsic_subpd(xmm1, xmm2);
var_90 = intrinsic_movapd(var_90, intrinsic_divpd(xmm2, xmm3));
xmm0 = intrinsic_movhpd(xmm0, var_38);
var_A0 = intrinsic_movapd(var_A0, intrinsic_divpd(intrinsic_subpd(xmm1, xmm0), xmm3));
rbx = [[NSCGSMutableWindowCornerMask alloc] init];
[rbx setImage:r15, rcx];
xmm0 = intrinsic_movsd(xmm0, var_78);
[rbx setImageScale:r15, rcx];
xmm0 = intrinsic_movaps(xmm0, var_90);
var_70 = intrinsic_movaps(var_70, xmm0);
intrinsic_movapd(var_60, intrinsic_movapd(xmm0, var_A0));
[rbx setCenter:r15, var_68];
rax = [NSCGSWindow windowWithWindowID:r14, var_68];
[rax setCornerMask:rbx, var_68];
[rbx release];
}
}
}
else {
rcx = *_CGRectNull;
CGSSetWindowCornerMask(r14, 0x0, 0x0, rcx);
}
}
return;
}
It turns out there are a few hidden NSGestureRecognizer
s in AppKit:
-
Accelerator
: force touch "accelerator" button-like recognition. -
ImmediateAction
: three-finger or force-touch definition lookup. -
PressureSensitivePan
: not sure? -
Pulse
: code is shown below.
void * -[NSPulseGestureRecognizer initWithTarget:action:](void * self, void * _cmd, void * arg2, void * arg3) {
rbx = [[self super] initWithTarget:arg2 action:arg3];
if (rbx != 0x0) {
rbx->_flags = rbx->_flags & 0xfffffffe;
[rbx setDelaysPrimaryMouseButtonEvents:0x1];
}
rax = rbx;
return rax;
}
void * -[NSPulseGestureRecognizer initWithCoder:](void * self, void * _cmd, void * arg2) {
r14 = arg2;
rbx = [[self super] initWithCoder:rdx];
if (rbx != 0x0) {
rbx->_flags = rbx->_flags & 0xfffffffe;
if ([r14 containsValueForKey:@"NSPulseGestureRecognizer.recognizesOnMouseDown"] != 0x0) {
rbx->_flags = rbx->_flags & 0xfffffffe | [r14 decodeBoolForKey:@"NSPulseGestureRecognizer.recognizesOnMouseDown"] & 0xff & 0x1;
}
}
rax = rbx;
return rax;
}
void -[NSPulseGestureRecognizer encodeWithCoder:](void * self, void * _cmd, void * arg2) {
[[self super] encodeWithCoder:rdx];
[arg2 encodeBool:self->_flags & 0x1 forKey:@"NSPulseGestureRecognizer.recognizesOnMouseDown"];
return;
}
void -[NSPulseGestureRecognizer setRecognizesOnMouseDown:](void * self, void * _cmd, char arg2) {
self->_flags = self->_flags & 0xfffffffe | arg2 & 0x1;
return;
}
char -[NSPulseGestureRecognizer recognizesOnMouseDown](void * self, void * _cmd) {
rax = self->_flags;
rax = rax & 0x1;
return rax;
}
struct CGPoint -[NSPulseGestureRecognizer locationInView:](void * self, void * _cmd, void * arg2) {
rax = arg2;
intrinsic_movsd(xmm0, self->_location, arg2, *_OBJC_IVAR_$_NSPulseGestureRecognizer._location);
intrinsic_movsd(xmm1, *(self + *_OBJC_IVAR_$_NSPulseGestureRecognizer._location + 0x8));
if (rax != 0x0) {
rax = [rax convertPoint:0x0 fromView:rcx];
}
return rax;
}
void -[NSPulseGestureRecognizer reset](void * self, void * _cmd) {
rdx = *_NSZeroPoint;
*(self + *_OBJC_IVAR_$_NSPulseGestureRecognizer._location + 0x8) = *_NSZeroRect;
self->_location = rdx;
self->_pressure = 0x0;
self->_stage = 0x0;
self->_stageTransition = 0x0;
return;
}
void -[NSPulseGestureRecognizer mouseDown:](void * self, void * _cmd, void * arg2) {
r14 = arg2;
rbx = self;
if ((!(BIT_TEST([r14 associatedEventsMask], 0x22))) && ((rbx->_flags & 0x1) == 0x0)) {
[rbx setState:0x5];
}
else {
if ([rbx state] == 0x0) {
[r14 locationInWindow];
rbx->_location = intrinsic_movsd(rbx->_location, xmm0);
*(rbx + *_OBJC_IVAR_$_NSPulseGestureRecognizer._location + 0x8) = intrinsic_movsd(*(rbx + *_OBJC_IVAR_$_NSPulseGestureRecognizer._location + 0x8), xmm1);
rbx->_stage = 0x1;
rbx->_pressure = 0x0;
rbx->_stageTransition = 0x0;
[rbx setState:0x1];
}
}
[[rbx super] mouseDown:r14];
return;
}
void -[NSPulseGestureRecognizer mouseDragged:](void * self, void * _cmd, void * arg2) {
[arg2 locationInWindow];
self->_location = intrinsic_movsd(self->_location, xmm0);
*(self + *_OBJC_IVAR_$_NSPulseGestureRecognizer._location + 0x8) = intrinsic_movsd(*(self + *_OBJC_IVAR_$_NSPulseGestureRecognizer._location + 0x8), xmm1);
[self setState:0x2];
[[self super] mouseDragged:arg2];
return;
}
void -[NSPulseGestureRecognizer mouseUp:](void * self, void * _cmd, void * arg2) {
r14 = arg2;
rbx = self;
rsi = @selector(setState:);
[self state] > 0x2;
_objc_msgSend(rbx, rsi);
[[rbx super] mouseUp:r14];
return;
}
void -[NSPulseGestureRecognizer rightMouseDown:](void * self, void * _cmd, void * arg2) {
[self setState:0x5];
[[self super] rightMouseDown:arg2];
return;
}
void -[NSPulseGestureRecognizer otherMouseDown:](void * self, void * _cmd, void * arg2) {
[self setState:0x5];
[[self super] otherMouseDown:arg2];
return;
}
void -[NSPulseGestureRecognizer pressureChangeWithEvent:](void * self, void * _cmd, void * arg2) {
r14 = arg2;
rbx = self;
r15 = [self state];
[r14 pressure];
xmm0 = intrinsic_cvtss2sd(xmm0, xmm0);
xmm1 = intrinsic_movsd(xmm1, *0xba6058);
xmm1 = intrinsic_minsd(xmm1, xmm0);
xmm0 = intrinsic_xorpd(xmm0, xmm0);
xmm1 = intrinsic_maxsd(xmm1, xmm0);
rbx->_pressure = intrinsic_movsd(rbx->_pressure, xmm1);
rbx->_stage = [r14 stage];
[r14 stageTransition];
rbx->_stageTransition = intrinsic_movsd(rbx->_stageTransition, intrinsic_maxsd(intrinsic_minsd(intrinsic_movsd(xmm1, *0xba6058), xmm0), *0xba6018));
if ((r15 <= 0x2) && (rbx->_stage <= 0x2)) {
[rbx setState:0x2];
}
[[rbx super] pressureChangeWithEvent:r14];
return;
}
void * -[NSPulseGestureRecognizer _desiredPressureBehavior](void * self, void * _cmd) {
rax = [[[NSPressureConfiguration alloc] initWithPressureBehavior:0x5] autorelease];
return rax;
}
In Sierra, the new Notification Center look is produced by the following code:
- (void)_buildLayerTree {
self.allowsGroupBlending = NO;
self.allowsEdgeAntialiasing = NO;
self.masksToBounds = YES;
self._backdropLayer = _createBackdropLayer(???);
self._tintLayer = [CALayer new];
self._tintLayer.name = @"tint";
self._backdropLayer.edgeAntialiasingMask = NO;
self.sublayers = @[self._backdropLayer, self._tintLayer];
}
CALayer *_createBackdropLayer(NSString *rbx) {
CABackdropLayer *r15 = [CABackdropLayer new];
r15.groupName = rbx;
r15.ignoresOffscreenGroups = YES;
r15.windowServerAware = YES;
CAFilter *r14 = [CAFilter filterWithName: kCAFilterGaussianBlur];
[r14 setValue:@(YES) forKey:@"inputNormalizeEdges"];
[r14 setValue:[NSNumber numberWithDouble: ???] forKey:@"inputRadius"];
CAFilter *r12 = [CAFilter filterWithName: kCAFilterColorSaturate];
[r12 setValue:[NSNumber numberWithDouble: ???] forKey:@"inputAmount"];
r15.filters = @[r14, r12];
r15.name = @"backdrop";
r15.scale = ???;
return r15;
}
- (void)setBlurRadius:(float)arg2 {
[self._backdropLayer setValue:@(arg2) forKeyPath:@"filters.gaussianBlur.inputRadius"];
}
- (void)setReduceTransparency:(BOOL)arg2 {
if (self._reduceTransparency != arg2) {
self._reduceTransparency = arg2;
if (arg2) {
self.sublayers = nil;
self.allowsGroupBlending = YES;
self.allowsEdgeAntialiasing = YES;
self.masksToBounds = NO;
self._backdropLayer = nil;
self._tintLayer = nil;
} else {
self.backgroundColor = nil;
[self _buildLayerTree];
[var_30 bounds]; // ???
[self setBounds:0x0, rcx]; // ???
}
self._material = (self._material == 0x0 ? 0x1 : 0x0) & 0xff;
self.material = rdx;
}
}
void -[NCMaterialLayer setMaterial:](void * self, void * _cmd, unsigned long long arg2) {
rbx = arg2;
r14 = self;
rax = *_OBJC_IVAR_$_NCMaterialLayer._material;
if (*(r14 + rax) != rbx) goto loc_bc76;
.l1:
return;
loc_bc76:
*(r14 + rax) = rbx;
if (r14->_reduceTransparency == 0x0) goto loc_bcc8;
loc_bc88:
if (rbx <= 0x6) {
intrinsic_movsd(xmm0, *(0xde20 + rbx * 0x8));
}
intrinsic_movsd(xmm1, *0xdc08);
rax = __CGColorGenericSRGBGray();
rdi = r14;
[rdi setBackgroundColor:rax];
return;
loc_bcc8:
rax = 0x0;
if (rbx > 0x6) goto loc_be09;
loc_bcd4:
goto *0xbecc[sign_extend_64(*(int32_t *)(0xbecc + rbx * 0x4)) + 0xbecc];
loc_bce4:
rax = [*_kCAFilterDarkenBlendMode retain];
xmm0 = intrinsic_movsd(xmm0, *0xdd10);
xmm1 = intrinsic_movsd(xmm1, *0xdd58);
xmm2 = intrinsic_movsd(xmm2, *0xdc08);
goto loc_be09;
loc_be09:
var_48 = intrinsic_movsd(var_48, xmm2);
var_40 = intrinsic_movsd(var_40, xmm1);
var_38 = intrinsic_movsd(var_38, xmm0);
var_30 = rax;
r12 = *_OBJC_IVAR_$_NCMaterialLayer._backdropLayer;
rdi = *(r14 + r12);
if (rbx <= 0x6) {
xmm0 = intrinsic_xorpd(xmm0, xmm0);
}
else {
xmm0 = intrinsic_movsd(xmm0, *0xdd60);
}
[rdi setBleedAmount:rdx];
rbx = *(r14 + r12);
xmm0 = intrinsic_movsd(xmm0, var_48);
xmm1 = intrinsic_movsd(xmm1, var_40);
rax = __CGColorGenericSRGBGray();
[rbx setBackgroundColor:rax];
rbx = r14->_tintLayer;
intrinsic_movsd(xmm1, *0xdc08);
intrinsic_movsd(xmm0, var_38);
rax = __CGColorGenericSRGBGray();
[rbx setBackgroundColor:rax];
[r14->_tintLayer setCompositingFilter:var_30];
[var_30 release];
return;
loc_bd11:
rax = [*_kCAFilterDarkenBlendMode retain];
xmm0 = intrinsic_movsd(xmm0, *0xdd10);
xmm1 = intrinsic_movsd(xmm1, *0xdd48);
xmm2 = intrinsic_movsd(xmm2, *0xdd50);
goto loc_be09;
loc_bd3e:
rax = [*_kCAFilterDarkenBlendMode retain];
xmm0 = intrinsic_movsd(xmm0, *0xdd38);
xmm1 = intrinsic_movsd(xmm1, *0xdd40);
xmm2 = intrinsic_movsd(xmm2, *0xdc08);
goto loc_be09;
loc_bd6b:
rax = [*_kCAFilterDarkenBlendMode retain];
xmm0 = intrinsic_movsd(xmm0, *0xdd10);
xmm1 = intrinsic_movsd(xmm1, *0xdd28);
xmm2 = intrinsic_movsd(xmm2, *0xdd30);
goto loc_be09;
loc_bd95:
rax = [*_kCAFilterDarkenBlendMode retain];
xmm0 = intrinsic_movsd(xmm0, *0xdd10);
xmm1 = intrinsic_movsd(xmm1, *0xdd18);
xmm2 = intrinsic_movsd(xmm2, *0xdd20);
goto loc_be09;
loc_bdbf:
rax = [*_kCAFilterLightenBlendMode retain];
xmm0 = intrinsic_movsd(xmm0, *0xdd00);
xmm1 = intrinsic_movsd(xmm1, *0xdd08);
goto loc_be01;
loc_be01:
xmm2 = intrinsic_movsd(xmm2, *0xdcf8);
goto loc_be09;
loc_bde1:
rax = [*_kCAFilterLightenBlendMode retain];
xmm0 = intrinsic_movsd(xmm0, *0xdce8);
xmm1 = intrinsic_movsd(xmm1, *0xdcf0);
goto loc_be01;
}
Using the CGS or SLS private headers, you can create an unmanaged lockscreen-and-above space like NotificationCenter does.
#include <Carbon/Carbon.h>
typedef void *CGSConnectionID;
extern CGSConnectionID _CGSDefaultConnection(void);
#define CGSDefaultConnection _CGSDefaultConnection()
typedef uint64_t CGSSpace;
typedef enum _CGSSpaceType {
kCGSSpaceUser,
kCGSSpaceFullscreen,
kCGSSpaceSystem,
kCGSSpaceUnknown
} CGSSpaceType;
typedef enum _CGSSpaceSelector {
kCGSSpaceCurrent = 5,
kCGSSpaceOther,
kCGSSpaceAll
} CGSSpaceSelector;
extern CFArrayRef CGSCopySpaces(const CGSConnectionID cid, CGSSpaceSelector type);
extern CFArrayRef CGSCopySpacesForWindows(const CGSConnectionID cid, CGSSpaceSelector type, CFArrayRef windows);
extern NSNumber * CGSWillSwitchSpaces(const CGSConnectionID cid, CFArrayRef a);
extern CFArrayRef CGSSpaceCopyOwners(const CGSConnectionID cid, CGSSpace space);
extern int CGSSpaceGetAbsoluteLevel(const CGSConnectionID cid, CGSSpace space);
extern void CGSSpaceSetAbsoluteLevel(const CGSConnectionID cid, CGSSpace space, int level);
extern int CGSSpaceGetCompatID(const CGSConnectionID cid, CGSSpace space);
extern void CGSSpaceSetCompatID(const CGSConnectionID cid, CGSSpace space, int compatID);
extern CGSSpaceType CGSSpaceGetType(const CGSConnectionID cid, CGSSpace space);
extern void CGSSpaceSetType(const CGSConnectionID cid, CGSSpace space, CGSSpaceType type);
extern CFStringRef CGSSpaceCopyName(const CGSConnectionID cid, CGSSpace space);
extern void CGSSpaceSetName(const CGSConnectionID cid, CGSSpace space, CFStringRef name);
extern CFArrayRef CGSSpaceCopyValues(const CGSConnectionID cid, CGSSpace space);
extern void CGSSpaceSetValues(const CGSConnectionID cid, CGSSpace space, CFArrayRef values);
typedef CFStringRef CGSManagedDisplay;
extern CGSManagedDisplay kCGSPackagesMainDisplayIdentifier;
extern CGSManagedDisplay CGSCopyBestManagedDisplayForRect(const CGSConnectionID cid, CGRect rect);
extern CGSManagedDisplay CGSCopyManagedDisplayForSpace(const CGSConnectionID cid, CGSSpace space);
extern CFArrayRef CGSCopyManagedDisplaySpaces(const CGSConnectionID cid);
extern bool CGSManagedDisplayIsAnimating(const CGSConnectionID cid, CGSManagedDisplay display);
extern void CGSManagedDisplaySetIsAnimating(const CGSConnectionID cid, CGSManagedDisplay display, bool isAnimating);
extern void CGSManagedDisplaySetCurrentSpace(const CGSConnectionID cid, CGSManagedDisplay display, CGSSpace space);
extern void CGSSpaceSetTransform(const CGSConnectionID cid, CGSSpace space, CGAffineTransform transform);
extern void CGSHideSpaces(const CGSConnectionID cid, NSArray *spaces);
extern void CGSShowSpaces(const CGSConnectionID cid, NSArray *spaces);
extern AXError _AXUIElementGetWindow(AXUIElementRef element, CGWindowID *idOut);
//
//
//
void -[FaceTime addWindowToUnmanagedSpace:](void * self, void * _cmd, void * arg2) {
r12 = self;
var_-48 = *___stack_chk_guard;
r13 = [arg2 retain];
r15 = CGSMainConnectionID();
rbx = @selector(lockScreenSpaceID);
if (_objc_msgSend(r12, rbx) == 0x0) {
rax = CGSSpaceCreate(r15, 0x1, 0x0);
[r12 setLockScreenSpaceID:rax];
var_-72 = r12;
rax = _objc_msgSend(r12, rbx);
CGSSpaceSetAbsoluteLevel(r15, rax, *(int32_t *)_kSLSSpaceAbsoluteLevelNotificationCenterAtScreenLock, _kSLSSpaceAbsoluteLevelNotificationCenterAtScreenLock);
r12 = [sub_100041e86() retain];
if (os_log_type_enabled(r12, 0x0) != 0x0) {
var_-88 = rsp;
r14 = rsp;
*(int32_t *)(r14 + 0xfffffffffffffff0) = 0x8000100;
*(r14 + 0xfffffffffffffff4) = [var_-72 lockScreenSpaceID];
r8 = r14 + 0xfffffffffffffff0;
r13 = r13;
_os_log_impl(__mh_execute_header, r12, 0x0, "Created unmanaged screen space with ID: %llu", r8, 0xc);
rsp = var_-88;
}
[r12 release];
rbx = @selector(lockScreenSpaceID);
r12 = var_-72;
}
if (_objc_msgSend(r12, rbx) != 0x0) {
var_-88 = r15;
rbx = [[r12 lockScreenWindows] retain];
r15 = r12;
r12 = r13;
rdx = r13;
r14 = [rbx containsObject:rdx];
[rbx release];
r13 = [sub_100041e86() retain];
rax = os_log_type_enabled(r13, 0x0);
if (r14 != 0x0) {
if (rax != 0x0) {
r14 = rsp;
rbx = rsp;
*(int32_t *)(rbx + 0xfffffffffffffff0) = 0x8000100;
*(rbx + 0xfffffffffffffff4) = [r12 windowNumber];
_os_log_impl(__mh_execute_header, r13, 0x0, "This window (%ld) has already been added to the unmanaged screen space. Ignoring.", rbx + 0xfffffffffffffff0, 0xc);
}
[r13 release];
r13 = r12;
}
else {
rcx = _objc_msgSend;
rbx = r15;
var_-80 = r12;
var_-72 = rbx;
if (rax != 0x0) {
var_-112 = rsp;
r14 = rsp;
*(int32_t *)(r14 + 0xffffffffffffffe0) = 0x8000200;
var_-96 = @selector(windowNumber);
rdi = r12;
r12 = rcx;
*(r14 + 0xffffffffffffffe4) = (r12)(rdi, @selector(windowNumber));
*(int16_t *)(r14 + 0xffffffffffffffec) = 0x800;
r15 = @selector(lockScreenSpaceID);
*(r14 + 0xffffffffffffffee) = (r12)(rbx, r15);
rcx = "Adding window: %ld to unmanaged space: %llu";
rdx = 0x0;
r8 = r14 + 0xffffffffffffffe0;
_os_log_impl(__mh_execute_header, r13, rdx, rcx, r8, 0x16);
}
else {
rcx = _objc_msgSend;
var_-96 = @selector(windowNumber);
r15 = @selector(lockScreenSpaceID);
r12 = rcx;
}
[r13 release];
rbx = [(r12)(@class(NSNumber), @selector(numberWithUnsignedLongLong:), (r12)(var_-72, r15, rdx, rcx, r8), rcx, r8) retain];
*var_-56 = rbx;
r13 = (r12)(@class(NSArray), @selector(arrayWithObjects:count:), var_-56, 0x1, r8);
[rbx release];
r14 = [(r12)(@class(NSNumber), @selector(numberWithInteger:), (r12)(var_-80, var_-96, var_-56, 0x1, r8), 0x1, r8) retain];
*var_-64 = r14;
rax = (r12)(@class(NSArray), @selector(arrayWithObjects:count:), var_-64, 0x1, r8);
CGSAddWindowsToSpaces(var_-88, rax, r13);
rdi = r14;
[rdi release];
CGSShowSpaces(var_-88, r13);
rbx = [(r12)(var_-72, @selector(lockScreenWindows), r13, 0x1, r8) retain];
(r12)(rbx, @selector(addObject:), var_-80, 0x1, r8);
[rbx release];
r13 = var_-80;
}
}
else {
r12 = [sub_100041e86() retain];
if (os_log_type_enabled(r12, 0x0) != 0x0) {
r15 = rsp;
rbx = rsp;
*(int32_t *)(rbx + 0xfffffffffffffff0) = 0x8000100;
*(rbx + 0xfffffffffffffff4) = [r13 windowNumber];
_os_log_impl(__mh_execute_header, r12, 0x0, "No unmanaged screen space to add window to: %ld", rbx + 0xfffffffffffffff0, 0xc);
}
[r12 release];
}
[r13 release];
if (*___stack_chk_guard != var_-48) {
__stack_chk_fail();
}
return;
}
- It turns out
WindowVous
(prefixWV
in Dock) was the early name forExpose
andMission Control
.