55#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
56#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
58HRESULT WINAPI DwmSetWindowAttribute (HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
60#define USE_UNDOCUMENTED_DARKMODE_API 1
62#if USE_UNDOCUMENTED_DARKMODE_API
63#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
64#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
66typedef DWORD(WINAPI* pfnSetPreferredAppMode)(DWORD appMode);
78@interface MyOpenGLView (OOPrivate)
81- (void) setWindowBorderless:(BOOL)borderless;
82- (void) handleStringInput: (SDL_KeyboardEvent *) kbd_event keyID:(Uint16)key_id;
87+ (NSMutableDictionary *) getNativeSize
89 NSMutableDictionary *
mode=[[NSMutableDictionary alloc] init];
90 int nativeDisplayWidth = 1024;
91 int nativeDisplayHeight = 768;
94 SDL_SysWMinfo dpyInfo;
95 SDL_VERSION(&dpyInfo.version);
96 if(SDL_GetWMInfo(&dpyInfo))
98 nativeDisplayWidth = DisplayWidth(dpyInfo.info.x11.display, 0);
99 nativeDisplayHeight = DisplayHeight(dpyInfo.info.x11.display, 0);
100 OOLog(
@"display.mode.list.native",
@"X11 native resolution detected: %d x %d", nativeDisplayWidth, nativeDisplayHeight);
104 OOLog(
@"display.mode.list.native.failed",
@"%@",
@"SDL_GetWMInfo failed, defaulting to 1024x768 for native size");
107 nativeDisplayWidth = GetSystemMetrics(SM_CXSCREEN);
108 nativeDisplayHeight = GetSystemMetrics(SM_CYSCREEN);
109 OOLog(
@"display.mode.list.native",
@"Windows native resolution detected: %d x %d", nativeDisplayWidth, nativeDisplayHeight);
111 OOLog(
@"display.mode.list.native.unknown",
@"Unknown architecture, defaulting to 1024x768");
113 [mode
setValue: [NSNumber numberWithInt: nativeDisplayWidth]
forKey:kOODisplayWidth];
114 [mode
setValue: [NSNumber numberWithInt: nativeDisplayHeight]
forKey: kOODisplayHeight];
115 [mode
setValue: [NSNumber numberWithInt: 0]
forKey: kOODisplayRefreshRate];
121- (void) createSurface
124 const int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL | SDL_RESIZABLE;
126 if (showSplashScreen)
130 NSSize tmp = currentWindowSize;
131 ShowWindow(SDL_Window,SW_SHOWMINIMIZED);
135 surface = SDL_SetVideoMode(firstScreen.width, firstScreen.height, 32, videoModeFlags);
138 currentWindowSize=tmp;
141 surface = SDL_SetVideoMode(8, 8, 32, videoModeFlags);
152 surface = SDL_SetVideoMode(firstScreen.width, firstScreen.height, 32, videoModeFlags);
157 [
self initialiseGLWithSize: firstScreen];
161 if (SDL_SetGamma(_gamma, _gamma, _gamma) < 0 )
163 char * errStr = SDL_GetError();
164 OOLogWARN(
@"gamma.set.failed",
@"Could not set gamma: %s", errStr);
169 SDL_EnableUNICODE(1);
178 SDL_Surface *icon=NULL;
180 NSString *cmdLineArgsStr =
@"Startup command: ";
184 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
185 showSplashScreen = [prefs oo_boolForKey:@"splash-screen" defaultValue:YES];
186 BOOL vSyncPreference = [prefs oo_boolForKey:@"v-sync" defaultValue:YES];
187 int bitsPerColorComponent = [prefs oo_boolForKey:@"hdr" defaultValue:NO] ? 16 : 8;
190 NSArray *arguments =
nil;
191 NSEnumerator *argEnum =
nil;
193 BOOL noSplashArgFound = NO;
195 [
self initKeyMappingData];
200 arguments = [[NSProcessInfo processInfo] arguments];
204 for (argEnum = [arguments objectEnumerator]; (arg = [argEnum nextObject]); )
206 if ([arg isEqual:
@"-nosplash"] || [arg isEqual:
@"--nosplash"])
208 showSplashScreen = NO;
209 noSplashArgFound = YES;
211 else if (([arg isEqual:
@"-splash"] || [arg isEqual:
@"--splash"]) && !noSplashArgFound)
213 showSplashScreen = YES;
217 if ([arg isEqual:
@"-novsync"] || [arg isEqual:
@"--novsync"]) vSyncPreference = NO;
219 if ([arg isEqual:
@"-hdr"]) bitsPerColorComponent = 16;
222 cmdLineArgsStr = [cmdLineArgsStr stringByAppendingFormat:@"%@ ", arg];
225 OOLog(
@"process.args",
@"%@", cmdLineArgsStr);
231 OOLog(
@"sdl.init",
@"%@",
@"initialising SDL");
232 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
234 OOLog(
@"sdl.init.failed",
@"Unable to init SDL: %s\n", SDL_GetError());
239 SDL_putenv (
"SDL_VIDEO_WINDOW_POS=center");
245 if (![
OOSound isSoundOK])
OOLog(
@"sound.init",
@"%@",
@"Sound system disabled.");
248 static char windowCaption[128];
249 NSString *versionString = [NSString stringWithFormat:@"Oolite v%@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]];
251 strcpy (windowCaption, [versionString UTF8String]);
252 strcat (windowCaption,
" - "__DATE__);
253 SDL_WM_SetCaption (windowCaption,
"Oolite");
257 SDL_EventState (SDL_SYSWMEVENT, SDL_ENABLE);
260 static SDL_SysWMinfo wInfo;
261 SDL_VERSION(&wInfo.version);
262 SDL_GetWMInfo(&wInfo);
263 SDL_Window = wInfo.window;
266 if (![
self getCurrentMonitorInfo:&monitorInfo])
268 OOLogWARN(
@"display.initGL.monitorInfoWarning",
@"Could not get current monitor information.");
271 atDesktopResolution = YES;
273#if USE_UNDOCUMENTED_DARKMODE_API
275 HMODULE hUxTheme = LoadLibraryExW(L
"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
279 pfnSetPreferredAppMode SetPreferredAppMode = (pfnSetPreferredAppMode)GetProcAddress(hUxTheme, MAKEINTRESOURCEA(135));
280 if (SetPreferredAppMode) SetPreferredAppMode(AllowDark);
281 FreeLibrary(hUxTheme);
286 grabMouseStatus = NO;
288 imagesDir = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Images"];
289 icon = SDL_LoadBMP([[imagesDir stringByAppendingPathComponent:
@"WMicon.bmp"] UTF8String]);
293 colorkey = SDL_MapRGB(icon->format, 128, 0, 128);
294 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, colorkey);
295 SDL_WM_SetIcon(icon, NULL);
297 SDL_FreeSurface(icon);
299 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, bitsPerColorComponent);
300 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, bitsPerColorComponent);
301 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, bitsPerColorComponent);
302 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, bitsPerColorComponent);
303 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
304 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
306 _colorSaturation = 1.0f;
310 _hdrMaxBrightness = [prefs oo_floatForKey:@"hdr-max-brightness" defaultValue:1000.0f];
311 _hdrPaperWhiteBrightness = [prefs oo_floatForKey:@"hdr-paperwhite-brightness" defaultValue:200.0f];
312 if (bitsPerColorComponent == 16)
315 SDL_GL_SetAttribute(SDL_GL_PIXEL_TYPE_FLOAT, 1);
321 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vSyncPreference);
322 OOLog(
@"display.initGL",
@"V-Sync %@requested.", vSyncPreference ?
@"" :
@"not ");
331 if ([prefs oo_boolForKey:
@"anti-aliasing" defaultValue:NO])
333 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
334 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
337 OOLog(
@"display.mode.list",
@"%@",
@"CREATING MODE LIST");
338 [
self populateFullScreenModelist];
343 [
self loadFullscreenSettings];
344 [
self loadWindowSize];
347 firstScreen= (fullScreen) ? [
self modeAsSize: currentSize] : currentWindowSize;
348 viewSize = firstScreen;
350 OOLog(
@"display.initGL",
@"Trying %d-bpcc, 24-bit depth buffer", bitsPerColorComponent);
351 [
self createSurface];
356 OOLog(
@"display.initGL",
@"%@",
@"Trying 8-bpcc, 32-bit depth buffer");
357 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
358 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
359 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
360 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
361 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
362 [
self createSurface];
368 OOLog(
@"display.initGL",
@"%@",
@"Trying 5-bpcc, 16-bit depth buffer");
369 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
370 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
371 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
372 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
374 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
375 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
377 [
self createSurface];
381 char * errStr = SDL_GetError();
382 OOLogERR(
@"display.mode.error",
@"Could not create display surface: %s", errStr);
384 if (showSplashScreen)
386 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"splash-screen"];
387 [[NSUserDefaults standardUserDefaults] synchronize];
388 OOLogWARN(
@"display.mode.conflict",
@"Possible incompatibility between the splash screen and video drivers detected.");
389 OOLogWARN(
@"display.mode.conflict",
@"Oolite will start without showing the splash screen from now on. Override with 'oolite.exe -splash'");
398 OOLog(
@"display.initGL",
@"%@",
@"Achieved color / depth buffer sizes (bits):");
399 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &testAttrib);
400 OOLog(
@"display.initGL",
@"Red: %d", testAttrib);
401 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &testAttrib);
402 OOLog(
@"display.initGL",
@"Green: %d", testAttrib);
403 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &testAttrib);
404 OOLog(
@"display.initGL",
@"Blue: %d", testAttrib);
405 SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &testAttrib);
406 OOLog(
@"display.initGL",
@"Alpha: %d", testAttrib);
407 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &testAttrib);
408 OOLog(
@"display.initGL",
@"Depth Buffer: %d", testAttrib);
410 SDL_GL_GetAttribute(SDL_GL_PIXEL_TYPE_FLOAT, &testAttrib);
411 OOLog(
@"display.initGL",
@"Pixel type is float : %d", testAttrib);
413 OOLog(
@"display.initGL",
@"Pixel format index: %d", GetPixelFormat(GetDC(SDL_Window)));
417 if (vSyncPreference && SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &vSyncValue) == -1)
419 OOLogWARN(
@"display.initGL",
@"Could not enable V-Sync. Please check that your graphics driver supports the %@_swap_control extension.",
423 bounds.size.width = surface->w;
424 bounds.size.height = surface->h;
426 [
self autoShowMouse];
428 virtualJoystickPosition = NSMakePoint(0.0,0.0);
431 _mouseVirtualStickSensitivityFactor = OOClamp_0_1_f([prefs oo_floatForKey:
@"mouse-flight-sensitivity" defaultValue:0.95f]);
433 if (_mouseVirtualStickSensitivityFactor < 0.005f) _mouseVirtualStickSensitivityFactor = 0.005f;
435 typedString = [[NSMutableString alloc] initWithString:@""];
437 isAlphabetKeyDown = NO;
439 timeIntervalAtLastClick = timeSinceLastMouseWheel = [NSDate timeIntervalSinceReferenceDate];
441 _mouseWheelDelta = 0.0f;
443 m_glContextInitialized = NO;
448- (void) endSplashScreen
451 if ([
self hdrOutput] && ![
self isOutputDisplayHDREnabled])
453 if (MessageBox(NULL,
"No primary display in HDR mode was detected.\n\n"
454 "If you continue, graphics will not be rendered as intended.\n"
455 "Click OK to launch anyway, or Cancel to exit.",
"oolite.exe - HDR requested",
456 MB_OKCANCEL | MB_ICONWARNING) == IDCANCEL)
463 if (!showSplashScreen)
return;
467 wasFullScreen = !fullScreen;
469 ShowWindow(SDL_Window,SW_RESTORE);
470 [
self initialiseGLWithSize: firstScreen];
474 int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL;
476 videoModeFlags |= (fullScreen) ? SDL_FULLSCREEN : SDL_RESIZABLE;
477 surface = SDL_SetVideoMode(firstScreen.width, firstScreen.height, 32, videoModeFlags);
479 if (!surface && fullScreen == YES)
481 [
self setFullScreenMode: NO];
482 videoModeFlags &= ~SDL_FULLSCREEN;
483 videoModeFlags |= SDL_RESIZABLE;
484 surface = SDL_SetVideoMode(currentWindowSize.width, currentWindowSize.height, 32, videoModeFlags);
487 SDL_putenv (
"SDL_VIDEO_WINDOW_POS=none");
496 SDL_Event dummyEvent;
497 while (SDL_PollEvent(&dummyEvent))
509 [
self autoShowMouse];
513- (void) initKeyMappingData
515 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
523 NSString *kbd = [prefs oo_stringForKey:@"keyboard-code" defaultValue:@"default"];
524 NSDictionary *subset = [kmap objectForKey:kbd];
526 [keyMappings_normal release];
527 keyMappings_normal = [[subset objectForKey:@"mapping_normal"] copy];
528 [keyMappings_shifted release];
529 keyMappings_shifted = [[subset objectForKey:@"mapping_shifted"] copy];
536 [typedString release];
539 [screenSizes release];
543 SDL_FreeSurface(surface);
547 if (keyMappings_normal)
548 [keyMappings_normal release];
550 if (keyMappings_shifted)
551 [keyMappings_shifted release];
557 [matrixManager release];
563- (void) autoShowMouse
568 if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE)
569 SDL_ShowCursor(SDL_DISABLE);
573 if (SDL_ShowCursor(SDL_QUERY) == SDL_DISABLE)
574 SDL_ShowCursor(SDL_ENABLE);
580 allowingStringInput = value;
584- (void) allowStringInput: (BOOL) value
594 return allowingStringInput;
598- (NSString *) typedString
604- (void) resetTypedString
606 [typedString setString:@""];
610- (void) setTypedString:(NSString*) value
612 [typedString setString:value];
628- (NSSize) backingViewSize
654 return gameController;
660 gameController = controller;
666 [
self autoShowMouse];
667 [
self setMouseInDeltaMode:OOMouseInteractionModeIsFlightMode(newMode)];
671- (BOOL) inFullScreenMode
677- (void) setFullScreenMode:(BOOL)fsm
682 [[NSUserDefaults standardUserDefaults]
683 setBool: fullScreen forKey:@"fullscreen"];
684 [[NSUserDefaults standardUserDefaults] synchronize];
688- (void) toggleScreenMode
690 [
self setFullScreenMode: !fullScreen];
692 [
self getCurrentMonitorInfo:&monitorInfo];
697 if(![
self isRunningOnPrimaryDisplayDevice])
699 [
self initialiseGLWithSize:NSMakeSize(monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
700 monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top)];
702 else [
self initialiseGLWithSize:[
self modeAsSize: currentSize]];
704 [
self initialiseGLWithSize:[
self modeAsSize: currentSize]];
708 [
self initialiseGLWithSize: currentWindowSize];
719- (void) setDisplayMode:(
int)mode fullScreen:(BOOL)fsm
721 [
self setFullScreenMode: fsm];
724 [
self initialiseGLWithSize: [
self modeAsSize: mode]];
728- (
int) indexOfCurrentSize
734- (void) setScreenSize: (
int)sizeIndex
736 currentSize=sizeIndex;
738 [
self initialiseGLWithSize: [
self modeAsSize: currentSize]];
742- (NSMutableArray *)getScreenSizeArray
748- (NSSize) modeAsSize:(
int)sizeIndex
750 NSDictionary *
mode=[screenSizes objectAtIndex: sizeIndex];
764 [
self drawRect: NSMakeRect(0, 0, viewSize.width, viewSize.height)];
767- (void) drawRect:(NSRect)rect
769 [
self updateScreenWithVideoMode:YES];
772- (void) updateScreenWithVideoMode:(BOOL) v_mode
774 if ((viewSize.width != surface->w)||(viewSize.height != surface->h))
777 m_glContextInitialized = NO;
779 viewSize.width = surface->w;
780 viewSize.height = surface->h;
783 if (m_glContextInitialized == NO)
785 [
self initialiseGLWithSize:viewSize useVideoMode:v_mode];
793 if (
UNIVERSE) [UNIVERSE drawUniverse];
797 glClearColor( 0.0, 0.0, 0.0, 0.0);
798 glClear( GL_COLOR_BUFFER_BIT);
801 SDL_GL_SwapBuffers();
804- (void) initSplashScreen
806 if (!showSplashScreen)
return;
809 SDL_Surface *image=NULL;
812 NSString *imagesDir = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Images"];
814 image = SDL_LoadBMP([[imagesDir stringByAppendingPathComponent:
@"splash.bmp"] UTF8String]);
818 SDL_FreeSurface(image);
819 OOLogWARN(
@"sdl.gameStart",
@"%@",
@"image 'splash.bmp' not found!");
820 [
self endSplashScreen];
831 dest.x = (GetSystemMetrics(SM_CXSCREEN)- dest.w)/2;
832 dest.y = (GetSystemMetrics(SM_CYSCREEN)-dest.h)/2;
833 SetWindowLong(SDL_Window,GWL_STYLE,GetWindowLong(SDL_Window,GWL_STYLE) & ~WS_CAPTION & ~WS_THICKFRAME);
834 ShowWindow(SDL_Window,SW_RESTORE);
835 MoveWindow(SDL_Window,dest.x,dest.y,dest.w,dest.h,TRUE);
847 surface = SDL_SetVideoMode(dest.w, dest.h, 32, SDL_HWSURFACE | SDL_OPENGL);
853 glViewport( 0, 0, dest.w, dest.h);
855 glEnable( GL_TEXTURE_2D );
856 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
857 glClear( GL_COLOR_BUFFER_BIT );
859 [matrixManager resetProjection];
860 [matrixManager orthoLeft: 0.0f right: dest.w bottom: dest.h top: 0.0 near: -1.0 far: 1.0];
861 [matrixManager syncProjection];
863 [matrixManager resetModelView];
864 [matrixManager syncModelView];
867 GLenum texture_format;
871 nOfColors = image->format->BytesPerPixel;
874 if (image->format->Rmask == 0x000000ff)
875 texture_format = GL_RGBA;
877 texture_format = GL_BGRA;
879 else if (nOfColors == 3)
881 if (image->format->Rmask == 0x000000ff)
882 texture_format = GL_RGB;
884 texture_format = GL_BGR;
886 SDL_FreeSurface(image);
887 OOLog(
@"Sdl.GameStart",
@"%@",
@"----- Encoding error within image 'splash.bmp'");
888 [
self endSplashScreen];
892 glGenTextures( 1, &texture );
893 glBindTexture( GL_TEXTURE_2D, texture );
896 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
897 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
900 glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, image->w, image->h, 0,
901 texture_format, GL_UNSIGNED_BYTE, image->pixels );
903 glBindTexture( GL_TEXTURE_2D, texture );
906 glTexCoord2i( 0, 0 );
908 glTexCoord2i( 1, 0 );
909 glVertex2i( dest.w, 0 );
910 glTexCoord2i( 1, 1 );
911 glVertex2i( dest.w, dest.h );
912 glTexCoord2i( 0, 1 );
913 glVertex2i( 0, dest.h );
917 SDL_GL_SwapBuffers();
918 [matrixManager resetModelView];
919 [matrixManager syncModelView];
922 SDL_FreeSurface( image );
924 glDeleteTextures(1, &texture);
926 glDisable( GL_TEXTURE_2D );
932- (MONITORINFOEX) currentMonitorInfo
938- (BOOL) getCurrentMonitorInfo:(MONITORINFOEX *)mInfo
940 HMONITOR hMon = MonitorFromWindow(SDL_Window, MONITOR_DEFAULTTOPRIMARY);
941 ZeroMemory(mInfo,
sizeof(MONITORINFOEX));
942 mInfo->cbSize =
sizeof(MONITORINFOEX);
943 if (GetMonitorInfo (hMon, (LPMONITORINFO)mInfo))
951- (BOOL) isRunningOnPrimaryDisplayDevice
954 [
self getCurrentMonitorInfo:&monitorInfo];
955 if (!(monitorInfo.dwFlags & MONITORINFOF_PRIMARY))
963- (void) grabMouseInsideGameWindow:(BOOL) value
968 GetWindowRect(SDL_Window, &gameWindowRect);
969 ClipCursor(&gameWindowRect);
975 grabMouseStatus = !!value;
979- (void) stringToClipboard:(NSString *)stringToCopy
983 const char *clipboardText = [stringToCopy cStringUsingEncoding:NSUTF8StringEncoding];
984 const size_t clipboardTextLength = strlen(clipboardText) + 1;
985 HGLOBAL clipboardMem = GlobalAlloc(GMEM_MOVEABLE, clipboardTextLength);
988 memcpy(GlobalLock(clipboardMem), clipboardText, clipboardTextLength);
989 GlobalUnlock(clipboardMem);
992 if (!SetClipboardData(CF_TEXT, clipboardMem))
994 OOLog(
@"stringToClipboard.failed",
@"Failed to copy string %@ to clipboard", stringToCopy);
999 GlobalFree(clipboardMem);
1011 SDLMod modState = SDL_GetModState();
1012 Uint8 *keyState = SDL_GetKeyState(NULL);
1013 BYTE keyboardStatus[256];
1014 #define OO_RESET_SDLKEY_MODIFIER(vkCode, kModCode, sdlkCode) do {\
1015 if (keyboardStatus[vkCode] & 0x0080) \
1017 modState |= kModCode; \
1018 keyState[sdlkCode] = SDL_PRESSED; \
1022 modState &= ~kModCode; \
1023 keyState[sdlkCode] = SDL_RELEASED; \
1026 if (GetKeyboardState(keyboardStatus))
1039 OO_RESET_SDLKEY_MODIFIER(VK_LCONTROL, KMOD_LCTRL, SDLK_LCTRL);
1040 OO_RESET_SDLKEY_MODIFIER(VK_RCONTROL, KMOD_RCTRL, SDLK_RCTRL);
1041 ctrl = (modState & KMOD_LCTRL || modState & KMOD_RCTRL);
1044 OO_RESET_SDLKEY_MODIFIER(VK_LSHIFT, KMOD_LSHIFT, SDLK_LSHIFT);
1045 OO_RESET_SDLKEY_MODIFIER(VK_RSHIFT, KMOD_RSHIFT, SDLK_RSHIFT);
1046 shift = (modState & KMOD_LSHIFT || modState & KMOD_RSHIFT);
1049 if (GetKeyState(VK_CAPITAL) & 0x0001)
1051 modState |= KMOD_CAPS;
1052 keyState[SDLK_CAPSLOCK] = SDL_PRESSED;
1056 modState &= ~KMOD_CAPS;
1057 keyState[SDLK_CAPSLOCK] = SDL_RELEASED;
1061 SDL_SetModState(modState);
1065- (void) setWindowBorderless:(BOOL)borderless
1067 LONG currentWindowStyle = GetWindowLong(SDL_Window, GWL_STYLE);
1070 if ((!borderless && (currentWindowStyle & WS_CAPTION)) ||
1071 (borderless && !(currentWindowStyle & WS_CAPTION)))
return;
1075 SetWindowLong(SDL_Window, GWL_STYLE, currentWindowStyle & ~WS_CAPTION & ~WS_THICKFRAME);
1079 SetWindowLong(SDL_Window, GWL_STYLE, currentWindowStyle |
1080 WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX );
1081 [
self refreshDarKOrLightMode];
1083 SetWindowPos(SDL_Window, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
1087- (void) refreshDarKOrLightMode
1089 int shouldSetDarkMode = [
self isDarkModeOn];
1090 DwmSetWindowAttribute (SDL_Window, DWMWA_USE_IMMERSIVE_DARK_MODE, &shouldSetDarkMode,
sizeof(shouldSetDarkMode));
1094- (BOOL) isDarkModeOn
1097 DWORD bufferSize =
sizeof(buffer);
1100 HRESULT resultRegGetValue = RegGetValueW(HKEY_CURRENT_USER, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
1101 L
"AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, buffer, &bufferSize);
1102 if (resultRegGetValue != ERROR_SUCCESS)
1108 int i = (
int)(buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]);
1115- (BOOL) atDesktopResolution
1117 return atDesktopResolution;
1127- (BOOL) isOutputDisplayHDREnabled
1129 UINT32 pathCount, modeCount;
1130 DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
1131 DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
1132 UINT32 flags = QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE;
1133 LONG tempResult = ERROR_SUCCESS;
1134 BOOL isAdvColorInfo2DetectionSuccess = NO;
1140 tempResult = GetDisplayConfigBufferSizes(flags, &pathCount, &modeCount);
1142 if (tempResult != ERROR_SUCCESS)
1144 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1149 pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(pathCount *
sizeof(DISPLAYCONFIG_PATH_INFO));
1150 if (!pPathInfoArray)
1152 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: -1");
1156 pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(modeCount *
sizeof(DISPLAYCONFIG_MODE_INFO));
1157 if (!pModeInfoArray)
1160 free(pPathInfoArray);
1161 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: -1");
1166 tempResult = QueryDisplayConfig(flags, &pathCount, pPathInfoArray, &modeCount, pModeInfoArray, NULL);
1168 if (tempResult != ERROR_SUCCESS)
1170 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1175 pPathInfoArray = realloc(pPathInfoArray, pathCount *
sizeof(DISPLAYCONFIG_PATH_INFO));
1176 if (!pPathInfoArray)
1178 OOLogERR(
@"gameView.isOutputDisplayHDREnabled",
@"Failed ro reallocate pPathInfoArray");
1181 pModeInfoArray = realloc(pModeInfoArray, modeCount *
sizeof(DISPLAYCONFIG_MODE_INFO));
1182 if (!pModeInfoArray)
1184 OOLogERR(
@"gameView.isOutputDisplayHDREnabled",
@"Failed to reallocate pModeInfoArray");
1190 }
while (tempResult == ERROR_INSUFFICIENT_BUFFER);
1192 if (tempResult != ERROR_SUCCESS)
1194 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1200 for (i = 0; i < pathCount; i++)
1202 DISPLAYCONFIG_PATH_INFO *path = &pPathInfoArray[i];
1204 DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
1205 targetName.header.adapterId = path->targetInfo.adapterId;
1206 targetName.header.id = path->targetInfo.id;
1207 targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
1208 targetName.header.size =
sizeof(targetName);
1209 tempResult = DisplayConfigGetDeviceInfo(&targetName.header);
1211 if (tempResult != ERROR_SUCCESS)
1213 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1218 DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 advColorInfo2 = {};
1219 advColorInfo2.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2;
1220 advColorInfo2.header.adapterId = path->targetInfo.adapterId;
1221 advColorInfo2.header.id = path->targetInfo.id;
1222 advColorInfo2.header.size =
sizeof(advColorInfo2);
1224 tempResult = DisplayConfigGetDeviceInfo(&advColorInfo2.header);
1226 if (tempResult == ERROR_SUCCESS) isAdvColorInfo2DetectionSuccess = YES;
1229 OOLogWARN(
@"gameView.isOutputDisplayHDREnabled",
@"Received 0x%08X while attempting to detect HDR mode using Advanced Color Info 2 API. Retrying detection using legacy API.", HRESULT_FROM_WIN32(tempResult));
1234 DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = {};
1235 advColorInfo.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
1236 advColorInfo.header.adapterId = path->targetInfo.adapterId;
1237 advColorInfo.header.id = path->targetInfo.id;
1238 advColorInfo.header.size =
sizeof(advColorInfo);
1240 tempResult = DisplayConfigGetDeviceInfo(&advColorInfo.header);
1242 if (tempResult != ERROR_SUCCESS)
1244 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1248 char saveDeviceName[64];
1249 wchar_t wcsDeviceID[256];
1251 ZeroMemory(&dd,
sizeof(dd));
1253 EnumDisplayDevices(NULL, i, &dd, 0);
1254 BOOL isPrimaryDisplayDevice = dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE;
1256 strncpy(saveDeviceName, dd.DeviceName, 33);
1257 EnumDisplayDevices(saveDeviceName, 0, &dd, 0x00000001);
1258 mbstowcs(wcsDeviceID, dd.DeviceID, 129);
1263 if (isPrimaryDisplayDevice && !wcscmp(targetName.monitorDevicePath, wcsDeviceID) &&
1264 ((isAdvColorInfo2DetectionSuccess && advColorInfo2.highDynamicRangeSupported && advColorInfo2.activeColorMode == DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR) ||
1265 (!isAdvColorInfo2DetectionSuccess && advColorInfo.advancedColorSupported && advColorInfo.advancedColorEnabled && !advColorInfo.wideColorEnforced)))
1272 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"HDR display output requested - checking availability: %@", result ?
@"YES" :
@"NO");
1274 free (pModeInfoArray);
1275 free (pPathInfoArray);
1281- (float) hdrMaxBrightness
1283 return _hdrMaxBrightness;
1287- (void) setHDRMaxBrightness: (
float)newMaxBrightness
1291 _hdrMaxBrightness = newMaxBrightness;
1293 [[NSUserDefaults standardUserDefaults] setFloat:_hdrMaxBrightness forKey:@"hdr-max-brightness"];
1297- (float) hdrPaperWhiteBrightness
1299 return _hdrPaperWhiteBrightness;
1303- (void) setHDRPaperWhiteBrightness: (
float)newPaperWhiteBrightness
1307 _hdrPaperWhiteBrightness = newPaperWhiteBrightness;
1309 [[NSUserDefaults standardUserDefaults] setFloat:_hdrPaperWhiteBrightness forKey:@"hdr-paperwhite-brightness"];
1316- (BOOL) isRunningOnPrimaryDisplayDevice
1322- (void) grabMouseInsideGameWindow:(BOOL) value
1328- (void) stringToClipboard:(NSString *)stringToCopy
1340- (void) setWindowBorderless:(BOOL)borderless
1352- (BOOL) isOutputDisplayHDREnabled
1360- (void) initialiseGLWithSize:(NSSize) v_size
1362 [
self initialiseGLWithSize:v_size useVideoMode:YES];
1366- (void) initialiseGLWithSize:(NSSize) v_size useVideoMode:(BOOL) v_mode
1369 NSSize oldViewSize = viewSize;
1372 OOLog(
@"display.initGL",
@"Requested a new surface of %d x %d, %@.", (
int)viewSize.width, (
int)viewSize.height,(fullScreen ?
@"fullscreen" :
@"windowed"));
1373 SDL_GL_SwapBuffers();
1376 if (!updateContext)
return;
1379 settings.dmSize =
sizeof(DEVMODE);
1380 settings.dmDriverExtra = 0;
1381 EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &settings);
1383 WINDOWPLACEMENT windowPlacement;
1384 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
1385 GetWindowPlacement(SDL_Window, &windowPlacement);
1387 static BOOL lastWindowPlacementMaximized = NO;
1388 if (fullScreen && (windowPlacement.showCmd == SW_SHOWMAXIMIZED))
1392 lastWindowPlacementMaximized = YES;
1396 if (lastWindowPlacementMaximized)
1398 windowPlacement.showCmd = SW_SHOWMAXIMIZED;
1403 BOOL changingResolution = [
self isRunningOnPrimaryDisplayDevice] &&
1404 ((fullScreen && (settings.dmPelsWidth != viewSize.width || settings.dmPelsHeight != viewSize.height)) ||
1405 (wasFullScreen && (settings.dmPelsWidth != [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayWidth] intValue]
1406 || settings.dmPelsHeight != [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayHeight] intValue])));
1418 [
self getCurrentMonitorInfo: &monitorInfo];
1420 settings.dmPelsWidth = viewSize.width;
1421 settings.dmPelsHeight = viewSize.height;
1422 settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1427 if(lastWindowPlacementMaximized)
1429 CopyRect(&lastGoodRect, &windowPlacement.rcNormalPosition);
1431 windowPlacement.showCmd = SW_SHOWNORMAL;
1432 SetWindowPlacement(SDL_Window, &windowPlacement);
1434 else GetWindowRect(SDL_Window, &lastGoodRect);
1437 SetForegroundWindow(SDL_Window);
1438 if (changingResolution)
1440 if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &settings, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
1442 m_glContextInitialized = YES;
1443 OOLogERR(
@"displayMode.change.error",
@"Could not switch to requested display mode.");
1446 atDesktopResolution = settings.dmPelsWidth == [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayWidth] intValue]
1447 && settings.dmPelsHeight == [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayHeight] intValue];
1450 MoveWindow(SDL_Window, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, (
int)viewSize.width, (
int)viewSize.height, TRUE);
1453 [
self setWindowBorderless:YES];
1457 else if ( wasFullScreen )
1459 if (changingResolution)
1462 if (ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL) == DISP_CHANGE_SUCCESSFUL)
1464 atDesktopResolution = YES;
1476 [
self getCurrentMonitorInfo: &monitorInfo];
1478 if (lastWindowPlacementMaximized) CopyRect(&windowPlacement.rcNormalPosition, &lastGoodRect);
1479 SetWindowPlacement(SDL_Window, &windowPlacement);
1480 if (!lastWindowPlacementMaximized)
1482 MoveWindow(SDL_Window, (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left - (
int)viewSize.width)/2 +
1483 monitorInfo.rcMonitor.left,
1484 (monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top - (
int)viewSize.height)/2 +
1485 monitorInfo.rcMonitor.top,
1486 (
int)viewSize.width, (
int)viewSize.height, TRUE);
1489 [
self setWindowBorderless:NO];
1491 lastWindowPlacementMaximized = NO;
1492 ShowWindow(SDL_Window,SW_SHOW);
1496 saveSize = !wasFullScreen;
1498 GetClientRect(SDL_Window, &wDC);
1500 if (!fullScreen && (bounds.size.width != wDC.right - wDC.left
1501 || bounds.size.height != wDC.bottom - wDC.top))
1510 RECT desiredClientRect;
1511 GetWindowRect(SDL_Window, &desiredClientRect);
1512 AdjustWindowRect(&desiredClientRect, WS_CAPTION | WS_THICKFRAME, FALSE);
1513 SetWindowPos(SDL_Window, NULL, desiredClientRect.left, desiredClientRect.top,
1514 desiredClientRect.right - desiredClientRect.left,
1515 desiredClientRect.bottom - desiredClientRect.top, 0);
1517 GetClientRect(SDL_Window, &wDC);
1518 viewSize.width = wDC.right - wDC.left;
1519 viewSize.height = wDC.bottom - wDC.top;
1523 bounds.size.width = viewSize.width = wDC.right - wDC.left;
1524 bounds.size.height = viewSize.height = wDC.bottom - wDC.top;
1528 bounds.origin.x = monitorInfo.rcMonitor.left;
1529 bounds.origin.y = monitorInfo.rcMonitor.top;
1531 wasFullScreen=fullScreen;
1535 int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL;
1538 videoModeFlags |= SDL_NOFRAME;
1539 if (fullScreen == YES)
1541 videoModeFlags |= SDL_FULLSCREEN;
1545 videoModeFlags |= SDL_RESIZABLE;
1547 surface = SDL_SetVideoMode((
int)viewSize.width, (
int)viewSize.height, 32, videoModeFlags);
1549 if (!surface && fullScreen == YES)
1551 [
self setFullScreenMode: NO];
1552 viewSize = oldViewSize;
1553 videoModeFlags &= ~SDL_FULLSCREEN;
1554 videoModeFlags |= SDL_RESIZABLE;
1555 surface = SDL_SetVideoMode((
int)viewSize.width, (
int)viewSize.height, 32, videoModeFlags);
1561 OOLogERR(
@"display.mode.error",
@"Unable to change display mode: %s",SDL_GetError());
1565 bounds.size.width = surface->w;
1566 bounds.size.height = surface->h;
1569 OOLog(
@"display.initGL",
@"Created a new surface of %d x %d, %@.", (
int)viewSize.width, (
int)viewSize.height,(fullScreen ?
@"fullscreen" :
@"windowed"));
1571 if (viewSize.width/viewSize.height > 4.0/3.0) {
1572 display_z = 480.0 * bounds.size.width/bounds.size.height;
1573 x_offset = 240.0 * bounds.size.width/bounds.size.height;
1578 y_offset = 320.0 * bounds.size.height/bounds.size.width;
1581 if (surface != 0) SDL_FreeSurface(surface);
1583 [
self autoShowMouse];
1585 [[
self gameController] setUpBasicOpenGLStateWithSize:viewSize];
1586 SDL_GL_SwapBuffers();
1589 m_glContextInitialized = YES;
1593- (float) colorSaturation
1595 return _colorSaturation;
1599- (void) adjustColorSaturation:(
float)colorSaturationAdjustment;
1601 _colorSaturation += colorSaturationAdjustment;