mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Merge pull request #655 from TomHarte/EventProtocol
Rationalises protocol for application-level event theft.
This commit is contained in:
commit
48f4d8b875
@ -401,6 +401,6 @@ void IWM::set_component_prefers_clocking(ClockingHint::Source *component, Clocki
|
||||
}
|
||||
|
||||
void IWM::set_activity_observer(Activity::Observer *observer) {
|
||||
if(drives_[0]) drives_[0]->set_activity_observer(observer, "Internal Drive", true);
|
||||
if(drives_[1]) drives_[1]->set_activity_observer(observer, "External Drive", true);
|
||||
if(drives_[0]) drives_[0]->set_activity_observer(observer, "Internal Floppy", true);
|
||||
if(drives_[1]) drives_[1]->set_activity_observer(observer, "External Floppy", true);
|
||||
}
|
||||
|
@ -11,20 +11,22 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@protocol CSApplicationKeyboardEventDelegate
|
||||
- (void)sendEvent:(nonnull NSEvent *)event;
|
||||
@class CSApplication;
|
||||
|
||||
@protocol CSApplicationEventDelegate
|
||||
- (BOOL)application:(nonnull CSApplication *)application shouldSendEvent:(nonnull NSEvent *)event;
|
||||
@end
|
||||
|
||||
/*!
|
||||
CSApplication differs from NSApplication in only one regard: it supports a keyboardEventDelegate.
|
||||
CSApplication differs from NSApplication in only one regard: it supports an eventDelegate.
|
||||
|
||||
If a keyboardEventDelegate is installed, all keyboard events — @c NSEventTypeKeyUp,
|
||||
@c NSEventTypeKeyDown and @c NSEventTypeFlagsChanged — will be diverted to it
|
||||
rather than passed through the usual processing. As a result keyboard shortcuts and assistive
|
||||
dialogue navigations won't work.
|
||||
If conected, an eventDelegate will be offered all application events prior to their propagation
|
||||
into the application proper. It may opt to remove those events from the queue. This primarily
|
||||
provides a way to divert things like the command key that will otherwise trigger menu
|
||||
shortcuts, for periods when it is appropriate to do so.
|
||||
*/
|
||||
@interface CSApplication: NSApplication
|
||||
@property(nonatomic, weak, nullable) id<CSApplicationKeyboardEventDelegate> keyboardEventDelegate;
|
||||
@property(nonatomic, weak, nullable) id<CSApplicationEventDelegate> eventDelegate;
|
||||
@end
|
||||
|
||||
|
||||
|
@ -11,27 +11,10 @@
|
||||
@implementation CSApplication
|
||||
|
||||
- (void)sendEvent:(NSEvent *)event {
|
||||
// The only reason to capture events here rather than at the window or view
|
||||
// is to divert key combinations such as command+w or command+q in the few
|
||||
// occasions when the user would expect those to affect a running machine
|
||||
// rather than to affect application state.
|
||||
//
|
||||
// Most obviously: when emulating a Macintosh, you'd expect command+q to
|
||||
// quit the application inside the Macintosh, not to quit the emulator.
|
||||
|
||||
switch(event.type) {
|
||||
case NSEventTypeKeyUp:
|
||||
case NSEventTypeKeyDown:
|
||||
case NSEventTypeFlagsChanged:
|
||||
if(self.keyboardEventDelegate) {
|
||||
[self.keyboardEventDelegate sendEvent:event];
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
[super sendEvent:event];
|
||||
// Send the event unless an event delegate says otherwise.
|
||||
if(!self.eventDelegate || [self.eventDelegate application:self shouldSendEvent:event]) {
|
||||
[super sendEvent:event];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -11,7 +11,7 @@
|
||||
@import CoreVideo;
|
||||
@import GLKit;
|
||||
|
||||
@interface CSOpenGLView () <NSDraggingDestination, CSApplicationKeyboardEventDelegate>
|
||||
@interface CSOpenGLView () <NSDraggingDestination, CSApplicationEventDelegate>
|
||||
@end
|
||||
|
||||
@implementation CSOpenGLView {
|
||||
@ -140,43 +140,32 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)propagateKeyboardEvent:(NSEvent *)event {
|
||||
switch(event.type) {
|
||||
default: break;
|
||||
- (void)keyDown:(NSEvent *)event {
|
||||
[self.responderDelegate keyDown:event];
|
||||
}
|
||||
|
||||
case kCGEventKeyDown:
|
||||
[self.responderDelegate keyDown:event];
|
||||
break;
|
||||
case kCGEventKeyUp:
|
||||
[self.responderDelegate keyUp:event];
|
||||
break;
|
||||
case kCGEventFlagsChanged:
|
||||
// Release the mouse upon a control + command.
|
||||
if(_mouseIsCaptured &&
|
||||
event.modifierFlags & NSEventModifierFlagControl &&
|
||||
event.modifierFlags & NSEventModifierFlagCommand) {
|
||||
[self releaseMouse];
|
||||
}
|
||||
- (void)keyUp:(NSEvent *)event {
|
||||
[self.responderDelegate keyUp:event];
|
||||
}
|
||||
|
||||
[self.responderDelegate flagsChanged:event];
|
||||
break;
|
||||
- (void)flagsChanged:(NSEvent *)event {
|
||||
// Release the mouse upon a control + command.
|
||||
if(_mouseIsCaptured &&
|
||||
event.modifierFlags & NSEventModifierFlagControl &&
|
||||
event.modifierFlags & NSEventModifierFlagCommand) {
|
||||
[self releaseMouse];
|
||||
}
|
||||
|
||||
[self.responderDelegate flagsChanged:event];
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent *)theEvent {
|
||||
[self propagateKeyboardEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)keyUp:(NSEvent *)theEvent {
|
||||
[self propagateKeyboardEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)theEvent {
|
||||
[self propagateKeyboardEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)sendEvent:(NSEvent *)event {
|
||||
[self propagateKeyboardEvent:event];
|
||||
- (BOOL)application:(nonnull CSApplication *)application shouldSendEvent:(nonnull NSEvent *)event {
|
||||
switch(event.type) {
|
||||
default: return YES;
|
||||
case NSEventTypeKeyUp: [self keyUp:event]; return NO;
|
||||
case NSEventTypeKeyDown: [self keyDown:event]; return NO;
|
||||
case NSEventTypeFlagsChanged: [self flagsChanged:event]; return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)paste:(id)sender {
|
||||
@ -245,7 +234,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
||||
CGAssociateMouseAndMouseCursorPosition(true);
|
||||
[NSCursor unhide];
|
||||
[self.delegate openGLViewDidReleaseMouse:self];
|
||||
((CSApplication *)[NSApplication sharedApplication]).keyboardEventDelegate = nil;
|
||||
((CSApplication *)[NSApplication sharedApplication]).eventDelegate = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,7 +295,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
||||
CGAssociateMouseAndMouseCursorPosition(false);
|
||||
[self.delegate openGLViewDidCaptureMouse:self];
|
||||
if(self.shouldUsurpCommand) {
|
||||
((CSApplication *)[NSApplication sharedApplication]).keyboardEventDelegate = self;
|
||||
((CSApplication *)[NSApplication sharedApplication]).eventDelegate = self;
|
||||
}
|
||||
|
||||
// Don't report the first click to the delegate; treat that as merely
|
||||
|
Loading…
Reference in New Issue
Block a user