1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-16 11:23:51 +00:00

Merge pull request #655 from TomHarte/EventProtocol

Rationalises protocol for application-level event theft.
This commit is contained in:
Thomas Harte 2019-09-24 22:32:22 -04:00 committed by GitHub
commit 48f4d8b875
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 65 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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