summaryrefslogtreecommitdiff
path: root/src/video
diff options
context:
space:
mode:
authorMichael Lutz <michi@icosahedron.de>2021-01-31 18:58:23 +0100
committerMichael Lutz <michi@icosahedron.de>2021-02-13 22:21:17 +0100
commit42af13c141eb74f63e58827f8a33e7f66d7d829a (patch)
treed8c3862cfefa10991ad315608d6003026926867d /src/video
parent60f30036f1338b6fba8a0c23d7a8b70eab697644 (diff)
downloadopenttd-42af13c141eb74f63e58827f8a33e7f66d7d829a.tar.xz
Codechange: [OSX] Split drawing into its own subview.
This allows the drawing backend code to be independent of any event or command handling.
Diffstat (limited to 'src/video')
-rw-r--r--src/video/cocoa/cocoa_v.mm53
-rw-r--r--src/video/cocoa/cocoa_wnd.h19
-rw-r--r--src/video/cocoa/cocoa_wnd.mm157
3 files changed, 125 insertions, 104 deletions
diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm
index 7f1e10bfe..ef30519ea 100644
--- a/src/video/cocoa/cocoa_v.mm
+++ b/src/video/cocoa/cocoa_v.mm
@@ -77,7 +77,11 @@ static FVideoDriver_Cocoa iFVideoDriver_Cocoa;
/* Subclass of OTTD_CocoaView to fix Quartz rendering */
-@interface OTTD_QuartzView : OTTD_CocoaView
+@interface OTTD_QuartzView : NSView {
+ VideoDriver_Cocoa *driver;
+}
+- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv;
+
- (void)drawRect:(NSRect)invalidRect;
@end
@@ -311,6 +315,28 @@ void VideoDriver_Cocoa::GameSizeChanged()
@implementation OTTD_QuartzView
+- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv
+{
+ if (self = [ super initWithFrame:frameRect ]) {
+ self->driver = drv;
+ }
+ return self;
+}
+
+- (BOOL)acceptsFirstResponder
+{
+ return NO;
+}
+
+/**
+ * Define the opaqueness of the window / screen
+ * @return opaqueness of window / screen
+ */
+- (BOOL)isOpaque
+{
+ return YES;
+}
+
- (void)drawRect:(NSRect)invalidRect
{
if (driver->cgcontext == NULL) return;
@@ -429,13 +455,12 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height)
/* Create main window. */
unsigned int style = NSTitledWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask;
- this->window = [ [ OTTD_CocoaWindow alloc ] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:NO ];
+ this->window = [ [ OTTD_CocoaWindow alloc ] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:NO driver:this ];
if (this->window == nil) {
DEBUG(driver, 0, "Could not create the Cocoa window.");
this->setup = false;
return false;
}
- [ this->window setDriver:this ];
/* Add built in full-screen support when available (OS X 10.7 and higher)
* This code actually compiles for 10.5 and later, but only makes sense in conjunction
@@ -468,16 +493,28 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height)
[ (OTTD_CocoaWindow *)this->window center ];
[ this->window makeKeyAndOrderFront:nil ];
- /* Create content view. */
- this->cocoaview = [ [ OTTD_QuartzView alloc ] initWithFrame:[ this->window contentRectForFrameRect:[ this->window frame ] ] andDriver:this ];
+ /* 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 ];
if (this->cocoaview == nil) {
- DEBUG(driver, 0, "Could not create the Quartz view.");
+ DEBUG(driver, 0, "Could not create the text wrapper view.");
+ this->setup = false;
+ return false;
+ }
+ [ (NSView *)this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ];
+
+ /* Create content view. */
+ NSView *draw_view = [ [ OTTD_QuartzView alloc ] initWithFrame:[ this->cocoaview bounds ] andDriver:this ];
+ if (draw_view == nil) {
+ DEBUG(driver, 0, "Could not create the drawing view.");
this->setup = false;
return false;
}
+ [ draw_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ];
- [ (NSView*)this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ];
- [ this->window setContentView:cocoaview ];
+ [ this->window setContentView:this->cocoaview ];
+ [ this->cocoaview addSubview:draw_view ];
+ [ draw_view release ];
[ this->window setColorSpace:[ NSColorSpace sRGBColorSpace ] ];
CGColorSpaceRelease(this->color_space);
diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h
index 96834d904..744a65786 100644
--- a/src/video/cocoa/cocoa_wnd.h
+++ b/src/video/cocoa/cocoa_wnd.h
@@ -22,31 +22,23 @@ extern NSString *OTTDMainLaunchGameEngine;
@end
/** Subclass of NSWindow to cater our special needs */
-@interface OTTD_CocoaWindow : NSWindow {
- VideoDriver_Cocoa *driver;
-}
-
-- (void)setDriver:(VideoDriver_Cocoa *)drv;
+@interface OTTD_CocoaWindow : NSWindow
+- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv;
- (void)miniaturize:(id)sender;
- (void)display;
- (void)setFrame:(NSRect)frameRect display:(BOOL)flag;
- (void)appDidHide:(NSNotification*)note;
- (void)appDidUnhide:(NSNotification*)note;
-- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag;
@end
/** Subclass of NSView to fix Quartz rendering and mouse awareness */
-@interface OTTD_CocoaView : NSView <NSTextInputClient>
-{
+@interface OTTD_CocoaView : NSView <NSTextInputClient> {
VideoDriver_Cocoa *driver;
- NSTrackingRectTag trackingtag;
}
- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv;
-- (void)drawRect:(NSRect)rect;
-- (BOOL)isOpaque;
+
- (BOOL)acceptsFirstResponder;
-- (BOOL)becomeFirstResponder;
- (void)setTrackingRect;
- (void)clearTrackingRect;
- (void)resetCursorRects;
@@ -58,9 +50,6 @@ extern NSString *OTTDMainLaunchGameEngine;
/** Delegate for our NSWindow to send ask for quit on close */
@interface OTTD_CocoaWindowDelegate : NSObject <NSWindowDelegate>
-{
- VideoDriver_Cocoa *driver;
-}
- (instancetype)initWithDriver:(VideoDriver_Cocoa *)drv;
- (BOOL)windowShouldClose:(id)sender;
diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm
index e7c916443..ac6d35dd2 100644
--- a/src/video/cocoa/cocoa_wnd.mm
+++ b/src/video/cocoa/cocoa_wnd.mm
@@ -48,6 +48,46 @@ NSString *OTTDMainLaunchGameEngine = @"ottdmain_launch_game_engine";
static bool _cocoa_video_dialog = false;
static OTTDMain *_ottd_main;
+
+/**
+ * Count the number of UTF-16 code points in a range of an UTF-8 string.
+ * @param from Start of the range.
+ * @param to End of the range.
+ * @return Number of UTF-16 code points in the range.
+ */
+static NSUInteger CountUtf16Units(const char *from, const char *to)
+{
+ NSUInteger i = 0;
+
+ while (from < to) {
+ WChar c;
+ size_t len = Utf8Decode(&c, from);
+ i += len < 4 ? 1 : 2; // Watch for surrogate pairs.
+ from += len;
+ }
+
+ return i;
+}
+
+/**
+ * Advance an UTF-8 string by a number of equivalent UTF-16 code points.
+ * @param str UTF-8 string.
+ * @param count Number of UTF-16 code points to advance the string by.
+ * @return Advanced string pointer.
+ */
+static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
+{
+ for (NSUInteger i = 0; i < count && *str != '\0'; ) {
+ WChar c;
+ size_t len = Utf8Decode(&c, str);
+ i += len < 4 ? 1 : 2; // Watch for surrogates.
+ str += len;
+ }
+
+ return str;
+}
+
+
/**
* The main class of the application, the application's delegate.
*/
@@ -69,11 +109,13 @@ static OTTDMain *_ottd_main;
*/
- (void)launchGameEngine: (NSNotification*) note
{
+ auto *drv = static_cast<VideoDriver_Cocoa *>(VideoDriver::GetInstance());
+
/* Setup cursor for the current _game_mode. */
- [ static_cast<VideoDriver_Cocoa *>(VideoDriver::GetInstance())->cocoaview resetCursorRects ];
+ [ drv->window invalidateCursorRectsForView:[ drv->window contentView ] ];
/* Hand off to main application code. */
- static_cast<VideoDriver_Cocoa *>(VideoDriver::GetInstance())->GameLoop();
+ drv->GameLoop();
/* We are done, thank you for playing. */
[ self performSelectorOnMainThread:@selector(stopEngine) withObject:nil waitUntilDone:FALSE ];
@@ -283,12 +325,10 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel
}
@end
-@implementation OTTD_CocoaWindow
-
-- (void)setDriver:(VideoDriver_Cocoa *)drv
-{
- driver = drv;
+@implementation OTTD_CocoaWindow {
+ VideoDriver_Cocoa *driver;
}
+
/**
* Minimize the window
*/
@@ -346,62 +386,28 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel
/**
* Initialize event system for the application rectangle
*/
-- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag
+- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv
{
- /* 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 ];
+ 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 ];
- return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ];
-}
+ [ [ NSNotificationCenter defaultCenter ] addObserver:self
+ selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ];
-@end
-
-
-
-/**
- * Count the number of UTF-16 code points in a range of an UTF-8 string.
- * @param from Start of the range.
- * @param to End of the range.
- * @return Number of UTF-16 code points in the range.
- */
-static NSUInteger CountUtf16Units(const char *from, const char *to)
-{
- NSUInteger i = 0;
-
- while (from < to) {
- WChar c;
- size_t len = Utf8Decode(&c, from);
- i += len < 4 ? 1 : 2; // Watch for surrogate pairs.
- from += len;
+ self->driver = drv;
}
- return i;
+ return self;
}
-/**
- * Advance an UTF-8 string by a number of equivalent UTF-16 code points.
- * @param str UTF-8 string.
- * @param count Number of UTF-16 code points to advance the string by.
- * @return Advanced string pointer.
- */
-static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
-{
- for (NSUInteger i = 0; i < count && *str != '\0'; ) {
- WChar c;
- size_t len = Utf8Decode(&c, str);
- i += len < 4 ? 1 : 2; // Watch for surrogates.
- str += len;
- }
+@end
- return str;
+@implementation OTTD_CocoaView {
+ NSTrackingRectTag trackingtag;
}
-@implementation OTTD_CocoaView
-
- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv
{
if (self = [ super initWithFrame:frameRect ]) {
@@ -409,22 +415,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
}
return self;
}
-/**
- * Define the opaqueness of the window / screen
- * @return opaqueness of window / screen
- */
-- (BOOL)isOpaque
-{
- return YES;
-}
-/**
- * Draws a rectangle on the screen.
- * It's overwritten by the individual drivers but must be defined
- */
-- (void)drawRect:(NSRect)invalidRect
-{
- return;
-}
+
/**
* Allow to handle events
*/
@@ -432,13 +423,15 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
{
return YES;
}
-/**
- * Actually handle events
- */
-- (BOOL)becomeFirstResponder
+
+- (void)setNeedsDisplayInRect:(NSRect)invalidRect
{
- return YES;
+ /* Drawing is handled by our sub-views. Just pass it along. */
+ for ( NSView *v in [ self subviews ]) {
+ [ v setNeedsDisplayInRect:[ v convertRect:invalidRect fromView:self ] ];
+ }
}
+
/**
* Define the rectangle where we draw our application window
*/
@@ -556,7 +549,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
/** Unmark the current marked text. */
- (void)unmarkText
{
- HandleTextInput(NULL, true);
+ HandleTextInput(nullptr, true);
}
/** Get the caret position. */
@@ -575,7 +568,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
size_t mark_len;
const char *mark = _focused_window->GetMarkedText(&mark_len);
- if (mark != NULL) {
+ if (mark != nullptr) {
NSUInteger start = CountUtf16Units(_focused_window->GetFocusedText(), mark);
NSUInteger len = CountUtf16Units(mark, mark + mark_len);
@@ -591,7 +584,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
if (!EditBoxInGlobalFocus()) return NO;
size_t len;
- return _focused_window->GetMarkedText(&len) != NULL;
+ return _focused_window->GetMarkedText(&len) != nullptr;
}
/** Get a string corresponding to the given range. */
@@ -602,7 +595,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
NSString *s = [ NSString stringWithUTF8String:_focused_window->GetFocusedText() ];
NSRange valid_range = NSIntersectionRange(NSMakeRange(0, [ s length ]), theRange);
- if (actualRange != NULL) *actualRange = valid_range;
+ if (actualRange != nullptr) *actualRange = valid_range;
if (valid_range.length == 0) return nil;
return [ [ [ NSAttributedString alloc ] initWithString:[ s substringWithRange:valid_range ] ] autorelease ];
@@ -611,7 +604,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
/** Get a string corresponding to the given range. */
- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
{
- return [ self attributedSubstringForProposedRange:theRange actualRange:NULL ];
+ return [ self attributedSubstringForProposedRange:theRange actualRange:nil ];
}
/** Get the current edit box string. */
@@ -632,7 +625,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
Point pt = { (int)view_pt.x, (int)[ self frame ].size.height - (int)view_pt.y };
const char *ch = _focused_window->GetTextCharacterAtPosition(pt);
- if (ch == NULL) return NSNotFound;
+ if (ch == nullptr) return NSNotFound;
return CountUtf16Units(_focused_window->GetFocusedText(), ch);
}
@@ -808,8 +801,10 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count)
@end
+@implementation OTTD_CocoaWindowDelegate {
+ VideoDriver_Cocoa *driver;
+}
-@implementation OTTD_CocoaWindowDelegate
/** Initialize the video driver */
- (instancetype)initWithDriver:(VideoDriver_Cocoa *)drv
{