src/video/cocoa_v.mm
changeset 6247 7d81e3a5d803
parent 6236 3b2905fddbaa
child 6248 e4a2ed7e5613
equal deleted inserted replaced
6246:75451000349d 6247:7d81e3a5d803
    39 extern "C" OSErr CPSGetCurrentProcess(CPSProcessSerNum* psn);
    39 extern "C" OSErr CPSGetCurrentProcess(CPSProcessSerNum* psn);
    40 extern "C" OSErr CPSEnableForegroundOperation(CPSProcessSerNum* psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
    40 extern "C" OSErr CPSEnableForegroundOperation(CPSProcessSerNum* psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
    41 extern "C" OSErr CPSSetFrontProcess(CPSProcessSerNum* psn);
    41 extern "C" OSErr CPSSetFrontProcess(CPSProcessSerNum* psn);
    42 
    42 
    43 /* From Menus.h (according to Xcode Developer Documentation) */
    43 /* From Menus.h (according to Xcode Developer Documentation) */
    44 extern "C" void ShowMenuBar(void);
    44 extern "C" void ShowMenuBar();
    45 extern "C" void HideMenuBar(void);
    45 extern "C" void HideMenuBar();
    46 
    46 
    47 /* Disables a warning. This is needed since the method exists but has been dropped from the header, supposedly as of 10.4. */
    47 /* Disables a warning. This is needed since the method exists but has been dropped from the header, supposedly as of 10.4. */
    48 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
    48 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
    49 @interface NSApplication(NSAppleMenu)
    49 @interface NSApplication(NSAppleMenu)
    50 - (void)setAppleMenu:(NSMenu *)menu;
    50 - (void)setAppleMenu:(NSMenu *)menu;
   124 	_frame = frame;
   124 	_frame = frame;
   125 }
   125 }
   126 @end
   126 @end
   127 
   127 
   128 
   128 
   129 static void QZ_Draw(void);
   129 static void QZ_Draw();
   130 static void QZ_UnsetVideoMode(void);
   130 static void QZ_UnsetVideoMode();
   131 static void QZ_UpdatePalette(uint start, uint count);
   131 static void QZ_UpdatePalette(uint start, uint count);
   132 static void QZ_WarpCursor(int x, int y);
   132 static void QZ_WarpCursor(int x, int y);
   133 static void QZ_ShowMouse(void);
   133 static void QZ_ShowMouse();
   134 static void QZ_HideMouse(void);
   134 static void QZ_HideMouse();
   135 static void CocoaVideoFullScreen(bool full_screen);
   135 static void CocoaVideoFullScreen(bool full_screen);
   136 
   136 
   137 
   137 
   138 static NSAutoreleasePool *_ottd_autorelease_pool;
   138 static NSAutoreleasePool *_ottd_autorelease_pool;
   139 static OTTDMain *_ottd_main;
   139 static OTTDMain *_ottd_main;
   190 
   190 
   191 /******************************************************************************
   191 /******************************************************************************
   192  *                             Game loop and accessories                      *
   192  *                             Game loop and accessories                      *
   193  ******************************************************************************/
   193  ******************************************************************************/
   194 
   194 
   195 static uint32 GetTick(void)
   195 static uint32 GetTick()
   196 {
   196 {
   197 	struct timeval tim;
   197 	struct timeval tim;
   198 
   198 
   199 	gettimeofday(&tim, NULL);
   199 	gettimeofday(&tim, NULL);
   200 	return tim.tv_usec / 1000 + tim.tv_sec * 1000;
   200 	return tim.tv_usec / 1000 + tim.tv_sec * 1000;
   201 }
   201 }
   202 
   202 
   203 static void QZ_CheckPaletteAnim(void)
   203 static void QZ_CheckPaletteAnim()
   204 {
   204 {
   205 	if (_pal_last_dirty != -1) {
   205 	if (_pal_last_dirty != -1) {
   206 		QZ_UpdatePalette(_pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1);
   206 		QZ_UpdatePalette(_pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1);
   207 		_pal_last_dirty = -1;
   207 		_pal_last_dirty = -1;
   208 	}
   208 	}
   467 		return [ _cocoa_video_data.qdview mouse:*pt inRect:[ _cocoa_video_data.qdview bounds ] ];
   467 		return [ _cocoa_video_data.qdview mouse:*pt inRect:[ _cocoa_video_data.qdview bounds ] ];
   468 	}
   468 	}
   469 }
   469 }
   470 
   470 
   471 
   471 
   472 static bool QZ_PollEvent(void)
   472 static bool QZ_PollEvent()
   473 {
   473 {
   474 	NSEvent *event;
   474 	NSEvent *event;
   475 	NSPoint pt;
   475 	NSPoint pt;
   476 	NSString *chars;
   476 	NSString *chars;
   477 #ifdef _DEBUG
   477 #ifdef _DEBUG
   661 
   661 
   662 	return true;
   662 	return true;
   663 }
   663 }
   664 
   664 
   665 
   665 
   666 static void QZ_GameLoop(void)
   666 static void QZ_GameLoop()
   667 {
   667 {
   668 	uint32 cur_ticks = GetTick();
   668 	uint32 cur_ticks = GetTick();
   669 	uint32 next_tick = cur_ticks + 30;
   669 	uint32 next_tick = cur_ticks + 30;
   670 	uint32 pal_tick = 0;
   670 	uint32 pal_tick = 0;
   671 #ifdef _DEBUG
   671 #ifdef _DEBUG
   762 
   762 
   763 /* This function makes the *game region* of the window 100% opaque.
   763 /* This function makes the *game region* of the window 100% opaque.
   764  * The genie effect uses the alpha component. Otherwise,
   764  * The genie effect uses the alpha component. Otherwise,
   765  * it doesn't seem to matter what value it has.
   765  * it doesn't seem to matter what value it has.
   766  */
   766  */
   767 static void QZ_SetPortAlphaOpaque(void)
   767 static void QZ_SetPortAlphaOpaque()
   768 {
   768 {
   769 	if (_cocoa_video_data.device_bpp == 32) {
   769 	if (_cocoa_video_data.device_bpp == 32) {
   770 		uint32* pixels = (uint32*)_cocoa_video_data.realpixels;
   770 		uint32* pixels = (uint32*)_cocoa_video_data.realpixels;
   771 		uint32 rowPixels = _cocoa_video_data.pitch / 4;
   771 		uint32 rowPixels = _cocoa_video_data.pitch / 4;
   772 		uint32 i;
   772 		uint32 i;
  1030 	0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
  1030 	0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
  1031 	0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0,
  1031 	0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0,
  1032 	1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0
  1032 	1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0
  1033 };
  1033 };
  1034 
  1034 
  1035 static void QZ_DrawResizeIcon(void)
  1035 static void QZ_DrawResizeIcon()
  1036 {
  1036 {
  1037 	int xoff = _cocoa_video_data.width - 16;
  1037 	int xoff = _cocoa_video_data.width - 16;
  1038 	int yoff = _cocoa_video_data.height - 16;
  1038 	int yoff = _cocoa_video_data.height - 16;
  1039 	int x;
  1039 	int x;
  1040 	int y;
  1040 	int y;
  1052 			}
  1052 			}
  1053 		}
  1053 		}
  1054 	}
  1054 	}
  1055 }
  1055 }
  1056 
  1056 
  1057 static void QZ_DrawWindow(void)
  1057 static void QZ_DrawWindow()
  1058 {
  1058 {
  1059 	int i;
  1059 	int i;
  1060 	RgnHandle dirty, temp;
  1060 	RgnHandle dirty, temp;
  1061 
  1061 
  1062 	/* Check if we need to do anything */
  1062 	/* Check if we need to do anything */
  1419 
  1419 
  1420 	CGDisplaySetPalette(_cocoa_video_data.display_id, _cocoa_video_data.palette);
  1420 	CGDisplaySetPalette(_cocoa_video_data.display_id, _cocoa_video_data.palette);
  1421 }
  1421 }
  1422 
  1422 
  1423 /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */
  1423 /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */
  1424 static void QZ_WaitForVerticalBlank(void)
  1424 static void QZ_WaitForVerticalBlank()
  1425 {
  1425 {
  1426 	/* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */
  1426 	/* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */
  1427 	double refreshRate;
  1427 	double refreshRate;
  1428 	double linesPerSecond;
  1428 	double linesPerSecond;
  1429 	double target;
  1429 	double target;
  1450 
  1450 
  1451 	CSleep((uint32)(adjustment * 1000));
  1451 	CSleep((uint32)(adjustment * 1000));
  1452 }
  1452 }
  1453 
  1453 
  1454 
  1454 
  1455 static void QZ_DrawScreen(void)
  1455 static void QZ_DrawScreen()
  1456 {
  1456 {
  1457 	const uint8* src = _cocoa_video_data.pixels;
  1457 	const uint8* src = _cocoa_video_data.pixels;
  1458 	uint8* dst       = (uint8*)_cocoa_video_data.realpixels;
  1458 	uint8* dst       = (uint8*)_cocoa_video_data.realpixels;
  1459 	uint pitch       = _cocoa_video_data.pitch;
  1459 	uint pitch       = _cocoa_video_data.pitch;
  1460 	uint width       = _cocoa_video_data.width;
  1460 	uint width       = _cocoa_video_data.width;
  1577 	} else {
  1577 	} else {
  1578 		QZ_UpdateWindowPalette(start, count);
  1578 		QZ_UpdateWindowPalette(start, count);
  1579 	}
  1579 	}
  1580 }
  1580 }
  1581 
  1581 
  1582 static void QZ_InitPalette(void)
  1582 static void QZ_InitPalette()
  1583 {
  1583 {
  1584 	QZ_UpdatePalette(0, 256);
  1584 	QZ_UpdatePalette(0, 256);
  1585 }
  1585 }
  1586 
  1586 
  1587 static void QZ_Draw(void)
  1587 static void QZ_Draw()
  1588 {
  1588 {
  1589 	if (_cocoa_video_data.fullscreen) {
  1589 	if (_cocoa_video_data.fullscreen) {
  1590 		QZ_DrawScreen();
  1590 		QZ_DrawScreen();
  1591 	} else {
  1591 	} else {
  1592 		QZ_DrawWindow();
  1592 		QZ_DrawWindow();
  1606 	{1600, 1200},
  1606 	{1600, 1200},
  1607 	{1680, 1050},
  1607 	{1680, 1050},
  1608 	{1920, 1200}
  1608 	{1920, 1200}
  1609 };
  1609 };
  1610 
  1610 
  1611 static void QZ_UpdateVideoModes(void)
  1611 static void QZ_UpdateVideoModes()
  1612 {
  1612 {
  1613 	uint i, j, count;
  1613 	uint i, j, count;
  1614 	OTTDPoint modes[32];
  1614 	OTTDPoint modes[32];
  1615 	const OTTDPoint *current_modes;
  1615 	const OTTDPoint *current_modes;
  1616 
  1616 
  1634 	}
  1634 	}
  1635 
  1635 
  1636 	_num_resolutions = j;
  1636 	_num_resolutions = j;
  1637 }
  1637 }
  1638 
  1638 
  1639 static void QZ_UnsetVideoMode(void)
  1639 static void QZ_UnsetVideoMode()
  1640 {
  1640 {
  1641 	if (_cocoa_video_data.fullscreen) {
  1641 	if (_cocoa_video_data.fullscreen) {
  1642 		/* Release fullscreen resources */
  1642 		/* Release fullscreen resources */
  1643 		OTTD_QuartzGammaTable gamma_table;
  1643 		OTTD_QuartzGammaTable gamma_table;
  1644 		int gamma_error;
  1644 		int gamma_error;
  1717 	if (ret != NULL && wasset) QZ_SetVideoMode(oldwidth, oldheight, oldfullscreen);
  1717 	if (ret != NULL && wasset) QZ_SetVideoMode(oldwidth, oldheight, oldfullscreen);
  1718 
  1718 
  1719 	return ret;
  1719 	return ret;
  1720 }
  1720 }
  1721 
  1721 
  1722 static void QZ_VideoInit(void)
  1722 static void QZ_VideoInit()
  1723 {
  1723 {
  1724 	memset(&_cocoa_video_data, 0, sizeof(_cocoa_video_data));
  1724 	memset(&_cocoa_video_data, 0, sizeof(_cocoa_video_data));
  1725 
  1725 
  1726 	/* Initialize the video settings; this data persists between mode switches */
  1726 	/* Initialize the video settings; this data persists between mode switches */
  1727 	_cocoa_video_data.display_id = kCGDirectMainDisplay;
  1727 	_cocoa_video_data.display_id = kCGDirectMainDisplay;
  1787 	CGWarpMouseCursorPosition(cgp);
  1787 	CGWarpMouseCursorPosition(cgp);
  1788 
  1788 
  1789 	/* Generate the mouse moved event */
  1789 	/* Generate the mouse moved event */
  1790 }
  1790 }
  1791 
  1791 
  1792 static void QZ_ShowMouse(void)
  1792 static void QZ_ShowMouse()
  1793 {
  1793 {
  1794 	if (!_cocoa_video_data.cursor_visible) {
  1794 	if (!_cocoa_video_data.cursor_visible) {
  1795 		[ NSCursor unhide ];
  1795 		[ NSCursor unhide ];
  1796 		_cocoa_video_data.cursor_visible = true;
  1796 		_cocoa_video_data.cursor_visible = true;
  1797 
  1797 
  1800 			UndrawMouseCursor();
  1800 			UndrawMouseCursor();
  1801 		_cursor.in_window = false;
  1801 		_cursor.in_window = false;
  1802 	}
  1802 	}
  1803 }
  1803 }
  1804 
  1804 
  1805 static void QZ_HideMouse(void)
  1805 static void QZ_HideMouse()
  1806 {
  1806 {
  1807 	if (_cocoa_video_data.cursor_visible) {
  1807 	if (_cocoa_video_data.cursor_visible) {
  1808 #ifndef _DEBUG
  1808 #ifndef _DEBUG
  1809 		[ NSCursor hide ];
  1809 		[ NSCursor hide ];
  1810 #endif
  1810 #endif
  1840 
  1840 
  1841 	return NSTerminateCancel; // NSTerminateLater ?
  1841 	return NSTerminateCancel; // NSTerminateLater ?
  1842 }
  1842 }
  1843 @end
  1843 @end
  1844 
  1844 
  1845 static void setApplicationMenu(void)
  1845 static void setApplicationMenu()
  1846 {
  1846 {
  1847 	/* warning: this code is very odd */
  1847 	/* warning: this code is very odd */
  1848 	NSMenu *appleMenu;
  1848 	NSMenu *appleMenu;
  1849 	NSMenuItem *menuItem;
  1849 	NSMenuItem *menuItem;
  1850 	NSString *title;
  1850 	NSString *title;
  1885 	[appleMenu release];
  1885 	[appleMenu release];
  1886 	[menuItem release];
  1886 	[menuItem release];
  1887 }
  1887 }
  1888 
  1888 
  1889 /* Create a window menu */
  1889 /* Create a window menu */
  1890 static void setupWindowMenu(void)
  1890 static void setupWindowMenu()
  1891 {
  1891 {
  1892 	NSMenu* windowMenu;
  1892 	NSMenu* windowMenu;
  1893 	NSMenuItem* windowMenuItem;
  1893 	NSMenuItem* windowMenuItem;
  1894 	NSMenuItem* menuItem;
  1894 	NSMenuItem* menuItem;
  1895 
  1895 
  1911 	/* Finally give up our references to the objects */
  1911 	/* Finally give up our references to the objects */
  1912 	[windowMenu release];
  1912 	[windowMenu release];
  1913 	[windowMenuItem release];
  1913 	[windowMenuItem release];
  1914 }
  1914 }
  1915 
  1915 
  1916 static void setupApplication(void)
  1916 static void setupApplication()
  1917 {
  1917 {
  1918 	CPSProcessSerNum PSN;
  1918 	CPSProcessSerNum PSN;
  1919 
  1919 
  1920 	/* Ensure the application object is initialised */
  1920 	/* Ensure the application object is initialised */
  1921 	[NSApplication sharedApplication];
  1921 	[NSApplication sharedApplication];
  1940 
  1940 
  1941 /******************************************************************************
  1941 /******************************************************************************
  1942  *                             Video driver interface                         *
  1942  *                             Video driver interface                         *
  1943  ******************************************************************************/
  1943  ******************************************************************************/
  1944 
  1944 
  1945 static void CocoaVideoStop(void)
  1945 static void CocoaVideoStop()
  1946 {
  1946 {
  1947 	if (!_cocoa_video_started) return;
  1947 	if (!_cocoa_video_started) return;
  1948 
  1948 
  1949 	if (_cocoa_video_data.isset) QZ_UnsetVideoMode();
  1949 	if (_cocoa_video_data.isset) QZ_UnsetVideoMode();
  1950 
  1950 
  1984 		_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].bottom = top + height;
  1984 		_cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].bottom = top + height;
  1985 	}
  1985 	}
  1986 	_cocoa_video_data.num_dirty_rects++;
  1986 	_cocoa_video_data.num_dirty_rects++;
  1987 }
  1987 }
  1988 
  1988 
  1989 static void CocoaVideoMainLoop(void)
  1989 static void CocoaVideoMainLoop()
  1990 {
  1990 {
  1991 	/* Start the main event loop */
  1991 	/* Start the main event loop */
  1992 	[NSApp run];
  1992 	[NSApp run];
  1993 }
  1993 }
  1994 
  1994 
  2042 	_cocoa_video_dialog = false;
  2042 	_cocoa_video_dialog = false;
  2043 }
  2043 }
  2044 
  2044 
  2045 
  2045 
  2046 /* This is needed since OS X applications are started with the working dir set to / when double-clicked */
  2046 /* This is needed since OS X applications are started with the working dir set to / when double-clicked */
  2047 void cocoaSetWorkingDirectory(void)
  2047 void cocoaSetWorkingDirectory()
  2048 {
  2048 {
  2049 	char parentdir[MAXPATHLEN];
  2049 	char parentdir[MAXPATHLEN];
  2050 	int chdir_ret;
  2050 	int chdir_ret;
  2051 	CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
  2051 	CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
  2052 	CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
  2052 	CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
  2059 }
  2059 }
  2060 
  2060 
  2061 /* These are called from main() to prevent a _NSAutoreleaseNoPool error when
  2061 /* These are called from main() to prevent a _NSAutoreleaseNoPool error when
  2062  * exiting before the cocoa video driver has been loaded
  2062  * exiting before the cocoa video driver has been loaded
  2063  */
  2063  */
  2064 void cocoaSetupAutoreleasePool(void)
  2064 void cocoaSetupAutoreleasePool()
  2065 {
  2065 {
  2066 	_ottd_autorelease_pool = [[NSAutoreleasePool alloc] init];
  2066 	_ottd_autorelease_pool = [[NSAutoreleasePool alloc] init];
  2067 }
  2067 }
  2068 
  2068 
  2069 void cocoaReleaseAutoreleasePool(void)
  2069 void cocoaReleaseAutoreleasePool()
  2070 {
  2070 {
  2071 	[_ottd_autorelease_pool release];
  2071 	[_ottd_autorelease_pool release];
  2072 }
  2072 }
  2073 
  2073 
  2074 #endif /* WITH_COCOA */
  2074 #endif /* WITH_COCOA */