OpenTTD Source 20260129-master-g2bb01bd0e4
cocoa_v.mm
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD 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, version 2.
4 * OpenTTD 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.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
18#if defined(WITH_COCOA) || defined(DOXYGEN_API)
19
20#include "../../stdafx.h"
21#include "../../os/macosx/macos.h"
22
23#include "../../os/macosx/macos_objective_c.h"
24#include "../../openttd.h"
25#include "../../debug.h"
26#include "../../error_func.h"
27#include "../../core/geometry_func.hpp"
28#include "../../core/math_func.hpp"
29#include "cocoa_v.h"
30#include "cocoa_wnd.h"
31#include "../../blitter/factory.hpp"
32#include "../../framerate_type.h"
33#include "../../gfx_func.h"
34#include "../../thread.h"
35#include "../../core/random_func.hpp"
36#include "../../progress.h"
37#include "../../settings_type.h"
38#include "../../window_func.h"
39#include "../../window_gui.h"
40
41#import <sys/param.h> /* for MAXPATHLEN */
42#import <sys/time.h> /* gettimeofday */
43
46extern bool _tab_is_down;
47
48
51 { 640, 480 },
52 { 800, 600 },
53 { 1024, 768 },
54 { 1152, 864 },
55 { 1280, 800 },
56 { 1280, 960 },
57 { 1280, 1024 },
58 { 1400, 1050 },
59 { 1600, 1200 },
60 { 1680, 1050 },
61 { 1920, 1200 },
62 { 2560, 1440 }
63};
64
65
66VideoDriver_Cocoa::VideoDriver_Cocoa(bool uses_hardware_acceleration)
67 : VideoDriver(uses_hardware_acceleration)
68{
69 this->setup = false;
70 this->buffer_locked = false;
71
72 this->refresh_sys_sprites = true;
73
74 this->window = nil;
75 this->cocoaview = nil;
76 this->delegate = nil;
77
78 this->colour_space = nullptr;
79
80 this->dirty_rect = {};
81}
82
85{
86 if (!_cocoa_video_started) return;
87
89
90 /* Release window mode resources */
91 if (this->window != nil) [ this->window close ];
92 [ this->cocoaview release ];
93 [ this->delegate release ];
94
95 CGColorSpaceRelease(this->colour_space);
96
98}
99
104std::optional<std::string_view> VideoDriver_Cocoa::Initialize()
105{
106 if (_cocoa_video_started) return "Already started";
108
109 /* Don't create a window or enter fullscreen if we're just going to show a dialog. */
110 if (!CocoaSetupApplication()) return std::nullopt;
111
112 this->UpdateAutoResolution();
114
115 return std::nullopt;
116}
117
125void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height)
126{
127 Rect r = {left, top, left + width, top + height};
128 this->dirty_rect = BoundingRect(this->dirty_rect, r);
129}
130
135{
136 /* Restart game loop if it was already running (e.g. after bootstrapping),
137 * otherwise this call is a no-op. */
138 [ [ NSNotificationCenter defaultCenter ] postNotificationName:OTTDMainLaunchGameEngine object:nil ];
139
140 /* Start the main event loop. */
141 [ NSApp run ];
142}
143
151{
152 NSSize screen_size = [ [ NSScreen mainScreen ] frame ].size;
153 w = std::min(w, (int)screen_size.width);
154 h = std::min(h, (int)screen_size.height);
155
156 NSRect contentRect = NSMakeRect(0, 0, w, h);
157 [ this->window setContentSize:contentRect.size ];
158
159 /* Ensure frame height - title bar height >= view height */
160 float content_height = [ this->window contentRectForFrameRect:[ this->window frame ] ].size.height;
161 contentRect.size.height = Clamp(h, 0, (int)content_height);
162
163 if (this->cocoaview != nil) {
164 h = (int)contentRect.size.height;
165 [ this->cocoaview setFrameSize:contentRect.size ];
166 }
167
168 [ (OTTD_CocoaWindow *)this->window center ];
169 this->AllocateBackingStore();
170
171 return true;
172}
173
180{
181 if (this->IsFullscreen() == full_screen) return true;
182
183 if ([ this->window respondsToSelector:@selector(toggleFullScreen:) ]) {
184 [ this->window performSelector:@selector(toggleFullScreen:) withObject:this->window ];
185
186 /* Hide the menu bar and the dock */
187 [ NSMenu setMenuBarVisible:!full_screen ];
188
189 this->UpdateVideoModes();
191 return true;
192 }
193
194 return false;
195}
196
201
203{
204 if (this->refresh_sys_sprites && this->window != nil) {
205 [ this->window refreshSystemSprites ];
206 this->refresh_sys_sprites = false;
207 }
208}
209
215{
216 this->AllocateBackingStore(true);
217 return true;
218}
219
224{
225 [ [ this->cocoaview inputContext ] performSelectorOnMainThread:@selector(discardMarkedText) withObject:nil waitUntilDone:[ NSThread isMainThread ] ];
226 /* Clear any marked string from the current edit box. */
227 HandleTextInput({}, true);
228}
229
235{
236 std::vector<int> rates{};
237
238 std::array<CGDirectDisplayID, 16> displays;
239
240 uint32_t count = 0;
241 CGGetActiveDisplayList(displays.size(), displays.data(), &count);
242
243 for (uint32_t i = 0; i < count; i++) {
244 CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
245 int rate = static_cast<int>(CGDisplayModeGetRefreshRate(mode));
246 if (rate > 0) rates.push_back(rate);
247 CGDisplayModeRelease(mode);
248 }
249
250 return rates;
251}
252
258{
259 NSRect frame = [ [ NSScreen mainScreen ] frame ];
260 return { static_cast<uint>(NSWidth(frame)), static_cast<uint>(NSHeight(frame)) };
261}
262
268{
269 if (this->buffer_locked) return false;
270 this->buffer_locked = true;
271
272 _screen.dst_ptr = this->GetVideoPointer();
273 assert(_screen.dst_ptr != nullptr);
274
275 return true;
276}
277
280{
281 if (_screen.dst_ptr != nullptr) {
282 /* Hand video buffer back to the drawing backend. */
283 this->ReleaseVideoPointer();
284 _screen.dst_ptr = nullptr;
285 }
286
287 this->buffer_locked = false;
288}
289
295{
296 return this->window != nil && ([ this->window styleMask ] & NSWindowStyleMaskFullScreen) != 0;
297}
298
303{
304 /* Store old window size if we entered fullscreen mode. */
305 bool fullscreen = this->IsFullscreen();
306 if (fullscreen && !_fullscreen) this->orig_res = _cur_resolution;
307 _fullscreen = fullscreen;
308
310
312
313 /* We need to store the window size as non-Retina size in
314 * the config file to get same windows size on next start. */
315 _cur_resolution.width = [ this->cocoaview frame ].size.width;
316 _cur_resolution.height = [ this->cocoaview frame ].size.height;
317}
318
323{
324 _resolutions.clear();
325
326 if (this->IsFullscreen()) {
327 /* Full screen, there is only one possible resolution. */
328 NSSize screen = [ [ this->window screen ] frame ].size;
329 _resolutions.emplace_back((uint)screen.width, (uint)screen.height);
330 } else {
331 /* Windowed; offer a selection of common window sizes up until the
332 * maximum usable screen space. This excludes the menu and dock areas. */
333 NSSize maxSize = [ [ NSScreen mainScreen] visibleFrame ].size;
334 for (const auto &d : _default_resolutions) {
335 if (d.width < maxSize.width && d.height < maxSize.height) _resolutions.push_back(d);
336 }
337 _resolutions.emplace_back((uint)maxSize.width, (uint)maxSize.height);
338 }
339}
340
347bool VideoDriver_Cocoa::MakeWindow(int width, int height)
348{
349 this->setup = true;
350
351 /* Limit window size to screen frame. */
352 NSSize screen_size = [ [ NSScreen mainScreen ] frame ].size;
353 if (width > screen_size.width) width = screen_size.width;
354 if (height > screen_size.height) height = screen_size.height;
355
356 NSRect contentRect = NSMakeRect(0, 0, width, height);
357
358 /* Create main window. */
359 unsigned int style = NSWindowStyleMaskTitled | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable;
360 this->window = [ [ OTTD_CocoaWindow alloc ] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:NO driver:this ];
361 if (this->window == nil) {
362 Debug(driver, 0, "Could not create the Cocoa window.");
363 this->setup = false;
364 return false;
365 }
366
367 /* Add built in full-screen support when available (OS X 10.7 and higher)
368 * This code actually compiles for 10.5 and later, but only makes sense in conjunction
369 * with the quartz fullscreen support as found only in 10.7 and later. */
370 if ([ this->window respondsToSelector:@selector(toggleFullScreen:) ]) {
371 NSWindowCollectionBehavior behavior = [ this->window collectionBehavior ];
372 behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
373 [ this->window setCollectionBehavior:behavior ];
374
375 NSButton *fullscreenButton = [ this->window standardWindowButton:NSWindowZoomButton ];
376 [ fullscreenButton setAction:@selector(toggleFullScreen:) ];
377 [ fullscreenButton setTarget:this->window ];
378 }
379
380 this->delegate = [ [ OTTD_CocoaWindowDelegate alloc ] initWithDriver:this ];
381 [ this->window setDelegate:this->delegate ];
382
383 [ this->window center ];
384 [ this->window makeKeyAndOrderFront:nil ];
385
386 /* Create wrapper view for input and event handling. */
387 NSRect view_frame = [ this->window contentRectForFrameRect:[ this->window frame ] ];
388 this->cocoaview = [ [ OTTD_CocoaView alloc ] initWithFrame:view_frame ];
389 if (this->cocoaview == nil) {
390 Debug(driver, 0, "Could not create the event wrapper view.");
391 this->setup = false;
392 return false;
393 }
394 [ this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ];
395
396 /* Create content view. */
397 NSView *draw_view = this->AllocateDrawView();
398 if (draw_view == nil) {
399 Debug(driver, 0, "Could not create the drawing view.");
400 this->setup = false;
401 return false;
402 }
403 [ draw_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ];
404
405 /* Create view chain: window -> input wrapper view -> content view. */
406 [ this->window setContentView:this->cocoaview ];
407 [ this->cocoaview addSubview:draw_view ];
408 [ this->window makeFirstResponder:this->cocoaview ];
409 [ draw_view release ];
410
411 [ this->window setColorSpace:[ NSColorSpace sRGBColorSpace ] ];
412 CGColorSpaceRelease(this->colour_space);
413 this->colour_space = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
414 if (this->colour_space == nullptr) this->colour_space = CGColorSpaceCreateDeviceRGB();
415 if (this->colour_space == nullptr) FatalError("Could not get a valid colour space for drawing.");
416
417 this->setup = false;
418
419 return true;
420}
421
422
428{
429 NSEventMask mask = NSEventMaskAny;
430 NSEvent *event = [ NSApp nextEventMatchingMask:mask untilDate:[ NSDate distantPast ] inMode:NSDefaultRunLoopMode dequeue:YES ];
431
432 if (event == nil) return false;
433
434 [ NSApp sendEvent:event ];
435
436 return true;
437}
438
440{
441 NSUInteger cur_mods = [ NSEvent modifierFlags ];
442
443 bool old_ctrl_pressed = _ctrl_pressed;
444
445 _ctrl_pressed = (cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSEventModifierFlagControl : NSEventModifierFlagCommand)) != 0;
446 _shift_pressed = (cur_mods & NSEventModifierFlagShift) != 0;
447
449
450 if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
451}
452
455{
456 this->StartGameThread();
457
458 for (;;) {
459 @autoreleasepool {
460 if (_exit_game) {
461 /* Restore saved resolution if in fullscreen mode. */
462 if (this->IsFullscreen()) _cur_resolution = this->orig_res;
463 break;
464 }
465
466 this->Tick();
467 this->SleepTillNextTick();
468 }
469 }
470
471 this->StopGameThread();
472}
473
474
476@interface OTTD_QuartzView : NSView {
478}
479- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_CocoaQuartz *)drv;
480@end
481
482@implementation OTTD_QuartzView
483
490- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_CocoaQuartz *)drv
491{
492 if (self = [ super initWithFrame:frameRect ]) {
493 self->driver = drv;
494
495 /* We manage our content updates ourselves. */
496 self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
497 self.wantsLayer = YES;
498
499 self.layer.magnificationFilter = kCAFilterNearest;
500 self.layer.opaque = YES;
501 }
502 return self;
503}
504
510{
511 return NO;
512}
513
518- (BOOL)isOpaque
519{
520 return YES;
521}
522
527- (BOOL)wantsUpdateLayer
528{
529 return YES;
530}
531
533- (void)updateLayer
534{
535 if (driver->cgcontext == nullptr) return;
536
537 /* Set layer contents to our backing buffer, which avoids needless copying. */
538 CGImageRef fullImage = CGBitmapContextCreateImage(driver->cgcontext);
539 self.layer.contents = (__bridge id)fullImage;
540 CGImageRelease(fullImage);
541}
542
545{
546 [ super viewDidChangeBackingProperties ];
547
548 self.layer.contentsScale = [ driver->cocoaview getContentsScale ];
549}
550
551@end
552
555
562static void ClearWindowBuffer(uint32_t *buffer, uint32_t pitch, uint32_t height)
563{
564 uint32_t fill = Colour(0, 0, 0).data;
565 for (uint32_t y = 0; y < height; y++) {
566 for (uint32_t x = 0; x < pitch; x++) {
567 buffer[y * pitch + x] = fill;
568 }
569 }
570}
571
572VideoDriver_CocoaQuartz::VideoDriver_CocoaQuartz()
573{
574 this->window_width = 0;
575 this->window_height = 0;
576 this->window_pitch = 0;
577 this->buffer_depth = 0;
578 this->window_buffer = nullptr;
579 this->pixel_buffer = nullptr;
580
581 this->cgcontext = nullptr;
582}
583
584std::optional<std::string_view> VideoDriver_CocoaQuartz::Start(const StringList &param)
585{
586 auto err = this->Initialize();
587 if (err) return err;
588
590 if (bpp != 8 && bpp != 32) {
591 Stop();
592 return "The cocoa quartz subdriver only supports 8 and 32 bpp.";
593 }
594
595 bool fullscreen = _fullscreen;
596 if (!this->MakeWindow(_cur_resolution.width, _cur_resolution.height)) {
597 Stop();
598 return "Could not create window";
599 }
600
601 this->AllocateBackingStore(true);
602
603 if (fullscreen) this->ToggleFullscreen(fullscreen);
604
605 this->GameSizeChanged();
606 this->UpdateVideoModes();
607
608 this->is_game_threaded = !GetDriverParamBool(param, "no_threads") && !GetDriverParamBool(param, "no_thread");
609
610 return std::nullopt;
611
612}
613
615{
617
618 CGContextRelease(this->cgcontext);
619
620 this->window_buffer.reset();
621 this->pixel_buffer.reset();
622}
623
624NSView *VideoDriver_CocoaQuartz::AllocateDrawView()
625{
626 return [ [ OTTD_QuartzView alloc ] initWithFrame:[ this->cocoaview bounds ] andDriver:this ];
627}
628
633void VideoDriver_CocoaQuartz::AllocateBackingStore([[maybe_unused]] bool force)
634{
635 if (this->window == nil || this->cocoaview == nil || this->setup) return;
636
637 this->UpdatePalette(0, 256);
638
639 NSRect newframe = [ this->cocoaview getRealRect:[ this->cocoaview frame ] ];
640
641 this->window_width = (int)newframe.size.width;
642 this->window_height = (int)newframe.size.height;
643 this->window_pitch = Align(this->window_width, 16 / sizeof(uint32_t)); // Quartz likes lines that are multiple of 16-byte.
645
646 /* Create Core Graphics Context */
647 this->window_buffer = std::make_unique<uint32_t[]>(this->window_pitch * this->window_height);
648 /* Initialize with opaque black. */
649 ClearWindowBuffer(this->window_buffer.get(), this->window_pitch, this->window_height);
650
651 CGContextRelease(this->cgcontext);
652 this->cgcontext = CGBitmapContextCreate(
653 this->window_buffer.get(), // data
654 this->window_width, // width
655 this->window_height, // height
656 8, // bits per component
657 this->window_pitch * 4, // bytes per row
658 this->colour_space, // colour space
659 kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host
660 );
661
662 assert(this->cgcontext != nullptr);
663 CGContextSetShouldAntialias(this->cgcontext, FALSE);
664 CGContextSetAllowsAntialiasing(this->cgcontext, FALSE);
665 CGContextSetInterpolationQuality(this->cgcontext, kCGInterpolationNone);
666
667 if (this->buffer_depth == 8) {
668 this->pixel_buffer = std::make_unique<uint8_t[]>(this->window_width * this->window_height);
669 } else {
670 this->pixel_buffer.reset();
671 }
672
673 /* Tell the game that the resolution has changed */
674 _screen.width = this->window_width;
675 _screen.height = this->window_height;
676 _screen.pitch = this->buffer_depth == 8 ? this->window_width : this->window_pitch;
677 _screen.dst_ptr = this->GetVideoPointer();
678
679 /* Redraw screen */
680 this->MakeDirty(0, 0, _screen.width, _screen.height);
681 this->GameSizeChanged();
682}
683
692void VideoDriver_CocoaQuartz::BlitIndexedToView32(int left, int top, int right, int bottom)
693{
694 const uint32_t *pal = this->palette;
695 const uint8_t *src = this->pixel_buffer.get();
696 uint32_t *dst = this->window_buffer.get();
697 uint width = this->window_width;
698 uint pitch = this->window_pitch;
699
700 for (int y = top; y < bottom; y++) {
701 for (int x = left; x < right; x++) {
702 dst[y * pitch + x] = pal[src[y * width + x]];
703 }
704 }
705}
706
712void VideoDriver_CocoaQuartz::UpdatePalette(uint first_colour, uint num_colours)
713{
714 if (this->buffer_depth != 8) return;
715
716 for (uint i = first_colour; i < first_colour + num_colours; i++) {
717 uint32_t clr = 0xff000000;
718 clr |= (uint32_t)_local_palette.palette[i].r << 16;
719 clr |= (uint32_t)_local_palette.palette[i].g << 8;
720 clr |= (uint32_t)_local_palette.palette[i].b;
721 this->palette[i] = clr;
722 }
723
724 this->MakeDirty(0, 0, _screen.width, _screen.height);
725}
726
728{
729 if (!CopyPalette(_local_palette)) return;
730
732
733 switch (blitter->UsePaletteAnimation()) {
736 break;
737
740 break;
741
743 break;
744
745 default:
746 NOT_REACHED();
747 }
748}
749
752{
754
755 /* Check if we need to do anything */
756 if (IsEmptyRect(this->dirty_rect) || [ this->window isMiniaturized ]) return;
757
758 /* We only need to blit in indexed mode since in 32bpp mode the game draws directly to the image. */
759 if (this->buffer_depth == 8) {
761 this->dirty_rect.left,
762 this->dirty_rect.top,
763 this->dirty_rect.right,
764 this->dirty_rect.bottom
765 );
766 }
767
768 NSRect dirtyrect;
769 dirtyrect.origin.x = this->dirty_rect.left;
770 dirtyrect.origin.y = this->window_height - this->dirty_rect.bottom;
771 dirtyrect.size.width = this->dirty_rect.right - this->dirty_rect.left;
772 dirtyrect.size.height = this->dirty_rect.bottom - this->dirty_rect.top;
773
774 /* Notify OS X that we have new content to show. */
775 [ this->cocoaview setNeedsDisplayInRect:[ this->cocoaview getVirtualRect:dirtyrect ] ];
776
777 /* Tell the OS to get our contents to screen as soon as possible. */
778 [ CATransaction flush ];
779
780 this->dirty_rect = {};
781}
782
783#endif /* WITH_COCOA or DOXYGEN_API */
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition factory.hpp:136
How all blitters should look like.
Definition base.hpp:29
virtual uint8_t GetScreenDepth()=0
Get the screen depth this blitter works for.
virtual Blitter::PaletteAnimation UsePaletteAnimation()=0
Check if the blitter uses palette animation at all.
virtual void PaletteAnimate(const Palette &palette)=0
Called when the 8bpp palette is changed; you should redraw all pixels on the screen that are equal to...
@ None
No palette animation.
@ Blitter
The blitter takes care of the palette animation.
@ VideoBackend
Palette animation should be done by video backend (8bpp only!)
virtual void PostResize()
Post resize event.
Definition base.hpp:205
RAII class for measuring simple elements of performance.
std::optional< std::string_view > Start(const StringList &param) override
Start this driver.
Definition cocoa_v.mm:584
CGContextRef cgcontext
Context reference for Quartz subdriver.
Definition cocoa_v.h:107
uint32_t palette[256]
Colour Palette.
Definition cocoa_v.h:101
int buffer_depth
Colour depth of used frame buffer.
Definition cocoa_v.h:93
int window_width
Current window width in pixel.
Definition cocoa_v.h:97
void CheckPaletteAnim() override
Process any pending palette animation.
Definition cocoa_v.mm:727
std::unique_ptr< uint32_t[]> window_buffer
Colour translation from palette to screen.
Definition cocoa_v.h:95
void AllocateBackingStore(bool force=false) override
Resize the window.
Definition cocoa_v.mm:633
void BlitIndexedToView32(int left, int top, int right, int bottom)
This function copies 8bpp pixels from the screen buffer in 32bpp windowed mode.
Definition cocoa_v.mm:692
std::unique_ptr< uint8_t[]> pixel_buffer
used for direct pixel access
Definition cocoa_v.h:94
void UpdatePalette(uint first_colour, uint num_colours)
Update the palette.
Definition cocoa_v.mm:712
void Stop() override
Stop Cocoa video driver.
Definition cocoa_v.mm:614
void Paint() override
Draw window.
Definition cocoa_v.mm:751
void * GetVideoPointer() override
Get a pointer to the video buffer.
Definition cocoa_v.h:125
int window_height
Current window height in pixel.
Definition cocoa_v.h:98
void GameSizeChanged()
Handle a change of the display area.
Definition cocoa_v.mm:302
bool ToggleFullscreen(bool fullscreen) override
Toggle between windowed and full screen mode for cocoa display driver.
Definition cocoa_v.mm:179
void UpdateVideoModes()
Update the video mode.
Definition cocoa_v.mm:322
std::vector< int > GetListOfMonitorRefreshRates() override
Get refresh rates of all connected monitors.
Definition cocoa_v.mm:234
Dimension GetScreenSize() const override
Get the resolution of the main screen.
Definition cocoa_v.mm:257
std::optional< std::string_view > Initialize()
Common driver initialization.
Definition cocoa_v.mm:104
bool refresh_sys_sprites
System sprites need refreshing.
Definition cocoa_v.h:26
void MainLoop() override
Start the main programme loop when using a cocoa video driver.
Definition cocoa_v.mm:134
OTTD_CocoaWindow * window
Pointer to window object.
Definition cocoa_v.h:31
OTTD_CocoaView * cocoaview
Pointer to view object.
Definition cocoa_v.h:32
virtual void ReleaseVideoPointer()
Hand video buffer back to the drawing backend.
Definition cocoa_v.h:85
virtual void * GetVideoPointer()=0
Get a pointer to the video buffer.
OTTD_CocoaWindowDelegate * delegate
Window delegate object.
Definition cocoa_v.h:35
bool IsFullscreen()
Are we in fullscreen mode?
Definition cocoa_v.mm:294
void InputLoop() override
Handle input logic, is CTRL pressed, should we fast-forward, etc.
Definition cocoa_v.mm:439
bool MakeWindow(int width, int height)
Build window and view with a given size.
Definition cocoa_v.mm:347
bool PollEvent() override
Poll and handle a single event from the OS.
Definition cocoa_v.mm:427
void MakeDirty(int left, int top, int width, int height) override
Set dirty a rectangle managed by a cocoa video subdriver.
Definition cocoa_v.mm:125
void PopulateSystemSprites() override
Populate all sprites in cache.
Definition cocoa_v.mm:202
bool LockVideoBuffer() override
Lock video buffer for drawing if it isn't already mapped.
Definition cocoa_v.mm:267
void EditBoxLostFocus() override
An edit box lost the input focus.
Definition cocoa_v.mm:223
void ClearSystemSprites() override
Clear all cached sprites.
Definition cocoa_v.mm:197
Rect dirty_rect
Region of the screen that needs redrawing.
Definition cocoa_v.h:63
void UnlockVideoBuffer() override
Unlock video buffer.
Definition cocoa_v.mm:279
void Stop() override
Stop Cocoa video driver.
Definition cocoa_v.mm:84
bool buffer_locked
Video buffer was locked by the main thread.
Definition cocoa_v.h:64
Dimension orig_res
Saved window size for non-fullscreen mode.
Definition cocoa_v.h:25
bool setup
Window is currently being created.
Definition cocoa_v.h:29
bool ChangeResolution(int w, int h) override
Change the resolution when using a cocoa video driver.
Definition cocoa_v.mm:150
bool AfterBlitterChange() override
Callback invoked after the blitter was changed.
Definition cocoa_v.mm:214
CGColorSpaceRef colour_space
Window colour space.
Definition cocoa_v.h:33
void MainLoopReal()
Main game loop.
Definition cocoa_v.mm:454
The base of all video drivers.
bool fast_forward_key_pressed
The fast-forward key is being pressed.
void Tick()
Give the video-driver a tick.
void SleepTillNextTick()
Sleep till the next tick is about to happen.
void StartGameThread()
Start the loop for game-tick.
void StopGameThread()
Stop the loop for the game-tick.
void UpdateAutoResolution()
Apply resolution auto-detection and clamp to sensible defaults.
static Palette _local_palette
Current palette to use for drawing.
Definition cocoa_ogl.mm:42
The Cocoa video driver.
bool _cocoa_video_started
Is the Cocoa video driver running.
Definition cocoa_v.mm:44
static FVideoDriver_CocoaQuartz iFVideoDriver_CocoaQuartz
Register the cocoa video driver.
Definition cocoa_v.mm:554
static Palette _local_palette
Current palette to use for drawing.
Definition cocoa_v.mm:45
bool _cocoa_video_started
Is the Cocoa video driver running.
Definition cocoa_v.mm:44
static const Dimension _default_resolutions[]
List of common display/window sizes.
Definition cocoa_v.mm:50
static void ClearWindowBuffer(uint32_t *buffer, uint32_t pitch, uint32_t height)
Clear buffer to opaque black.
Definition cocoa_v.mm:562
bool _tab_is_down
Is tab button pressed.
Definition cocoa_wnd.mm:77
OS interface for the cocoa video driver.
bool CocoaSetupApplication()
Startup the application.
Definition cocoa_wnd.mm:328
void CocoaExitApplication()
Deregister app delegate.
Definition cocoa_wnd.mm:364
NSString * OTTDMainLaunchGameEngine
Name of notification observer used to restart the game loop if necessary.
Definition cocoa_wnd.mm:75
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
bool GetDriverParamBool(const StringList &parm, std::string_view name)
Get a boolean parameter the list of parameters.
Definition driver.cpp:67
std::vector< Dimension > _resolutions
List of resolutions.
Definition driver.cpp:28
Dimension _cur_resolution
The current resolution.
Definition driver.cpp:29
@ PFE_VIDEO
Speed of painting drawn video buffer.
Rect BoundingRect(const Rect &r1, const Rect &r2)
Compute the bounding rectangle around two rectangles.
bool IsEmptyRect(const Rect &r)
Check if a rectangle is empty.
bool _shift_pressed
Is Shift pressed?
Definition gfx.cpp:39
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
void HandleCtrlChanged()
State of CONTROL key has changed.
Definition window.cpp:2708
void HandleTextInput(std::string_view str, bool marked=false, std::optional< size_t > caret=std::nullopt, std::optional< size_t > insert_location=std::nullopt, std::optional< size_t > replacement_end=std::nullopt)
Handle text input.
Definition window.cpp:2738
Subclass of NSView to support mouse awareness and text input.
Definition cocoa_wnd.h:43
Delegate for our NSWindow to send ask for quit on close.
Definition cocoa_wnd.h:51
Subclass of NSWindow to cater our special needs.
Definition cocoa_wnd.h:33
Subclass of OTTD_CocoaView to fix Quartz rendering.
Definition cocoa_v.mm:476
BOOL isOpaque()
Specifies whether the view is opaque.
Definition cocoa_v.mm:518
void updateLayer()
Updates the layer based on driver data.
Definition cocoa_v.mm:533
BOOL wantsUpdateLayer()
Specifies whether the view wants updates for layer.
Definition cocoa_v.mm:527
BOOL acceptsFirstResponder()
Specifies whether the view accepts first responder.
Definition cocoa_v.mm:509
VideoDriver_CocoaQuartz * driver
The driver to fix rendering for.
Definition cocoa_v.mm:477
void viewDidChangeBackingProperties()
Updates members with new values after changes in driver.
Definition cocoa_v.mm:544
constexpr T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
Definition math_func.hpp:37
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
bool CopyPalette(Palette &local_palette, bool force_copy)
Copy the current palette if the palette was updated.
Definition palette.cpp:225
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
std::vector< std::string > StringList
Type for a list of strings.
Definition string_type.h:60
GUISettings gui
settings related to the GUI
Dimensions (a width and height) of a rectangle in 2D.
uint8_t right_mouse_btn_emulation
should we emulate right mouse clicking?
Information about the currently used palette.
Definition gfx_type.h:373
int first_dirty
The first dirty element.
Definition gfx_type.h:375
int count_dirty
The number of dirty elements.
Definition gfx_type.h:376
Colour palette[256]
Current palette. Entry 0 has to be always fully transparent!
Definition gfx_type.h:374
Specification of a rectangle with absolute coordinates of all edges.
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition window.cpp:3318
@ WC_GAME_OPTIONS
Game options window; Window numbers: