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 typedString = [[NSMutableString alloc] initWithString:@""];
433 isAlphabetKeyDown = NO;
435 timeIntervalAtLastClick = timeSinceLastMouseWheel = [NSDate timeIntervalSinceReferenceDate];
437 _mouseWheelDelta = 0.0f;
439 m_glContextInitialized = NO;
444- (void) endSplashScreen
447 if ([
self hdrOutput] && ![
self isOutputDisplayHDREnabled])
449 if (MessageBox(NULL,
"No primary display in HDR mode was detected.\n\n"
450 "If you continue, graphics will not be rendered as intended.\n"
451 "Click OK to launch anyway, or Cancel to exit.",
"oolite.exe - HDR requested",
452 MB_OKCANCEL | MB_ICONWARNING) == IDCANCEL)
459 if (!showSplashScreen)
return;
463 wasFullScreen = !fullScreen;
465 ShowWindow(SDL_Window,SW_RESTORE);
466 [
self initialiseGLWithSize: firstScreen];
470 int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL;
472 videoModeFlags |= (fullScreen) ? SDL_FULLSCREEN : SDL_RESIZABLE;
473 surface = SDL_SetVideoMode(firstScreen.width, firstScreen.height, 32, videoModeFlags);
475 if (!surface && fullScreen == YES)
477 [
self setFullScreenMode: NO];
478 videoModeFlags &= ~SDL_FULLSCREEN;
479 videoModeFlags |= SDL_RESIZABLE;
480 surface = SDL_SetVideoMode(currentWindowSize.width, currentWindowSize.height, 32, videoModeFlags);
483 SDL_putenv (
"SDL_VIDEO_WINDOW_POS=none");
492 SDL_Event dummyEvent;
493 while (SDL_PollEvent(&dummyEvent))
505 [
self autoShowMouse];
509- (void) initKeyMappingData
511 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
519 NSString *kbd = [prefs oo_stringForKey:@"keyboard-code" defaultValue:@"default"];
520 NSDictionary *subset = [kmap objectForKey:kbd];
522 [keyMappings_normal release];
523 keyMappings_normal = [[subset objectForKey:@"mapping_normal"] copy];
524 [keyMappings_shifted release];
525 keyMappings_shifted = [[subset objectForKey:@"mapping_shifted"] copy];
532 [typedString release];
535 [screenSizes release];
539 SDL_FreeSurface(surface);
543 if (keyMappings_normal)
544 [keyMappings_normal release];
546 if (keyMappings_shifted)
547 [keyMappings_shifted release];
553 [matrixManager release];
559- (void) autoShowMouse
564 if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE)
565 SDL_ShowCursor(SDL_DISABLE);
569 if (SDL_ShowCursor(SDL_QUERY) == SDL_DISABLE)
570 SDL_ShowCursor(SDL_ENABLE);
576 allowingStringInput = value;
580- (void) allowStringInput: (BOOL) value
590 return allowingStringInput;
594- (NSString *) typedString
600- (void) resetTypedString
602 [typedString setString:@""];
606- (void) setTypedString:(NSString*) value
608 [typedString setString:value];
624- (NSSize) backingViewSize
650 return gameController;
656 gameController = controller;
662 [
self autoShowMouse];
663 [
self setMouseInDeltaMode:OOMouseInteractionModeIsFlightMode(newMode)];
667- (BOOL) inFullScreenMode
673- (void) setFullScreenMode:(BOOL)fsm
678 [[NSUserDefaults standardUserDefaults]
679 setBool: fullScreen forKey:@"fullscreen"];
680 [[NSUserDefaults standardUserDefaults] synchronize];
684- (void) toggleScreenMode
686 [
self setFullScreenMode: !fullScreen];
688 [
self getCurrentMonitorInfo:&monitorInfo];
693 if(![
self isRunningOnPrimaryDisplayDevice])
695 [
self initialiseGLWithSize:NSMakeSize(monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
696 monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top)];
698 else [
self initialiseGLWithSize:[
self modeAsSize: currentSize]];
700 [
self initialiseGLWithSize:[
self modeAsSize: currentSize]];
704 [
self initialiseGLWithSize: currentWindowSize];
715- (void) setDisplayMode:(
int)mode fullScreen:(BOOL)fsm
717 [
self setFullScreenMode: fsm];
720 [
self initialiseGLWithSize: [
self modeAsSize: mode]];
724- (
int) indexOfCurrentSize
730- (void) setScreenSize: (
int)sizeIndex
732 currentSize=sizeIndex;
734 [
self initialiseGLWithSize: [
self modeAsSize: currentSize]];
738- (NSMutableArray *)getScreenSizeArray
744- (NSSize) modeAsSize:(
int)sizeIndex
746 NSDictionary *
mode=[screenSizes objectAtIndex: sizeIndex];
760 [
self drawRect: NSMakeRect(0, 0, viewSize.width, viewSize.height)];
763- (void) drawRect:(NSRect)rect
765 [
self updateScreenWithVideoMode:YES];
768- (void) updateScreenWithVideoMode:(BOOL) v_mode
770 if ((viewSize.width != surface->w)||(viewSize.height != surface->h))
773 m_glContextInitialized = NO;
775 viewSize.width = surface->w;
776 viewSize.height = surface->h;
779 if (m_glContextInitialized == NO)
781 [
self initialiseGLWithSize:viewSize useVideoMode:v_mode];
789 if (
UNIVERSE) [UNIVERSE drawUniverse];
793 glClearColor( 0.0, 0.0, 0.0, 0.0);
794 glClear( GL_COLOR_BUFFER_BIT);
797 SDL_GL_SwapBuffers();
800- (void) initSplashScreen
802 if (!showSplashScreen)
return;
805 SDL_Surface *image=NULL;
808 NSString *imagesDir = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Images"];
810 image = SDL_LoadBMP([[imagesDir stringByAppendingPathComponent:
@"splash.bmp"] UTF8String]);
814 SDL_FreeSurface(image);
815 OOLogWARN(
@"sdl.gameStart",
@"%@",
@"image 'splash.bmp' not found!");
816 [
self endSplashScreen];
827 dest.x = (GetSystemMetrics(SM_CXSCREEN)- dest.w)/2;
828 dest.y = (GetSystemMetrics(SM_CYSCREEN)-dest.h)/2;
829 SetWindowLong(SDL_Window,GWL_STYLE,GetWindowLong(SDL_Window,GWL_STYLE) & ~WS_CAPTION & ~WS_THICKFRAME);
830 ShowWindow(SDL_Window,SW_RESTORE);
831 MoveWindow(SDL_Window,dest.x,dest.y,dest.w,dest.h,TRUE);
843 surface = SDL_SetVideoMode(dest.w, dest.h, 32, SDL_HWSURFACE | SDL_OPENGL);
849 glViewport( 0, 0, dest.w, dest.h);
851 glEnable( GL_TEXTURE_2D );
852 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
853 glClear( GL_COLOR_BUFFER_BIT );
855 [matrixManager resetProjection];
856 [matrixManager orthoLeft: 0.0f right: dest.w bottom: dest.h top: 0.0 near: -1.0 far: 1.0];
857 [matrixManager syncProjection];
859 [matrixManager resetModelView];
860 [matrixManager syncModelView];
863 GLenum texture_format;
867 nOfColors = image->format->BytesPerPixel;
870 if (image->format->Rmask == 0x000000ff)
871 texture_format = GL_RGBA;
873 texture_format = GL_BGRA;
875 else if (nOfColors == 3)
877 if (image->format->Rmask == 0x000000ff)
878 texture_format = GL_RGB;
880 texture_format = GL_BGR;
882 SDL_FreeSurface(image);
883 OOLog(
@"Sdl.GameStart",
@"%@",
@"----- Encoding error within image 'splash.bmp'");
884 [
self endSplashScreen];
888 glGenTextures( 1, &texture );
889 glBindTexture( GL_TEXTURE_2D, texture );
892 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
893 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
896 glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, image->w, image->h, 0,
897 texture_format, GL_UNSIGNED_BYTE, image->pixels );
899 glBindTexture( GL_TEXTURE_2D, texture );
902 glTexCoord2i( 0, 0 );
904 glTexCoord2i( 1, 0 );
905 glVertex2i( dest.w, 0 );
906 glTexCoord2i( 1, 1 );
907 glVertex2i( dest.w, dest.h );
908 glTexCoord2i( 0, 1 );
909 glVertex2i( 0, dest.h );
913 SDL_GL_SwapBuffers();
914 [matrixManager resetModelView];
915 [matrixManager syncModelView];
918 SDL_FreeSurface( image );
920 glDeleteTextures(1, &texture);
922 glDisable( GL_TEXTURE_2D );
928- (MONITORINFOEX) currentMonitorInfo
934- (BOOL) getCurrentMonitorInfo:(MONITORINFOEX *)mInfo
936 HMONITOR hMon = MonitorFromWindow(SDL_Window, MONITOR_DEFAULTTOPRIMARY);
937 ZeroMemory(mInfo,
sizeof(MONITORINFOEX));
938 mInfo->cbSize =
sizeof(MONITORINFOEX);
939 if (GetMonitorInfo (hMon, (LPMONITORINFO)mInfo))
947- (BOOL) isRunningOnPrimaryDisplayDevice
950 [
self getCurrentMonitorInfo:&monitorInfo];
951 if (!(monitorInfo.dwFlags & MONITORINFOF_PRIMARY))
959- (void) grabMouseInsideGameWindow:(BOOL) value
964 GetWindowRect(SDL_Window, &gameWindowRect);
965 ClipCursor(&gameWindowRect);
971 grabMouseStatus = !!value;
975- (void) stringToClipboard:(NSString *)stringToCopy
979 const char *clipboardText = [stringToCopy cStringUsingEncoding:NSUTF8StringEncoding];
980 const size_t clipboardTextLength = strlen(clipboardText) + 1;
981 HGLOBAL clipboardMem = GlobalAlloc(GMEM_MOVEABLE, clipboardTextLength);
984 memcpy(GlobalLock(clipboardMem), clipboardText, clipboardTextLength);
985 GlobalUnlock(clipboardMem);
988 if (!SetClipboardData(CF_TEXT, clipboardMem))
990 OOLog(
@"stringToClipboard.failed",
@"Failed to copy string %@ to clipboard", stringToCopy);
995 GlobalFree(clipboardMem);
1007 SDLMod modState = SDL_GetModState();
1008 Uint8 *keyState = SDL_GetKeyState(NULL);
1009 BYTE keyboardStatus[256];
1010 #define OO_RESET_SDLKEY_MODIFIER(vkCode, kModCode, sdlkCode) do {\
1011 if (keyboardStatus[vkCode] & 0x0080) \
1013 modState |= kModCode; \
1014 keyState[sdlkCode] = SDL_PRESSED; \
1018 modState &= ~kModCode; \
1019 keyState[sdlkCode] = SDL_RELEASED; \
1022 if (GetKeyboardState(keyboardStatus))
1035 OO_RESET_SDLKEY_MODIFIER(VK_LCONTROL, KMOD_LCTRL, SDLK_LCTRL);
1036 OO_RESET_SDLKEY_MODIFIER(VK_RCONTROL, KMOD_RCTRL, SDLK_RCTRL);
1037 ctrl = (modState & KMOD_LCTRL || modState & KMOD_RCTRL);
1040 OO_RESET_SDLKEY_MODIFIER(VK_LSHIFT, KMOD_LSHIFT, SDLK_LSHIFT);
1041 OO_RESET_SDLKEY_MODIFIER(VK_RSHIFT, KMOD_RSHIFT, SDLK_RSHIFT);
1042 shift = (modState & KMOD_LSHIFT || modState & KMOD_RSHIFT);
1045 if (GetKeyState(VK_CAPITAL) & 0x0001)
1047 modState |= KMOD_CAPS;
1048 keyState[SDLK_CAPSLOCK] = SDL_PRESSED;
1052 modState &= ~KMOD_CAPS;
1053 keyState[SDLK_CAPSLOCK] = SDL_RELEASED;
1057 SDL_SetModState(modState);
1061- (void) setWindowBorderless:(BOOL)borderless
1063 LONG currentWindowStyle = GetWindowLong(SDL_Window, GWL_STYLE);
1066 if ((!borderless && (currentWindowStyle & WS_CAPTION)) ||
1067 (borderless && !(currentWindowStyle & WS_CAPTION)))
return;
1071 SetWindowLong(SDL_Window, GWL_STYLE, currentWindowStyle & ~WS_CAPTION & ~WS_THICKFRAME);
1075 SetWindowLong(SDL_Window, GWL_STYLE, currentWindowStyle |
1076 WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX );
1077 [
self refreshDarKOrLightMode];
1079 SetWindowPos(SDL_Window, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
1083- (void) refreshDarKOrLightMode
1085 int shouldSetDarkMode = [
self isDarkModeOn];
1086 DwmSetWindowAttribute (SDL_Window, DWMWA_USE_IMMERSIVE_DARK_MODE, &shouldSetDarkMode,
sizeof(shouldSetDarkMode));
1090- (BOOL) isDarkModeOn
1093 DWORD bufferSize =
sizeof(buffer);
1096 HRESULT resultRegGetValue = RegGetValueW(HKEY_CURRENT_USER, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
1097 L
"AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, buffer, &bufferSize);
1098 if (resultRegGetValue != ERROR_SUCCESS)
1104 int i = (
int)(buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]);
1111- (BOOL) atDesktopResolution
1113 return atDesktopResolution;
1123- (BOOL) isOutputDisplayHDREnabled
1125 UINT32 pathCount, modeCount;
1126 DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
1127 DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
1128 UINT32 flags = QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE;
1129 LONG tempResult = ERROR_SUCCESS;
1130 BOOL isAdvColorInfo2DetectionSuccess = NO;
1136 tempResult = GetDisplayConfigBufferSizes(flags, &pathCount, &modeCount);
1138 if (tempResult != ERROR_SUCCESS)
1140 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1145 pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(pathCount *
sizeof(DISPLAYCONFIG_PATH_INFO));
1146 if (!pPathInfoArray)
1148 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: -1");
1152 pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(modeCount *
sizeof(DISPLAYCONFIG_MODE_INFO));
1153 if (!pModeInfoArray)
1156 free(pPathInfoArray);
1157 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: -1");
1162 tempResult = QueryDisplayConfig(flags, &pathCount, pPathInfoArray, &modeCount, pModeInfoArray, NULL);
1164 if (tempResult != ERROR_SUCCESS)
1166 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1171 pPathInfoArray = realloc(pPathInfoArray, pathCount *
sizeof(DISPLAYCONFIG_PATH_INFO));
1172 if (!pPathInfoArray)
1174 OOLogERR(
@"gameView.isOutputDisplayHDREnabled",
@"Failed ro reallocate pPathInfoArray");
1177 pModeInfoArray = realloc(pModeInfoArray, modeCount *
sizeof(DISPLAYCONFIG_MODE_INFO));
1178 if (!pModeInfoArray)
1180 OOLogERR(
@"gameView.isOutputDisplayHDREnabled",
@"Failed to reallocate pModeInfoArray");
1186 }
while (tempResult == ERROR_INSUFFICIENT_BUFFER);
1188 if (tempResult != ERROR_SUCCESS)
1190 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1196 for (i = 0; i < pathCount; i++)
1198 DISPLAYCONFIG_PATH_INFO *path = &pPathInfoArray[i];
1200 DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
1201 targetName.header.adapterId = path->targetInfo.adapterId;
1202 targetName.header.id = path->targetInfo.id;
1203 targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
1204 targetName.header.size =
sizeof(targetName);
1205 tempResult = DisplayConfigGetDeviceInfo(&targetName.header);
1207 if (tempResult != ERROR_SUCCESS)
1209 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1214 DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 advColorInfo2 = {};
1215 advColorInfo2.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2;
1216 advColorInfo2.header.adapterId = path->targetInfo.adapterId;
1217 advColorInfo2.header.id = path->targetInfo.id;
1218 advColorInfo2.header.size =
sizeof(advColorInfo2);
1220 tempResult = DisplayConfigGetDeviceInfo(&advColorInfo2.header);
1222 if (tempResult == ERROR_SUCCESS) isAdvColorInfo2DetectionSuccess = YES;
1225 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));
1230 DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = {};
1231 advColorInfo.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
1232 advColorInfo.header.adapterId = path->targetInfo.adapterId;
1233 advColorInfo.header.id = path->targetInfo.id;
1234 advColorInfo.header.size =
sizeof(advColorInfo);
1236 tempResult = DisplayConfigGetDeviceInfo(&advColorInfo.header);
1238 if (tempResult != ERROR_SUCCESS)
1240 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1244 char saveDeviceName[64];
1245 wchar_t wcsDeviceID[256];
1247 ZeroMemory(&dd,
sizeof(dd));
1249 EnumDisplayDevices(NULL, i, &dd, 0);
1250 BOOL isPrimaryDisplayDevice = dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE;
1252 strncpy(saveDeviceName, dd.DeviceName, 33);
1253 EnumDisplayDevices(saveDeviceName, 0, &dd, 0x00000001);
1254 mbstowcs(wcsDeviceID, dd.DeviceID, 129);
1259 if (isPrimaryDisplayDevice && !wcscmp(targetName.monitorDevicePath, wcsDeviceID) &&
1260 ((isAdvColorInfo2DetectionSuccess && advColorInfo2.highDynamicRangeSupported && advColorInfo2.activeColorMode == DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR) ||
1261 (!isAdvColorInfo2DetectionSuccess && advColorInfo.advancedColorSupported && advColorInfo.advancedColorEnabled && !advColorInfo.wideColorEnforced)))
1268 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"HDR display output requested - checking availability: %@", result ?
@"YES" :
@"NO");
1270 free (pModeInfoArray);
1271 free (pPathInfoArray);
1277- (float) hdrMaxBrightness
1279 return _hdrMaxBrightness;
1283- (void) setHDRMaxBrightness: (
float)newMaxBrightness
1287 _hdrMaxBrightness = newMaxBrightness;
1289 [[NSUserDefaults standardUserDefaults] setFloat:_hdrMaxBrightness forKey:@"hdr-max-brightness"];
1293- (float) hdrPaperWhiteBrightness
1295 return _hdrPaperWhiteBrightness;
1299- (void) setHDRPaperWhiteBrightness: (
float)newPaperWhiteBrightness
1303 _hdrPaperWhiteBrightness = newPaperWhiteBrightness;
1305 [[NSUserDefaults standardUserDefaults] setFloat:_hdrPaperWhiteBrightness forKey:@"hdr-paperwhite-brightness"];
1312- (BOOL) isRunningOnPrimaryDisplayDevice
1318- (void) grabMouseInsideGameWindow:(BOOL) value
1324- (void) stringToClipboard:(NSString *)stringToCopy
1336- (void) setWindowBorderless:(BOOL)borderless
1348- (BOOL) isOutputDisplayHDREnabled
1356- (void) initialiseGLWithSize:(NSSize) v_size
1358 [
self initialiseGLWithSize:v_size useVideoMode:YES];
1362- (void) initialiseGLWithSize:(NSSize) v_size useVideoMode:(BOOL) v_mode
1365 NSSize oldViewSize = viewSize;
1368 OOLog(
@"display.initGL",
@"Requested a new surface of %d x %d, %@.", (
int)viewSize.width, (
int)viewSize.height,(fullScreen ?
@"fullscreen" :
@"windowed"));
1369 SDL_GL_SwapBuffers();
1372 if (!updateContext)
return;
1375 settings.dmSize =
sizeof(DEVMODE);
1376 settings.dmDriverExtra = 0;
1377 EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &settings);
1379 WINDOWPLACEMENT windowPlacement;
1380 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
1381 GetWindowPlacement(SDL_Window, &windowPlacement);
1383 static BOOL lastWindowPlacementMaximized = NO;
1384 if (fullScreen && (windowPlacement.showCmd == SW_SHOWMAXIMIZED))
1388 lastWindowPlacementMaximized = YES;
1392 if (lastWindowPlacementMaximized)
1394 windowPlacement.showCmd = SW_SHOWMAXIMIZED;
1399 BOOL changingResolution = [
self isRunningOnPrimaryDisplayDevice] &&
1400 ((fullScreen && (settings.dmPelsWidth != viewSize.width || settings.dmPelsHeight != viewSize.height)) ||
1401 (wasFullScreen && (settings.dmPelsWidth != [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayWidth] intValue]
1402 || settings.dmPelsHeight != [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayHeight] intValue])));
1414 [
self getCurrentMonitorInfo: &monitorInfo];
1416 settings.dmPelsWidth = viewSize.width;
1417 settings.dmPelsHeight = viewSize.height;
1418 settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1423 if(lastWindowPlacementMaximized)
1425 CopyRect(&lastGoodRect, &windowPlacement.rcNormalPosition);
1427 windowPlacement.showCmd = SW_SHOWNORMAL;
1428 SetWindowPlacement(SDL_Window, &windowPlacement);
1430 else GetWindowRect(SDL_Window, &lastGoodRect);
1433 SetForegroundWindow(SDL_Window);
1434 if (changingResolution)
1436 if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &settings, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
1438 m_glContextInitialized = YES;
1439 OOLogERR(
@"displayMode.change.error",
@"Could not switch to requested display mode.");
1442 atDesktopResolution = settings.dmPelsWidth == [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayWidth] intValue]
1443 && settings.dmPelsHeight == [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayHeight] intValue];
1446 MoveWindow(SDL_Window, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, (
int)viewSize.width, (
int)viewSize.height, TRUE);
1449 [
self setWindowBorderless:YES];
1453 else if ( wasFullScreen )
1455 if (changingResolution)
1458 if (ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL) == DISP_CHANGE_SUCCESSFUL)
1460 atDesktopResolution = YES;
1472 [
self getCurrentMonitorInfo: &monitorInfo];
1474 if (lastWindowPlacementMaximized) CopyRect(&windowPlacement.rcNormalPosition, &lastGoodRect);
1475 SetWindowPlacement(SDL_Window, &windowPlacement);
1476 if (!lastWindowPlacementMaximized)
1478 MoveWindow(SDL_Window, (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left - (
int)viewSize.width)/2 +
1479 monitorInfo.rcMonitor.left,
1480 (monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top - (
int)viewSize.height)/2 +
1481 monitorInfo.rcMonitor.top,
1482 (
int)viewSize.width, (
int)viewSize.height, TRUE);
1485 [
self setWindowBorderless:NO];
1487 lastWindowPlacementMaximized = NO;
1488 ShowWindow(SDL_Window,SW_SHOW);
1492 saveSize = !wasFullScreen;
1494 GetClientRect(SDL_Window, &wDC);
1496 if (!fullScreen && (bounds.size.width != wDC.right - wDC.left
1497 || bounds.size.height != wDC.bottom - wDC.top))
1506 RECT desiredClientRect;
1507 GetWindowRect(SDL_Window, &desiredClientRect);
1508 AdjustWindowRect(&desiredClientRect, WS_CAPTION | WS_THICKFRAME, FALSE);
1509 SetWindowPos(SDL_Window, NULL, desiredClientRect.left, desiredClientRect.top,
1510 desiredClientRect.right - desiredClientRect.left,
1511 desiredClientRect.bottom - desiredClientRect.top, 0);
1513 GetClientRect(SDL_Window, &wDC);
1514 viewSize.width = wDC.right - wDC.left;
1515 viewSize.height = wDC.bottom - wDC.top;
1519 bounds.size.width = viewSize.width = wDC.right - wDC.left;
1520 bounds.size.height = viewSize.height = wDC.bottom - wDC.top;
1524 bounds.origin.x = monitorInfo.rcMonitor.left;
1525 bounds.origin.y = monitorInfo.rcMonitor.top;
1527 wasFullScreen=fullScreen;
1531 int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL;
1534 videoModeFlags |= SDL_NOFRAME;
1535 if (fullScreen == YES)
1537 videoModeFlags |= SDL_FULLSCREEN;
1541 videoModeFlags |= SDL_RESIZABLE;
1543 surface = SDL_SetVideoMode((
int)viewSize.width, (
int)viewSize.height, 32, videoModeFlags);
1545 if (!surface && fullScreen == YES)
1547 [
self setFullScreenMode: NO];
1548 viewSize = oldViewSize;
1549 videoModeFlags &= ~SDL_FULLSCREEN;
1550 videoModeFlags |= SDL_RESIZABLE;
1551 surface = SDL_SetVideoMode((
int)viewSize.width, (
int)viewSize.height, 32, videoModeFlags);
1557 OOLogERR(
@"display.mode.error",
@"Unable to change display mode: %s",SDL_GetError());
1561 bounds.size.width = surface->w;
1562 bounds.size.height = surface->h;
1565 OOLog(
@"display.initGL",
@"Created a new surface of %d x %d, %@.", (
int)viewSize.width, (
int)viewSize.height,(fullScreen ?
@"fullscreen" :
@"windowed"));
1567 if (viewSize.width/viewSize.height > 4.0/3.0) {
1568 display_z = 480.0 * bounds.size.width/bounds.size.height;
1569 x_offset = 240.0 * bounds.size.width/bounds.size.height;
1574 y_offset = 320.0 * bounds.size.height/bounds.size.width;
1577 if (surface != 0) SDL_FreeSurface(surface);
1579 [
self autoShowMouse];
1581 [[
self gameController] setUpBasicOpenGLStateWithSize:viewSize];
1582 SDL_GL_SwapBuffers();
1585 m_glContextInitialized = YES;
1589- (float) colorSaturation
1591 return _colorSaturation;
1595- (void) adjustColorSaturation:(
float)colorSaturationAdjustment;
1597 _colorSaturation += colorSaturationAdjustment;