Skip to content

Commit

Permalink
Change global Fn key handling
Browse files Browse the repository at this point in the history
  • Loading branch information
robbertkl committed Nov 7, 2016
1 parent 7184653 commit 781dec5
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 113 deletions.
6 changes: 6 additions & 0 deletions TouchBar.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
5EAC87211DCA8BAD001BB8AC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5EAC871F1DCA8BAD001BB8AC /* MainMenu.xib */; };
5EC06EB91DCFCF4200A7AA57 /* UsbDeviceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EC06EB81DCFCF4200A7AA57 /* UsbDeviceController.m */; };
5EC478651DCBD51200C06ED1 /* TouchBarServer Helper.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5E19C5151DCB94BF00DA3CB1 /* TouchBarServer Helper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
5EE8BF561DD0D68A00AA074F /* Application.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EE8BF551DD0D68A00AA074F /* Application.m */; };
5EF078601DCA8CC400BD69DA /* PTChannel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EF078581DCA8CC400BD69DA /* PTChannel.m */; };
5EF078611DCA8CC400BD69DA /* PTChannel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EF078581DCA8CC400BD69DA /* PTChannel.m */; };
5EF078621DCA8CC400BD69DA /* PTProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EF0785B1DCA8CC400BD69DA /* PTProtocol.m */; };
Expand Down Expand Up @@ -85,6 +86,8 @@
5EAC87221DCA8BAD001BB8AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5EC06EB71DCFCF4200A7AA57 /* UsbDeviceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UsbDeviceController.h; sourceTree = "<group>"; };
5EC06EB81DCFCF4200A7AA57 /* UsbDeviceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UsbDeviceController.m; sourceTree = "<group>"; };
5EE8BF541DD0D68A00AA074F /* Application.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Application.h; sourceTree = "<group>"; };
5EE8BF551DD0D68A00AA074F /* Application.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Application.m; sourceTree = "<group>"; };
5EF078551DCA8CC400BD69DA /* Peertalk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Peertalk.h; sourceTree = "<group>"; };
5EF078561DCA8CC400BD69DA /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = "<group>"; };
5EF078571DCA8CC400BD69DA /* PTChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTChannel.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -202,6 +205,8 @@
children = (
5EAC87171DCA8BAC001BB8AC /* AppDelegate.h */,
5EAC87181DCA8BAC001BB8AC /* AppDelegate.m */,
5EE8BF541DD0D68A00AA074F /* Application.h */,
5EE8BF551DD0D68A00AA074F /* Application.m */,
5E19C50E1DCB947B00DA3CB1 /* StartAtLoginController.h */,
5E19C50F1DCB947B00DA3CB1 /* StartAtLoginController.m */,
5EC06EB71DCFCF4200A7AA57 /* UsbDeviceController.h */,
Expand Down Expand Up @@ -409,6 +414,7 @@
5EC06EB91DCFCF4200A7AA57 /* UsbDeviceController.m in Sources */,
5EF078631DCA8CC400BD69DA /* PTProtocol.m in Sources */,
5EF078611DCA8CC400BD69DA /* PTChannel.m in Sources */,
5EE8BF561DD0D68A00AA074F /* Application.m in Sources */,
5EF078651DCA8CC400BD69DA /* PTUSBHub.m in Sources */,
5EAC87191DCA8BAC001BB8AC /* AppDelegate.m in Sources */,
5E19C5101DCB947B00DA3CB1 /* StartAtLoginController.m in Sources */,
Expand Down
1 change: 1 addition & 0 deletions TouchBarServer/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

@interface AppDelegate : NSObject <NSApplicationDelegate>

- (void)keyEvent:(NSEvent *)event;

@end

205 changes: 93 additions & 112 deletions TouchBarServer/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
#import "Protocol.h"
#import "UsbDeviceController.h"

@import Carbon;

typedef int CGSConnectionID;
CG_EXTERN void CGSGetKeys(KeyMap k);
CG_EXTERN CGSConnectionID CGSMainConnectionID(void);
CG_EXTERN void CGSGetBackgroundEventMask(CGSConnectionID cid, int *outMask);
CG_EXTERN CGError CGSSetBackgroundEventMask(CGSConnectionID cid, int mask);

extern CGDisplayStreamRef SLSDFRDisplayStreamCreate(void *, dispatch_queue_t, CGDisplayStreamFrameAvailableHandler);
extern BOOL DFRSetStatus(int);
extern BOOL DFRFoundationPostEventWithMouseActivity(NSEventType type, NSPoint p);
Expand Down Expand Up @@ -112,12 +120,13 @@ @interface AppDelegate () <UsbDeviceControllerDelegate>

@implementation AppDelegate {
NSStatusItem *_statusItem;
id _monitor;
id _localMonitor;
TouchBarWindow* _touchBarWindow;

CGDisplayStreamRef _stream;
UsbDeviceController *_usbDeviceController;

BOOL _fnKeyIsDown;
BOOL _couldBeSoleFnKeyPress;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
Expand Down Expand Up @@ -180,61 +189,15 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
BOOL value = [[defaults valueForKeyPath:keyPath] boolValue];

if ([keyPath isEqualToString:@"values.EnableScreenBar"]) {
if (value && AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)(@{(__bridge id)kAXTrustedCheckOptionPrompt:@YES})) == NO) {
[defaults setValue:@NO forKeyPath:keyPath];
return;
}

CGSConnectionID connectionId = CGSMainConnectionID();
int backgroundEventMask;
int keyEventMask = NSKeyDownMask | NSKeyUpMask | NSFlagsChangedMask;
CGSGetBackgroundEventMask(connectionId, &backgroundEventMask);
if (value) {
[_touchBarWindow setIsVisible:NO];

[self startDetectSingleFnKeyPress:^{
if (_touchBarWindow.visible == YES) {
[NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
context.duration = 0.1;
[[_touchBarWindow animator] setAlphaValue:0.0];
} completionHandler:^{
if(_touchBarWindow.alphaValue == 0.0)
[_touchBarWindow setIsVisible:NO];
}];
} else {

NSPoint mousePoint = [NSEvent mouseLocation];
NSScreen* currentScreen = [NSScreen mainScreen];
for(NSScreen* screen in [NSScreen screens])
{
if(NSPointInRect(mousePoint, screen.visibleFrame)) {
currentScreen = screen;
break;
}
}

NSRect screenFrame = currentScreen.visibleFrame;
CGFloat screenRight = screenFrame.origin.x + screenFrame.size.width;
CGFloat barWidth = _touchBarWindow.frame.size.width;
CGFloat barHeight = _touchBarWindow.frame.size.height;

NSPoint origin = mousePoint;
origin.x -= barWidth * 0.5;
origin.y -= barHeight;

if(origin.x < screenFrame.origin.x)
origin.x = screenFrame.origin.x;

if(origin.x + barWidth > screenRight)
origin.x = screenRight - barWidth;

if(origin.y - barHeight < screenFrame.origin.y)
origin.y += barHeight;

[_touchBarWindow setFrameOrigin:origin];

_touchBarWindow.alphaValue = 1.0;
[_touchBarWindow setIsVisible:YES];
}
}];
CGSSetBackgroundEventMask(connectionId, backgroundEventMask | keyEventMask);
} else {
[self stopDetectingSingleFnKeyPress];
CGSSetBackgroundEventMask(connectionId, backgroundEventMask & ~keyEventMask);
[_touchBarWindow setIsVisible:NO];
}
} else if ([keyPath isEqualToString:@"values.EnableRemoteBar"]) {
Expand All @@ -246,73 +209,91 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
}
}

- (void)startDetectSingleFnKeyPress:(void (^)(void))handler
{
if(_monitor != nil)
return;

NSMutableSet<NSNumber*>* pressedKeySet = [NSMutableSet new];
__block BOOL fnKeyIsDown = NO;
__block BOOL couldBeSoleFnKeyPress = YES;
__block NSEventModifierFlags otherModifiersBesideFn = 0;
NSEvent* (^monitorHandler)(NSEvent*) = ^(NSEvent* event) {
- (void)toggleTouchBarWindow {
if (_touchBarWindow.visible == YES) {
[NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
context.duration = 0.1;
[[_touchBarWindow animator] setAlphaValue:0.0];
} completionHandler:^{
if(_touchBarWindow.alphaValue == 0.0)
[_touchBarWindow setIsVisible:NO];
}];
} else {

switch(event.type) {
case NSKeyDown:
[pressedKeySet addObject:@(event.keyCode)];
couldBeSoleFnKeyPress = NO;
break;

case NSKeyUp:
[pressedKeySet removeObject:@(event.keyCode)];
couldBeSoleFnKeyPress = NO;
NSPoint mousePoint = [NSEvent mouseLocation];
NSScreen* currentScreen = [NSScreen mainScreen];
for(NSScreen* screen in [NSScreen screens])
{
if(NSPointInRect(mousePoint, screen.visibleFrame)) {
currentScreen = screen;
break;
}
}

NSRect screenFrame = currentScreen.visibleFrame;
CGFloat screenRight = screenFrame.origin.x + screenFrame.size.width;
CGFloat barWidth = _touchBarWindow.frame.size.width;
CGFloat barHeight = _touchBarWindow.frame.size.height;

NSPoint origin = mousePoint;
origin.x -= barWidth * 0.5;
origin.y -= barHeight;

if(origin.x < screenFrame.origin.x)
origin.x = screenFrame.origin.x;

if(origin.x + barWidth > screenRight)
origin.x = screenRight - barWidth;

if(origin.y - barHeight < screenFrame.origin.y)
origin.y += barHeight;

[_touchBarWindow setFrameOrigin:origin];

_touchBarWindow.alphaValue = 1.0;
[_touchBarWindow setIsVisible:YES];
}
}

- (void)keyEvent:(NSEvent *)event {
if (![[[[NSUserDefaultsController sharedUserDefaultsController] values] valueForKey:@"EnableScreenBar"] boolValue]) return;

switch(event.type) {
case NSKeyDown:
_couldBeSoleFnKeyPress = NO;
break;

case NSKeyUp:
_couldBeSoleFnKeyPress = NO;
break;

case NSFlagsChanged: {
NSEventModifierFlags modifierFlags = (event.modifierFlags & NSDeviceIndependentModifierFlagsMask);
BOOL newFnKeyIsDown = (modifierFlags & NSFunctionKeyMask) != 0;

if(newFnKeyIsDown != _fnKeyIsDown) {
_fnKeyIsDown = newFnKeyIsDown;

case NSFlagsChanged: {
NSEventModifierFlags modifierFlags = (event.modifierFlags & NSDeviceIndependentModifierFlagsMask);
otherModifiersBesideFn = (modifierFlags & ~NSFunctionKeyMask);
BOOL newFnKeyIsDown = (modifierFlags & NSFunctionKeyMask) != 0;
KeyMap keymap;
CGSGetKeys(keymap);

if(newFnKeyIsDown != fnKeyIsDown) {
fnKeyIsDown = newFnKeyIsDown;
if(otherModifiersBesideFn == 0 && pressedKeySet.count == 0) {
if(fnKeyIsDown == YES){
couldBeSoleFnKeyPress = YES;
} else if(couldBeSoleFnKeyPress == YES) {
if(handler != nil)
handler();
}
if (keymap[0].bigEndianValue == 0 && keymap[2].bigEndianValue == 0 && keymap[3].bigEndianValue == 0) {
if (_fnKeyIsDown) {
_couldBeSoleFnKeyPress = keymap[1].bigEndianValue == 1 << 31;
} else if (_couldBeSoleFnKeyPress && keymap[1].bigEndianValue == 0) {
[self toggleTouchBarWindow];
}
} else {
_couldBeSoleFnKeyPress = NO;
}

if(otherModifiersBesideFn != 0 || pressedKeySet.count > 0)
couldBeSoleFnKeyPress = NO;
} else {
_couldBeSoleFnKeyPress = NO;
}
break;

default:
break;
}

return event;
};
_monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask|NSKeyUpMask|NSFlagsChangedMask handler:^(NSEvent* event){
monitorHandler(event);
}];
_localMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask|NSKeyUpMask|NSFlagsChangedMask handler:monitorHandler];
}

- (void)stopDetectingSingleFnKeyPress
{
if(_monitor != nil)
{
[NSEvent removeMonitor:_monitor];
_monitor = nil;
}

if (_localMonitor) {
[NSEvent removeMonitor:_localMonitor];
_localMonitor = nil;

default:
break;
}
}

Expand Down
13 changes: 13 additions & 0 deletions TouchBarServer/Application.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Application.h
// Blaat
//
// Created by Robbert Klarenbeek on 07/11/2016.
// Copyright © 2016 Bikkelbroeders. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface Application : NSApplication

@end
32 changes: 32 additions & 0 deletions TouchBarServer/Application.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Application.m
// Blaat
//
// Created by Robbert Klarenbeek on 07/11/2016.
// Copyright © 2016 Bikkelbroeders. All rights reserved.
//

#import "Application.h"

#import "AppDelegate.h"

@implementation Application

- (NSEvent *)nextEventMatchingMask:(NSEventMask)mask untilDate:(NSDate *)expiration inMode:(NSRunLoopMode)mode dequeue:(BOOL)deqFlag {
NSEvent *event = [super nextEventMatchingMask:mask untilDate:expiration inMode:mode dequeue:deqFlag];
if (event.type == NSKeyDown || event.type == NSKeyUp || event.type == NSFlagsChanged) {
AppDelegate *appDelegate = self.delegate;
[appDelegate keyEvent:event];
}
return event;
}

- (void)sendEvent:(NSEvent *)event {
if (!self.keyWindow && (event.type == NSKeyDown || event.type == NSKeyUp || event.type == NSFlagsChanged)) {
return;
}

[super sendEvent:event];
}

@end
2 changes: 1 addition & 1 deletion TouchBarServer/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<string>Application</string>
</dict>
</plist>

0 comments on commit 781dec5

Please sign in to comment.