|
@@ -56,28 +56,30 @@ extern "C" void HideMenuBar();
|
|
|
#undef ALIGN
|
|
|
/* Defined in stdbool.h */
|
|
|
#ifndef __cplusplus
|
|
|
# ifndef __BEOS__
|
|
|
# undef bool
|
|
|
# undef false
|
|
|
# undef true
|
|
|
# endif
|
|
|
#endif
|
|
|
|
|
|
|
|
|
#include "../stdafx.h"
|
|
|
#include "../openttd.h"
|
|
|
#include "../debug.h"
|
|
|
#include "../macros.h"
|
|
|
#include "../os/macosx/splash.h"
|
|
|
#include "../variables.h"
|
|
|
#include "../gfx.h"
|
|
|
#include "cocoa_v.h"
|
|
|
#include "cocoa_keys.h"
|
|
|
#include "../blitter/factory.hpp"
|
|
|
#include "../fileio.h"
|
|
|
|
|
|
#undef Point
|
|
|
#undef Rect
|
|
|
|
|
|
/* Subclass of NSWindow to fix genie effect and support resize events */
|
|
|
@interface OTTD_QuartzWindow : NSWindow
|
|
|
- (void)miniaturize:(id)sender;
|
|
|
- (void)display;
|
|
@@ -122,32 +124,31 @@ struct OTTD_QuartzGammaTable {
|
|
|
{
|
|
|
_frame = frame;
|
|
|
}
|
|
|
@end
|
|
|
|
|
|
|
|
|
static void QZ_Draw();
|
|
|
static void QZ_UnsetVideoMode();
|
|
|
static void QZ_UpdatePalette(uint start, uint count);
|
|
|
static void QZ_WarpCursor(int x, int y);
|
|
|
static void QZ_ShowMouse();
|
|
|
static void QZ_HideMouse();
|
|
|
static void CocoaVideoFullScreen(bool full_screen);
|
|
|
|
|
|
|
|
|
static NSAutoreleasePool *_ottd_autorelease_pool;
|
|
|
static OTTDMain *_ottd_main;
|
|
|
|
|
|
|
|
|
static struct CocoaVideoData {
|
|
|
static struct VideoDriver_Cocoa::Data {
|
|
|
bool isset;
|
|
|
bool issetting;
|
|
|
|
|
|
CGDirectDisplayID display_id; /* 0 == main display (only support single display) */
|
|
|
CFDictionaryRef mode; /* current mode of the display */
|
|
|
CFDictionaryRef save_mode; /* original mode of the display */
|
|
|
CFArrayRef mode_list; /* list of available fullscreen modes */
|
|
|
CGDirectPaletteRef palette; /* palette of an 8-bit display */
|
|
|
|
|
|
uint32 device_width;
|
|
|
uint32 device_height;
|
|
|
uint32 device_bpp;
|
|
@@ -357,25 +358,25 @@ static void QZ_KeyEvent(unsigned short k
|
|
|
{
|
|
|
switch (keycode) {
|
|
|
case QZ_UP: SB(_dirkeys, 1, 1, down); break;
|
|
|
case QZ_DOWN: SB(_dirkeys, 3, 1, down); break;
|
|
|
case QZ_LEFT: SB(_dirkeys, 0, 1, down); break;
|
|
|
case QZ_RIGHT: SB(_dirkeys, 2, 1, down); break;
|
|
|
|
|
|
case QZ_TAB: _cocoa_video_data.tab_is_down = down; break;
|
|
|
|
|
|
case QZ_RETURN:
|
|
|
case QZ_f:
|
|
|
if (down && (_cocoa_video_data.current_mods & NSCommandKeyMask)) {
|
|
|
CocoaVideoFullScreen(!_fullscreen);
|
|
|
_video_driver->ToggleFullscreen(!_fullscreen);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (down) {
|
|
|
uint32 pressed_key = QZ_MapKey(keycode) | unicode;
|
|
|
HandleKeypress(pressed_key);
|
|
|
DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), down, mapping: %x", keycode, unicode, pressed_key);
|
|
|
} else {
|
|
|
DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), up", keycode, unicode);
|
|
|
}
|
|
|
}
|
|
@@ -1310,27 +1311,27 @@ static uint32 QZ_FadeGammaIn(const OTTD_
|
|
|
redTable, greenTable, blueTable
|
|
|
) != CGDisplayNoErr) {
|
|
|
CGDisplayRestoreColorSyncSettings();
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
CSleep(10);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
static const char* QZ_SetVideoFullScreen(int width, int height)
|
|
|
static const char* QZ_SetVideoToggleFullscreen(int width, int height)
|
|
|
{
|
|
|
const char* errstr = "QZ_SetVideoFullScreen error";
|
|
|
const char* errstr = "QZ_SetVideoToggleFullscreen error";
|
|
|
int exact_match;
|
|
|
CFNumberRef number;
|
|
|
int bpp;
|
|
|
int gamma_error;
|
|
|
OTTD_QuartzGammaTable gamma_table;
|
|
|
NSRect screen_rect;
|
|
|
CGError error;
|
|
|
NSPoint pt;
|
|
|
|
|
|
/* Destroy any previous mode */
|
|
|
if (_cocoa_video_data.isset) QZ_UnsetVideoMode();
|
|
|
|
|
@@ -1698,25 +1699,25 @@ static void QZ_UnsetVideoMode()
|
|
|
|
|
|
QZ_ShowMouse();
|
|
|
}
|
|
|
|
|
|
|
|
|
static const char* QZ_SetVideoMode(uint width, uint height, bool fullscreen)
|
|
|
{
|
|
|
const char *ret;
|
|
|
|
|
|
_cocoa_video_data.issetting = true;
|
|
|
if (fullscreen) {
|
|
|
/* Setup full screen video */
|
|
|
ret = QZ_SetVideoFullScreen(width, height);
|
|
|
ret = QZ_SetVideoToggleFullscreen(width, height);
|
|
|
} else {
|
|
|
/* Setup windowed video */
|
|
|
ret = QZ_SetVideoWindowed(width, height);
|
|
|
}
|
|
|
_cocoa_video_data.issetting = false;
|
|
|
if (ret != NULL) return ret;
|
|
|
|
|
|
/* Signal successful completion (used internally) */
|
|
|
_cocoa_video_data.isset = true;
|
|
|
|
|
|
/* Tell the game that the resolution has changed */
|
|
|
_screen.width = _cocoa_video_data.width;
|
|
@@ -1961,120 +1962,113 @@ static void setupApplication()
|
|
|
setupWindowMenu();
|
|
|
|
|
|
/* Create OTTDMain and make it the app delegate */
|
|
|
_ottd_main = [[OTTDMain alloc] init];
|
|
|
[NSApp setDelegate:_ottd_main];
|
|
|
}
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
* Video driver interface *
|
|
|
******************************************************************************/
|
|
|
|
|
|
static void CocoaVideoStop()
|
|
|
static FVideoDriver_Cocoa iFVideoDriver_Cocoa;
|
|
|
|
|
|
void VideoDriver_Cocoa::Stop()
|
|
|
{
|
|
|
if (!_cocoa_video_started) return;
|
|
|
|
|
|
if (_cocoa_video_data.isset) QZ_UnsetVideoMode();
|
|
|
|
|
|
[_ottd_main release];
|
|
|
|
|
|
_cocoa_video_started = false;
|
|
|
}
|
|
|
|
|
|
static const char *CocoaVideoStart(const char * const *parm)
|
|
|
const char *VideoDriver_Cocoa::Start(const char * const *parm)
|
|
|
{
|
|
|
const char *ret;
|
|
|
|
|
|
if (_cocoa_video_started) return "Already started";
|
|
|
_cocoa_video_started = true;
|
|
|
|
|
|
memset(&_cocoa_video_data, 0, sizeof(_cocoa_video_data));
|
|
|
|
|
|
setupApplication();
|
|
|
|
|
|
/* Don't create a window or enter fullscreen if we're just going to show a dialog. */
|
|
|
if (_cocoa_video_dialog) return NULL;
|
|
|
|
|
|
QZ_VideoInit();
|
|
|
|
|
|
ret = QZ_SetVideoMode(_cur_resolution[0], _cur_resolution[1], _fullscreen);
|
|
|
if (ret != NULL) CocoaVideoStop();
|
|
|
if (ret != NULL) VideoDriver_Cocoa::Stop();
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
static void CocoaVideoMakeDirty(int left, int top, int width, int height)
|
|
|
void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height)
|
|
|
{
|
|
|
if (_cocoa_video_data.num_dirty_rects < MAX_DIRTY_RECTS) {
|
|
|
_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].left = left;
|
|
|
_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].top = top;
|
|
|
_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].right = left + width;
|
|
|
_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].bottom = top + height;
|
|
|
}
|
|
|
_cocoa_video_data.num_dirty_rects++;
|
|
|
}
|
|
|
|
|
|
static void CocoaVideoMainLoop()
|
|
|
void VideoDriver_Cocoa::MainLoop()
|
|
|
{
|
|
|
/* Start the main event loop */
|
|
|
[NSApp run];
|
|
|
}
|
|
|
|
|
|
static bool CocoaVideoChangeRes(int w, int h)
|
|
|
bool VideoDriver_Cocoa::ChangeResolution(int w, int h)
|
|
|
{
|
|
|
const char *ret = QZ_SetVideoModeAndRestoreOnFailure((uint)w, (uint)h, _cocoa_video_data.fullscreen);
|
|
|
if (ret != NULL) {
|
|
|
DEBUG(driver, 0, "cocoa_v: CocoaVideoChangeRes failed with message: %s", ret);
|
|
|
DEBUG(driver, 0, "cocoa_v: VideoDriver_Cocoa::ChangeResolution failed with message: %s", ret);
|
|
|
}
|
|
|
|
|
|
return ret == NULL;
|
|
|
}
|
|
|
|
|
|
static void CocoaVideoFullScreen(bool full_screen)
|
|
|
void VideoDriver_Cocoa::ToggleFullscreen(bool full_screen)
|
|
|
{
|
|
|
const char *ret = QZ_SetVideoModeAndRestoreOnFailure(_cocoa_video_data.width, _cocoa_video_data.height, full_screen);
|
|
|
if (ret != NULL) {
|
|
|
DEBUG(driver, 0, "cocoa_v: CocoaVideoFullScreen failed with message: %s", ret);
|
|
|
DEBUG(driver, 0, "cocoa_v: VideoDriver_Cocoa::ToggleFullscreen failed with message: %s", ret);
|
|
|
}
|
|
|
|
|
|
_fullscreen = _cocoa_video_data.fullscreen;
|
|
|
}
|
|
|
|
|
|
const HalVideoDriver _cocoa_video_driver = {
|
|
|
CocoaVideoStart,
|
|
|
CocoaVideoStop,
|
|
|
CocoaVideoMakeDirty,
|
|
|
CocoaVideoMainLoop,
|
|
|
CocoaVideoChangeRes,
|
|
|
CocoaVideoFullScreen,
|
|
|
};
|
|
|
|
|
|
|
|
|
/* This is needed since sometimes assert is called before the videodriver is initialized */
|
|
|
void CocoaDialog(const char* title, const char* message, const char* buttonLabel)
|
|
|
{
|
|
|
bool wasstarted;
|
|
|
|
|
|
_cocoa_video_dialog = true;
|
|
|
|
|
|
wasstarted = _cocoa_video_started;
|
|
|
if (!_cocoa_video_started && CocoaVideoStart(NULL) != NULL) {
|
|
|
if (!_cocoa_video_started && VideoDriver_Cocoa::Start(NULL) != NULL) {
|
|
|
fprintf(stderr, "%s: %s\n", title, message);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
NSRunAlertPanel([NSString stringWithCString: title], [NSString stringWithCString: message], [NSString stringWithCString: buttonLabel], nil, nil);
|
|
|
|
|
|
if (!wasstarted) CocoaVideoStop();
|
|
|
if (!wasstarted) VideoDriver_Cocoa::Stop();
|
|
|
|
|
|
_cocoa_video_dialog = false;
|
|
|
}
|
|
|
|
|
|
/* This is needed since OS X application bundles do not have a
|
|
|
* current directory and the data files are 'somewhere' in the bundle */
|
|
|
void cocoaSetApplicationBundleDir()
|
|
|
{
|
|
|
char tmp[MAXPATHLEN];
|
|
|
CFURLRef url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
|
|
|
if (CFURLGetFileSystemRepresentation(url, true, (unsigned char*)tmp, MAXPATHLEN)) {
|
|
|
AppendPathSeparator(tmp, lengthof(tmp));
|