summaryrefslogtreecommitdiffstats
path: root/osdep
diff options
context:
space:
mode:
Diffstat (limited to 'osdep')
-rw-r--r--osdep/macosx_application.m14
-rw-r--r--osdep/macosx_application_objc.h5
-rw-r--r--osdep/macosx_events.h8
-rw-r--r--osdep/macosx_events.m113
4 files changed, 109 insertions, 31 deletions
diff --git a/osdep/macosx_application.m b/osdep/macosx_application.m
index 1329091e12..665a04b222 100644
--- a/osdep/macosx_application.m
+++ b/osdep/macosx_application.m
@@ -120,19 +120,7 @@ static NSString *escape_loadfile_name(NSString *input)
- (void)sendEvent:(NSEvent *)event
{
- if ([event type] == NSSystemDefined && [event subtype] == 8) {
- // It's a media key! Handle it specially. The magic numbers are reverse
- // engineered and found on several blog posts. Unfortunately there is
- // no public API for this. F-bomb.
- int code = (([event data1] & 0xFFFF0000) >> 16);
- int flags = ([event data1] & 0x0000FFFF);
- int down = (((flags & 0xFF00) >> 8)) == 0xA;
-
- if (down)
- [self.eventsResponder handleMediaKey:code];
- } else {
- [super sendEvent:event];
- }
+ [super sendEvent:event];
if (self.inputContext)
mp_input_wakeup(self.inputContext);
diff --git a/osdep/macosx_application_objc.h b/osdep/macosx_application_objc.h
index 3ab74698c3..c8026cfc14 100644
--- a/osdep/macosx_application_objc.h
+++ b/osdep/macosx_application_objc.h
@@ -28,10 +28,13 @@ struct cocoa_input_queue;
@end
@interface EventsResponder : NSObject <HIDRemoteDelegate>
-- (void)handleMediaKey:(int)key;
+- (BOOL)handleMediaKey:(int)key;
- (NSEvent *)handleKeyDown:(NSEvent *)event;
- (void)startAppleRemote;
- (void)stopAppleRemote;
+- (void)startMediaKeys;
+- (void)restartMediaKeys;
+- (void)stopMediaKeys;
@property(nonatomic, retain) HIDRemote *remote;
@end
diff --git a/osdep/macosx_events.h b/osdep/macosx_events.h
index 9557aeab5c..b8162dc125 100644
--- a/osdep/macosx_events.h
+++ b/osdep/macosx_events.h
@@ -23,7 +23,11 @@
void cocoa_put_key(int keycode);
void cocoa_check_events(void);
-void cocoa_start_apple_remote(void);
-void cocoa_stop_apple_remote(void);
+
+void cocoa_init_apple_remote(void);
+void cocoa_uninit_apple_remote(void);
+
+void cocoa_init_media_keys(void);
+void cocoa_uninit_media_keys(void);
#endif
diff --git a/osdep/macosx_events.m b/osdep/macosx_events.m
index 86d0ebaa3e..7970f0b5d5 100644
--- a/osdep/macosx_events.m
+++ b/osdep/macosx_events.m
@@ -92,18 +92,67 @@ static int convert_key(unsigned key, unsigned charcode)
return charcode;
}
-void cocoa_start_apple_remote(void)
+void cocoa_init_apple_remote(void)
{
Application *app = mpv_shared_app();
[app.eventsResponder startAppleRemote];
}
-void cocoa_stop_apple_remote(void)
+void cocoa_uninit_apple_remote(void)
{
Application *app = mpv_shared_app();
[app.eventsResponder stopAppleRemote];
}
+static CGEventRef tap_event_callback(CGEventTapProxy proxy, CGEventType type,
+ CGEventRef event, void *ctx)
+{
+ EventsResponder *responder = ctx;
+
+ if (type == kCGEventTapDisabledByTimeout) {
+ // The Mach Port receiving the taps became unresponsive for some
+ // reason, restart listening on it.
+ [responder restartMediaKeys];
+ return event;
+ }
+
+ if (type == kCGEventTapDisabledByUserInput)
+ return event;
+
+ NSEvent *nse = [NSEvent eventWithCGEvent:event];
+
+ if ([nse type] != NSSystemDefined || [nse subtype] != 8)
+ // This is not a media key
+ return event;
+
+ // It's a media key! Handle it specially. The magic numbers are reverse
+ // engineered and found on several blog posts. Unfortunately there is
+ // no public API for this. F-bomb.
+ int code = (([nse data1] & 0xFFFF0000) >> 16);
+ int flags = ([nse data1] & 0x0000FFFF);
+ int down = (((flags & 0xFF00) >> 8)) == 0xA;
+
+ if (down && [responder handleMediaKey:code]) {
+ // Handled this event, return nil so that it is removed from the
+ // global queue.
+ return nil;
+ } else {
+ // Was a media key but we were not interested in it. Leave it in the
+ // global queue by returning the original event.
+ return event;
+ }
+}
+
+void cocoa_init_media_keys(void) {
+ Application *app = mpv_shared_app();
+ [app.eventsResponder startMediaKeys];
+}
+
+void cocoa_uninit_media_keys(void) {
+ Application *app = mpv_shared_app();
+ [app.eventsResponder stopMediaKeys];
+}
+
void cocoa_check_events(void)
{
Application *app = mpv_shared_app();
@@ -117,7 +166,9 @@ void cocoa_put_key(int keycode)
[mpv_shared_app().iqueue push:keycode];
}
-@implementation EventsResponder
+@implementation EventsResponder {
+ CFMachPortRef _mk_tap_port;
+}
- (void)startAppleRemote
{
dispatch_async(dispatch_get_main_queue(), ^{
@@ -135,24 +186,56 @@ void cocoa_put_key(int keycode)
[self.remote stopRemoteControl];
});
}
+- (void)restartMediaKeys
+{
+ CGEventTapEnable(self->_mk_tap_port, true);
+}
+- (void)startMediaKeys
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // Install a Quartz Event Tap. This will notify mpv through the
+ // returned Mach Port and cause mpv to execute the `tap_event_callback`
+ // function.
+ self->_mk_tap_port = CGEventTapCreate(kCGSessionEventTap,
+ kCGHeadInsertEventTap,
+ kCGEventTapOptionDefault,
+ CGEventMaskBit(NX_SYSDEFINED),
+ tap_event_callback,
+ self);
+
+ assert(self->_mk_tap_port != nil);
+
+ NSMachPort *port = (NSMachPort *)self->_mk_tap_port;
+ [[NSRunLoop mainRunLoop] addPort:port forMode:NSRunLoopCommonModes];
+ });
+}
+- (void)stopMediaKeys
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSMachPort *port = (NSMachPort *)self->_mk_tap_port;
+ [[NSRunLoop mainRunLoop] removePort:port forMode:NSRunLoopCommonModes];
+ CFRelease(self->_mk_tap_port);
+ self->_mk_tap_port = nil;
+ });
+}
- (NSArray *) keyEquivalents
{
return @[@"h", @"q", @"Q", @"0", @"1", @"2"];
}
-- (void)handleMediaKey:(int)key
+- (BOOL)handleMediaKey:(int)key
{
- switch (key) {
- case NX_KEYTYPE_PLAY:
- cocoa_put_key(MP_KEY_PLAY);
- break;
-
- case NX_KEYTYPE_FAST:
- cocoa_put_key(MP_KEY_NEXT);
- break;
+ NSDictionary *keymap = @{
+ @(NX_KEYTYPE_PLAY): @(MP_MK_PLAY),
+ @(NX_KEYTYPE_REWIND): @(MP_MK_PREV),
+ @(NX_KEYTYPE_FAST): @(MP_MK_NEXT),
+ };
- case NX_KEYTYPE_REWIND:
- cocoa_put_key(MP_KEY_PREV);
- break;
+ int mpkey = [keymap[@(key)] intValue];
+ if (mpkey > 0) {
+ cocoa_put_key(mpkey);
+ return YES;
+ } else {
+ return NO;
}
}
- (NSEvent*)handleKeyDown:(NSEvent *)event