diff --git a/keycastr/About.ca/index.xml b/keycastr/About.ca/index.xml index 751b6da..fd2fd8d 100644 --- a/keycastr/About.ca/index.xml +++ b/keycastr/About.ca/index.xml @@ -32,6 +32,8 @@ multitouchEnabled + playerBackgroundColor + 0.95 0.95 0.95 1 presentationMouseEventsEnabled presentationShowsCursor @@ -43,7 +45,7 @@ savesWindowFrame scalesToFitInPlayer - + showsTouches snappingEnabled diff --git a/keycastr/About.ca/main.caml b/keycastr/About.ca/main.caml index 62c8c9f..8dfa369 100644 --- a/keycastr/About.ca/main.caml +++ b/keycastr/About.ca/main.caml @@ -1,44 +1,12 @@ - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/keycastr/KCAboutView.m b/keycastr/KCAboutView.m index 4804f9d..42203bb 100644 --- a/keycastr/KCAboutView.m +++ b/keycastr/KCAboutView.m @@ -30,7 +30,14 @@ @interface KCAboutView : NSView @end -@implementation KCAboutView +@implementation KCAboutView { + CALayer *_rootLayer; + CAStateController *_stateController; + CAState *_pressedState; + + id _eventMonitor; +} + - (void)awakeFromNib { [super awakeFromNib]; @@ -38,15 +45,88 @@ NSError *outError; CAPackage *package = [CAPackage packageWithContentsOfURL:url type:kCAPackageTypeCAMLBundle options:nil error:&outError]; - if (outError) { NSLog(@"%@", [outError description]); + + return; + } + + _rootLayer = package.rootLayer; + + _stateController = [[CAStateController alloc] initWithLayer:_rootLayer]; + [_stateController setInitialStatesOfLayer:package.rootLayer transitionSpeed:0.0]; + + _pressedState = [_rootLayer valueForKey:@"states"][0]; + + self.wantsLayer = YES; + self.layer = package.rootLayer; + + // Track mouse hovering over app logo + CGRect appLogoRect = CGRectMake(84, 24, 94, 94); + + NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:appLogoRect + options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) + owner:self + userInfo:nil]; + + [self addTrackingArea:trackingArea]; +} + +- (void)setPressedState:(BOOL)pressed { + if (pressed) { + [_stateController setState:_pressedState ofLayer:_rootLayer transitionSpeed:1.0]; } else { - self.wantsLayer = YES; - self.layer = package.rootLayer; + [_stateController setState:nil ofLayer:_rootLayer transitionSpeed:1.0]; } } + +// MARK: Event monitoring + +- (void)removeMonitor { + if (_eventMonitor) { + [NSEvent removeMonitor:_eventMonitor]; + _eventMonitor = nil; + } +} + +- (void)viewDidMoveToWindow { + [super viewDidMoveToWindow]; + + if (self.window) { + __weak typeof(self) weakSelf = self; + + // Track command button being held + _eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskFlagsChanged + handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) { + BOOL heldCommand = event.modifierFlags & NSEventModifierFlagCommand; + + [weakSelf handleCommandPress:heldCommand]; + + return event; + }]; + } + else { + [self removeMonitor]; + } +} + +- (void)dealloc { + [self removeMonitor]; +} + +// MARK: Event handling + +- (void)handleCommandPress:(BOOL)heldCommand { + [self setPressedState:heldCommand]; +} + +- (void)mouseEntered:(NSEvent *)event { + [self setPressedState:YES]; +} +- (void)mouseExited:(NSEvent *)event { + [self setPressedState:NO]; +} @end diff --git a/keycastr/QuartzCorePrivate.h b/keycastr/QuartzCorePrivate.h index 272d831..99c0b60 100644 --- a/keycastr/QuartzCorePrivate.h +++ b/keycastr/QuartzCorePrivate.h @@ -6,12 +6,25 @@ extern NSString *kCAPackageTypeCAMLBundle; @interface CAPackage : NSObject +@property(readonly) CALayer *rootLayer; + + (id)packageWithData:(NSData *)data type:(NSString *)type options:(id)opts error:(NSError **)outError; + (id)packageWithContentsOfURL:(NSURL *)url type:(NSString *)type options:(id)opts error:(NSError **)outError; -- (NSArray *)publishedObjectNames; +@end -@property(readonly, getter=isGeometryFlipped) BOOL geometryFlipped; -@property(readonly) CALayer *rootLayer; + +@interface CAState : NSObject; +@end + + +@interface CAStateController : NSObject; + +@property (readonly) CALayer* layer; + +- (void)setState:(id)state ofLayer:(id)layer transitionSpeed:(float)speed; +- (void)setState:(id)state ofLayer:(id)layer; +- (id)initWithLayer:(id)layer; +- (void)setInitialStatesOfLayer:(id)layer transitionSpeed:(float)speed; @end