From 965ce1294726427bf31da33bb5c7650773f8aada Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Wed, 3 Feb 2021 22:43:06 +0100 Subject: [PATCH] Codechange: [OSX] Use newer mouse tracking API. --- src/video/cocoa/cocoa_v.mm | 2 +- src/video/cocoa/cocoa_wnd.h | 16 +----- src/video/cocoa/cocoa_wnd.mm | 101 +++++++++++++---------------------- 3 files changed, 40 insertions(+), 79 deletions(-) diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index ef30519ea6..185f28c84e 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -495,7 +495,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) /* Create wrapper view for text input. */ NSRect view_frame = [ this->window contentRectForFrameRect:[ this->window frame ] ]; - this->cocoaview = [ [ OTTD_CocoaView alloc ] initWithFrame:view_frame andDriver:this ]; + this->cocoaview = [ [ OTTD_CocoaView alloc ] initWithFrame:view_frame ]; if (this->cocoaview == nil) { DEBUG(driver, 0, "Could not create the text wrapper view."); this->setup = false; diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index 744a657861..449b457af1 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -32,20 +32,8 @@ extern NSString *OTTDMainLaunchGameEngine; - (void)appDidUnhide:(NSNotification*)note; @end -/** Subclass of NSView to fix Quartz rendering and mouse awareness */ -@interface OTTD_CocoaView : NSView { - VideoDriver_Cocoa *driver; -} -- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv; - -- (BOOL)acceptsFirstResponder; -- (void)setTrackingRect; -- (void)clearTrackingRect; -- (void)resetCursorRects; -- (void)viewWillMoveToWindow:(NSWindow *)win; -- (void)viewDidMoveToWindow; -- (void)mouseEntered:(NSEvent *)theEvent; -- (void)mouseExited:(NSEvent *)theEvent; +/** Subclass of NSView to support mouse awareness and text input. */ +@interface OTTD_CocoaView : NSView @end /** Delegate for our NSWindow to send ask for quit on close */ diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index ac6d35dd21..8f72836cca 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -112,7 +112,9 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) auto *drv = static_cast(VideoDriver::GetInstance()); /* Setup cursor for the current _game_mode. */ - [ drv->window invalidateCursorRectsForView:[ drv->window contentView ] ]; + NSEvent *e = [ [ NSEvent alloc ] init ]; + [ drv->cocoaview cursorUpdate:e ]; + [ e release ]; /* Hand off to main application code. */ drv->GameLoop(); @@ -329,6 +331,25 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel VideoDriver_Cocoa *driver; } +/** + * Initialize event system for the application rectangle + */ +- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv +{ + if (self = [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]) { + /* Make our window subclass receive these application notifications */ + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; + + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; + + self->driver = drv; + } + + return self; +} + /** * Minimize the window */ @@ -383,38 +404,10 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel { driver->active = true; } -/** - * Initialize event system for the application rectangle - */ -- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv -{ - if (self = [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]) { - /* Make our window subclass receive these application notifications */ - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; - - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; - - self->driver = drv; - } - - return self; -} @end -@implementation OTTD_CocoaView { - NSTrackingRectTag trackingtag; -} - -- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv -{ - if (self = [ super initWithFrame:frameRect ]) { - self->driver = drv; - } - return self; -} +@implementation OTTD_CocoaView /** * Allow to handle events @@ -432,46 +425,26 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel } } -/** - * Define the rectangle where we draw our application window - */ -- (void)setTrackingRect +/** Update mouse cursor to use for this view. */ +- (void)cursorUpdate:(NSEvent *)event { - NSPoint loc = [ self convertPoint:[ [ self window ] mouseLocationOutsideOfEventStream ] fromView:nil ]; - BOOL inside = ([ self hitTest:loc ]==self); - if (inside) [ [ self window ] makeFirstResponder:self ]; - trackingtag = [ self addTrackingRect:[ self visibleRect ] owner:self userData:nil assumeInside:inside ]; + [ (_game_mode == GM_BOOTSTRAP ? [ NSCursor arrowCursor ] : [ NSCursor clearCocoaCursor ]) set ]; } -/** - * Return responsibility for the application window to system - */ -- (void)clearTrackingRect -{ - [ self removeTrackingRect:trackingtag ]; -} -/** - * Declare responsibility for the cursor within our application rect - */ -- (void)resetCursorRects -{ - [ super resetCursorRects ]; - [ self clearTrackingRect ]; - [ self setTrackingRect ]; - [ self addCursorRect:[ self bounds ] cursor:(_game_mode == GM_BOOTSTRAP ? [ NSCursor arrowCursor ] : [ NSCursor clearCocoaCursor ]) ]; -} -/** - * Prepare for moving the application window - */ + - (void)viewWillMoveToWindow:(NSWindow *)win { - if (!win && [ self window ]) [ self clearTrackingRect ]; + for (NSTrackingArea *a in [ self trackingAreas ]) { + [ self removeTrackingArea:a ]; + } } -/** - * Restore our responsibility for our application window after moving - */ + - (void)viewDidMoveToWindow { - if ([ self window ]) [ self setTrackingRect ]; + /* Install mouse tracking area. */ + NSTrackingAreaOptions track_opt = NSTrackingInVisibleRect | NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited | NSTrackingCursorUpdate; + NSTrackingArea *track = [ [ NSTrackingArea alloc ] initWithRect:[ self bounds ] options:track_opt owner:self userInfo:nil ]; + [ self addTrackingArea:track ]; + [ track release ]; } /** * Make OpenTTD aware that it has control over the mouse @@ -485,7 +458,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel */ - (void)mouseExited:(NSEvent *)theEvent { - if (driver->window != nil) UndrawMouseCursor(); + if ([ self window ] != nil) UndrawMouseCursor(); _cursor.in_window = false; }