cocoa: decouple events from application somewhat

This commit is contained in:
FRAU KOUJIRO 2014-04-15 16:51:40 -07:00 committed by Stefano Pigozzi
parent ff6c387a73
commit 78a266d599
4 changed files with 118 additions and 64 deletions

View File

@ -23,16 +23,20 @@
#include "common/msg.h"
#include "input/input.h"
#include "input/event.h"
#include "input/keycodes.h"
#include "osdep/macosx_application_objc.h"
#import "osdep/macosx_application_objc.h"
#include "osdep/macosx_compat.h"
#import "osdep/macosx_events_objc.h"
#define MPV_PROTOCOL @"mpv://"
static pthread_t playback_thread_id;
@interface Application (PrivateMethods)
@interface Application ()
{
EventsResponder *_eventsResponder;
}
- (NSMenuItem *)menuItemWithParent:(NSMenu *)parent
title:(NSString *)title
action:(SEL)selector
@ -61,17 +65,14 @@ Application *mpv_shared_app(void)
@synthesize argumentsList = _arguments_list;
@synthesize willStopOnOpenEvent = _will_stop_on_open_event;
@synthesize inputContext = _input_context;
@synthesize eventsResponder = _events_responder;
@synthesize menuItems = _menu_items;
@synthesize input_ready = _input_ready;
- (void)sendEvent:(NSEvent *)event
{
[super sendEvent:event];
if (self.inputContext)
mp_input_wakeup(self.inputContext);
if (_eventsResponder.inputContext)
mp_input_wakeup(_eventsResponder.inputContext);
}
- (id)init
@ -80,19 +81,8 @@ Application *mpv_shared_app(void)
self.menuItems = [[[NSMutableDictionary alloc] init] autorelease];
self.files = nil;
self.argumentsList = [[[NSMutableArray alloc] init] autorelease];
self.eventsResponder = [[[EventsResponder alloc] init] autorelease];
_eventsResponder = [EventsResponder sharedInstance];
self.willStopOnOpenEvent = NO;
self.input_ready = [[[NSCondition alloc] init] autorelease];
[NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask|NSKeyUpMask
handler:^(NSEvent *event) {
BOOL equivalent = [[NSApp mainMenu] performKeyEquivalent:event];
if (equivalent) {
return (NSEvent *)nil;
} else {
return [self.eventsResponder handleKey:event];
}
}];
NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager];
[em setEventHandler:self
@ -174,9 +164,10 @@ Application *mpv_shared_app(void)
- (void)stopMPV:(char *)cmd
{
if (self.inputContext) {
mp_cmd_t *cmdt = mp_input_parse_cmd(self.inputContext, bstr0(cmd), "");
mp_input_queue_cmd(self.inputContext, cmdt);
struct input_ctx *inputContext = _eventsResponder.inputContext;
if (inputContext) {
mp_cmd_t *cmdt = mp_input_parse_cmd(inputContext, bstr0(cmd), "");
mp_input_queue_cmd(inputContext, cmdt);
} else {
terminate_cocoa_application();
}
@ -289,7 +280,7 @@ Application *mpv_shared_app(void)
size_t bytes = [obj lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
files_utf8[i] = talloc_memdup(files_utf8, filename, bytes + 1);
}];
mp_event_drop_files(self.inputContext, num_files, files_utf8);
mp_event_drop_files(_eventsResponder.inputContext, num_files, files_utf8);
talloc_free(files_utf8);
}
@ -327,10 +318,10 @@ int cocoa_main(mpv_main_fn mpv_main, int argc, char *argv[])
macosx_finder_args_preinit(&argc, &argv);
pthread_create(&playback_thread_id, NULL, playback_thread, &ctx);
[mpv_shared_app().input_ready lock];
while (!mpv_shared_app().inputContext)
[mpv_shared_app().input_ready wait];
[mpv_shared_app().input_ready unlock];
[_eventsResponder.input_ready lock];
while (!_eventsResponder.inputContext)
[_eventsResponder.input_ready wait];
[_eventsResponder.input_ready unlock];
cocoa_run_runloop();
@ -387,10 +378,10 @@ void cocoa_stop_runloop(void)
void cocoa_set_input_context(struct input_ctx *input_context)
{
[mpv_shared_app().input_ready lock];
mpv_shared_app().inputContext = input_context;
[mpv_shared_app().input_ready signal];
[mpv_shared_app().input_ready unlock];
[_eventsResponder.input_ready lock];
_eventsResponder.inputContext = input_context;
[_eventsResponder.input_ready signal];
[_eventsResponder.input_ready unlock];
}
void cocoa_post_fake_event(void)

View File

@ -18,19 +18,6 @@
#import <Cocoa/Cocoa.h>
#include "osdep/macosx_application.h"
#import "ar/HIDRemote.h"
@interface EventsResponder : NSObject <HIDRemoteDelegate>
- (BOOL)handleMediaKey:(NSEvent *)event;
- (NSEvent *)handleKey:(NSEvent *)event;
- (void)startAppleRemote;
- (void)stopAppleRemote;
- (void)startMediaKeys;
- (void)restartMediaKeys;
- (void)stopMediaKeys;
- (int)mapKeyModifiers:(int)cocoaModifiers;
- (int)keyModifierMask:(NSEvent *)event;
@end
@interface Application : NSApplication
- (void)initialize_menu;
@ -38,13 +25,10 @@
- (void)stopPlayback;
- (void)handleFilesArray:(NSArray *)files;
@property(nonatomic, assign) struct input_ctx *inputContext;
@property(nonatomic, retain) EventsResponder *eventsResponder;
@property(nonatomic, retain) NSMutableDictionary *menuItems;
@property(nonatomic, retain) NSArray *files;
@property(nonatomic, retain) NSMutableArray *argumentsList;
@property(nonatomic, assign) BOOL willStopOnOpenEvent;
@property(nonatomic, retain) NSCondition *input_ready;
@end
Application *mpv_shared_app(void);

View File

@ -27,12 +27,30 @@
#include "talloc.h"
#include "input/input.h"
#include "input/keycodes.h"
// doesn't make much sense, but needed to access keymap functionality
#include "video/out/vo.h"
#import "osdep/macosx_application_objc.h"
#include "osdep/macosx_events.h"
#include "osdep/macosx_compat.h"
#import "osdep/macosx_events_objc.h"
@interface EventsResponder ()
{
CFMachPortRef _mk_tap_port;
HIDRemote *_remote;
}
- (BOOL)handleMediaKey:(NSEvent *)event;
- (NSEvent *)handleKey:(NSEvent *)event;
- (void)startAppleRemote;
- (void)stopAppleRemote;
- (void)startMediaKeys;
- (void)restartMediaKeys;
- (void)stopMediaKeys;
- (int)mapKeyModifiers:(int)cocoaModifiers;
- (int)keyModifierMask:(NSEvent *)event;
@end
#define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask)
#define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask)
@ -93,14 +111,12 @@ static int convert_key(unsigned key, unsigned charcode)
void cocoa_init_apple_remote(void)
{
Application *app = mpv_shared_app();
[app.eventsResponder startAppleRemote];
[[EventsResponder sharedInstance] startAppleRemote];
}
void cocoa_uninit_apple_remote(void)
{
Application *app = mpv_shared_app();
[app.eventsResponder stopAppleRemote];
[[EventsResponder sharedInstance] stopAppleRemote];
}
static int mk_code(NSEvent *event)
@ -150,34 +166,64 @@ static CGEventRef tap_event_callback(CGEventTapProxy proxy, CGEventType type,
}
void cocoa_init_media_keys(void) {
[mpv_shared_app().eventsResponder startMediaKeys];
[[EventsResponder sharedInstance] startMediaKeys];
}
void cocoa_uninit_media_keys(void) {
[mpv_shared_app().eventsResponder stopMediaKeys];
[[EventsResponder sharedInstance] stopMediaKeys];
}
void cocoa_put_key(int keycode)
{
if (mpv_shared_app().inputContext)
mp_input_put_key(mpv_shared_app().inputContext, keycode);
struct input_ctx *inputContext = [EventsResponder sharedInstance].inputContext;
if (inputContext)
mp_input_put_key(inputContext, keycode);
}
void cocoa_put_key_with_modifiers(int keycode, int modifiers)
{
keycode |= [mpv_shared_app().eventsResponder mapKeyModifiers:modifiers];
keycode |= [[EventsResponder sharedInstance] mapKeyModifiers:modifiers];
cocoa_put_key(keycode);
}
@implementation EventsResponder {
CFMachPortRef _mk_tap_port;
HIDRemote *_remote;
@implementation EventsResponder
@synthesize inputContext = _input_context;
@synthesize input_ready = _input_ready;
+ (EventsResponder *)sharedInstance
{
static EventsResponder *responder = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
responder = [EventsResponder new];
});
return responder;
}
- (id)init
{
self = [super init];
if (self) {
_input_ready = [NSCondition new];
[NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask|NSKeyUpMask
handler:^(NSEvent *event) {
BOOL equivalent = [[NSApp mainMenu] performKeyEquivalent:event];
if (equivalent) {
return (NSEvent *)nil;
} else {
return [self handleKey:event];
}
}];
}
return self;
}
- (BOOL)useAltGr
{
if (mpv_shared_app().inputContext)
return mp_input_use_alt_gr(mpv_shared_app().inputContext);
if (self.inputContext)
return mp_input_use_alt_gr(self.inputContext);
else
return YES;
}

View File

@ -0,0 +1,33 @@
/*
* Cocoa Application Event Handling
*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#import "ar/HIDRemote.h"
#include "osdep/macosx_events.h"
struct input_ctx;
@interface EventsResponder : NSObject <HIDRemoteDelegate>
+ (EventsResponder *)sharedInstance;
@property(nonatomic, assign) struct input_ctx *inputContext;
@property(nonatomic, retain) NSCondition *input_ready;
@end