File diff r7169:b87d36998a2d → r7170:38b143754b40
src/video/cocoa_v.mm
Show inline comments
 
@@ -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));