53#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
54HRESULT WINAPI DwmSetWindowAttribute (HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
57@interface MyOpenGLView (OOPrivate)
60- (void) setWindowBorderless:(BOOL)borderless;
61- (void) handleStringInput: (SDL_KeyboardEvent *) kbd_event keyID:(Uint16)key_id;
66+ (NSMutableDictionary *) getNativeSize
68 NSMutableDictionary *
mode=[[NSMutableDictionary alloc] init];
69 int nativeDisplayWidth = 1024;
70 int nativeDisplayHeight = 768;
73 SDL_SysWMinfo dpyInfo;
74 SDL_VERSION(&dpyInfo.version);
75 if(SDL_GetWMInfo(&dpyInfo))
77 nativeDisplayWidth = DisplayWidth(dpyInfo.info.x11.display, 0);
78 nativeDisplayHeight = DisplayHeight(dpyInfo.info.x11.display, 0);
79 OOLog(
@"display.mode.list.native",
@"X11 native resolution detected: %d x %d", nativeDisplayWidth, nativeDisplayHeight);
83 OOLog(
@"display.mode.list.native.failed",
@"%@",
@"SDL_GetWMInfo failed, defaulting to 1024x768 for native size");
86 nativeDisplayWidth = GetSystemMetrics(SM_CXSCREEN);
87 nativeDisplayHeight = GetSystemMetrics(SM_CYSCREEN);
88 OOLog(
@"display.mode.list.native",
@"Windows native resolution detected: %d x %d", nativeDisplayWidth, nativeDisplayHeight);
90 OOLog(
@"display.mode.list.native.unknown",
@"Unknown architecture, defaulting to 1024x768");
92 [mode
setValue: [NSNumber numberWithInt: nativeDisplayWidth]
forKey:kOODisplayWidth];
93 [mode
setValue: [NSNumber numberWithInt: nativeDisplayHeight]
forKey: kOODisplayHeight];
94 [mode
setValue: [NSNumber numberWithInt: 0]
forKey: kOODisplayRefreshRate];
100- (void) createSurface
103 const int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL | SDL_RESIZABLE;
105 if (showSplashScreen)
109 NSSize tmp = currentWindowSize;
110 ShowWindow(SDL_Window,SW_SHOWMINIMIZED);
114 surface = SDL_SetVideoMode(firstScreen.width, firstScreen.height, 32, videoModeFlags);
117 currentWindowSize=tmp;
120 surface = SDL_SetVideoMode(8, 8, 32, videoModeFlags);
131 surface = SDL_SetVideoMode(firstScreen.width, firstScreen.height, 32, videoModeFlags);
136 [
self initialiseGLWithSize: firstScreen];
140 if (SDL_SetGamma(_gamma, _gamma, _gamma) < 0 )
142 char * errStr = SDL_GetError();
143 OOLogWARN(
@"gamma.set.failed",
@"Could not set gamma: %s", errStr);
148 SDL_EnableUNICODE(1);
157 SDL_Surface *icon=NULL;
159 NSString *cmdLineArgsStr =
@"Startup command: ";
163 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
164 showSplashScreen = [prefs oo_boolForKey:@"splash-screen" defaultValue:YES];
165 BOOL vSyncPreference = [prefs oo_boolForKey:@"v-sync" defaultValue:YES];
166 int bitsPerColorComponent = [prefs oo_boolForKey:@"hdr" defaultValue:NO] ? 16 : 8;
169 NSArray *arguments =
nil;
170 NSEnumerator *argEnum =
nil;
172 BOOL noSplashArgFound = NO;
174 [
self initKeyMappingData];
179 arguments = [[NSProcessInfo processInfo] arguments];
183 for (argEnum = [arguments objectEnumerator]; (arg = [argEnum nextObject]); )
185 if ([arg isEqual:
@"-nosplash"] || [arg isEqual:
@"--nosplash"])
187 showSplashScreen = NO;
188 noSplashArgFound = YES;
190 else if (([arg isEqual:
@"-splash"] || [arg isEqual:
@"--splash"]) && !noSplashArgFound)
192 showSplashScreen = YES;
196 if ([arg isEqual:
@"-novsync"] || [arg isEqual:
@"--novsync"]) vSyncPreference = NO;
198 if ([arg isEqual:
@"-hdr"]) bitsPerColorComponent = 16;
201 cmdLineArgsStr = [cmdLineArgsStr stringByAppendingFormat:@"%@ ", arg];
204 OOLog(
@"process.args",
@"%@", cmdLineArgsStr);
210 OOLog(
@"sdl.init",
@"%@",
@"initialising SDL");
211 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
213 OOLog(
@"sdl.init.failed",
@"Unable to init SDL: %s\n", SDL_GetError());
218 SDL_putenv (
"SDL_VIDEO_WINDOW_POS=center");
224 if (![
OOSound isSoundOK])
OOLog(
@"sound.init",
@"%@",
@"Sound system disabled.");
227 static char windowCaption[128];
228 NSString *versionString = [NSString stringWithFormat:@"Oolite v%@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]];
230 strcpy (windowCaption, [versionString UTF8String]);
231 strcat (windowCaption,
" - "__DATE__);
232 SDL_WM_SetCaption (windowCaption,
"Oolite");
236 SDL_EventState (SDL_SYSWMEVENT, SDL_ENABLE);
239 static SDL_SysWMinfo wInfo;
240 SDL_VERSION(&wInfo.version);
241 SDL_GetWMInfo(&wInfo);
242 SDL_Window = wInfo.window;
245 if (![
self getCurrentMonitorInfo:&monitorInfo])
247 OOLogWARN(
@"display.initGL.monitorInfoWarning",
@"Could not get current monitor information.");
250 atDesktopResolution = YES;
253 grabMouseStatus = NO;
255 imagesDir = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Images"];
256 icon = SDL_LoadBMP([[imagesDir stringByAppendingPathComponent:
@"WMicon.bmp"] UTF8String]);
260 colorkey = SDL_MapRGB(icon->format, 128, 0, 128);
261 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, colorkey);
262 SDL_WM_SetIcon(icon, NULL);
264 SDL_FreeSurface(icon);
266 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, bitsPerColorComponent);
267 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, bitsPerColorComponent);
268 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, bitsPerColorComponent);
269 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, bitsPerColorComponent);
270 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
271 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
273 _colorSaturation = 1.0f;
277 _hdrMaxBrightness = [prefs oo_floatForKey:@"hdr-max-brightness" defaultValue:1000.0f];
278 _hdrPaperWhiteBrightness = [prefs oo_floatForKey:@"hdr-paperwhite-brightness" defaultValue:200.0f];
279 if (bitsPerColorComponent == 16)
282 SDL_GL_SetAttribute(SDL_GL_PIXEL_TYPE_FLOAT, 1);
288 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vSyncPreference);
289 OOLog(
@"display.initGL",
@"V-Sync %@requested.", vSyncPreference ?
@"" :
@"not ");
298 if ([prefs oo_boolForKey:
@"anti-aliasing" defaultValue:NO])
300 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
301 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
304 OOLog(
@"display.mode.list",
@"%@",
@"CREATING MODE LIST");
305 [
self populateFullScreenModelist];
310 [
self loadFullscreenSettings];
311 [
self loadWindowSize];
314 firstScreen= (fullScreen) ? [
self modeAsSize: currentSize] : currentWindowSize;
315 viewSize = firstScreen;
317 OOLog(
@"display.initGL",
@"Trying %d-bpcc, 24-bit depth buffer", bitsPerColorComponent);
318 [
self createSurface];
323 OOLog(
@"display.initGL",
@"%@",
@"Trying 8-bpcc, 32-bit depth buffer");
324 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
325 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
326 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
327 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
328 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
329 [
self createSurface];
335 OOLog(
@"display.initGL",
@"%@",
@"Trying 5-bpcc, 16-bit depth buffer");
336 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
337 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
338 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
339 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
341 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
342 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
344 [
self createSurface];
348 char * errStr = SDL_GetError();
349 OOLogERR(
@"display.mode.error",
@"Could not create display surface: %s", errStr);
351 if (showSplashScreen)
353 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"splash-screen"];
354 [[NSUserDefaults standardUserDefaults] synchronize];
355 OOLogWARN(
@"display.mode.conflict",
@"Possible incompatibility between the splash screen and video drivers detected.");
356 OOLogWARN(
@"display.mode.conflict",
@"Oolite will start without showing the splash screen from now on. Override with 'oolite.exe -splash'");
365 OOLog(
@"display.initGL",
@"%@",
@"Achieved color / depth buffer sizes (bits):");
366 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &testAttrib);
367 OOLog(
@"display.initGL",
@"Red: %d", testAttrib);
368 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &testAttrib);
369 OOLog(
@"display.initGL",
@"Green: %d", testAttrib);
370 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &testAttrib);
371 OOLog(
@"display.initGL",
@"Blue: %d", testAttrib);
372 SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &testAttrib);
373 OOLog(
@"display.initGL",
@"Alpha: %d", testAttrib);
374 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &testAttrib);
375 OOLog(
@"display.initGL",
@"Depth Buffer: %d", testAttrib);
377 SDL_GL_GetAttribute(SDL_GL_PIXEL_TYPE_FLOAT, &testAttrib);
378 OOLog(
@"display.initGL",
@"Pixel type is float : %d", testAttrib);
382 if (vSyncPreference && SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &vSyncValue) == -1)
384 OOLogWARN(
@"display.initGL",
@"Could not enable V-Sync. Please check that your graphics driver supports the %@_swap_control extension.",
388 bounds.size.width = surface->w;
389 bounds.size.height = surface->h;
391 [
self autoShowMouse];
393 virtualJoystickPosition = NSMakePoint(0.0,0.0);
396 typedString = [[NSMutableString alloc] initWithString:@""];
398 isAlphabetKeyDown = NO;
400 timeIntervalAtLastClick = timeSinceLastMouseWheel = [NSDate timeIntervalSinceReferenceDate];
402 _mouseWheelDelta = 0.0f;
404 m_glContextInitialized = NO;
409- (void) endSplashScreen
412 if ([
self hdrOutput] && ![
self isOutputDisplayHDREnabled])
414 if (MessageBox(NULL,
"No primary display in HDR mode was detected.\n\n"
415 "If you continue, graphics will not be rendered as intended.\n"
416 "Click OK to launch anyway, or Cancel to exit.",
"oolite.exe - HDR requested",
417 MB_OKCANCEL | MB_ICONWARNING) == IDCANCEL)
424 if (!showSplashScreen)
return;
428 wasFullScreen = !fullScreen;
430 ShowWindow(SDL_Window,SW_RESTORE);
431 [
self initialiseGLWithSize: firstScreen];
435 int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL;
437 videoModeFlags |= (fullScreen) ? SDL_FULLSCREEN : SDL_RESIZABLE;
438 surface = SDL_SetVideoMode(firstScreen.width, firstScreen.height, 32, videoModeFlags);
440 if (!surface && fullScreen == YES)
442 [
self setFullScreenMode: NO];
443 videoModeFlags &= ~SDL_FULLSCREEN;
444 videoModeFlags |= SDL_RESIZABLE;
445 surface = SDL_SetVideoMode(currentWindowSize.width, currentWindowSize.height, 32, videoModeFlags);
448 SDL_putenv (
"SDL_VIDEO_WINDOW_POS=none");
457 SDL_Event dummyEvent;
458 while (SDL_PollEvent(&dummyEvent))
470 [
self autoShowMouse];
474- (void) initKeyMappingData
476 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
484 NSString *kbd = [prefs oo_stringForKey:@"keyboard-code" defaultValue:@"default"];
485 NSDictionary *subset = [kmap objectForKey:kbd];
487 [keyMappings_normal release];
488 keyMappings_normal = [[subset objectForKey:@"mapping_normal"] copy];
489 [keyMappings_shifted release];
490 keyMappings_shifted = [[subset objectForKey:@"mapping_shifted"] copy];
497 [typedString release];
500 [screenSizes release];
504 SDL_FreeSurface(surface);
508 if (keyMappings_normal)
509 [keyMappings_normal release];
511 if (keyMappings_shifted)
512 [keyMappings_shifted release];
518 [matrixManager release];
524- (void) autoShowMouse
529 if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE)
530 SDL_ShowCursor(SDL_DISABLE);
534 if (SDL_ShowCursor(SDL_QUERY) == SDL_DISABLE)
535 SDL_ShowCursor(SDL_ENABLE);
541 allowingStringInput = value;
545- (void) allowStringInput: (BOOL) value
555 return allowingStringInput;
559- (NSString *) typedString
565- (void) resetTypedString
567 [typedString setString:@""];
571- (void) setTypedString:(NSString*) value
573 [typedString setString:value];
589- (NSSize) backingViewSize
615 return gameController;
621 gameController = controller;
627 [
self autoShowMouse];
628 [
self setMouseInDeltaMode:OOMouseInteractionModeIsFlightMode(newMode)];
632- (BOOL) inFullScreenMode
638- (void) setFullScreenMode:(BOOL)fsm
643 [[NSUserDefaults standardUserDefaults]
644 setBool: fullScreen forKey:@"fullscreen"];
645 [[NSUserDefaults standardUserDefaults] synchronize];
649- (void) toggleScreenMode
651 [
self setFullScreenMode: !fullScreen];
653 [
self getCurrentMonitorInfo:&monitorInfo];
658 if(![
self isRunningOnPrimaryDisplayDevice])
660 [
self initialiseGLWithSize:NSMakeSize(monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
661 monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top)];
663 else [
self initialiseGLWithSize:[
self modeAsSize: currentSize]];
665 [
self initialiseGLWithSize:[
self modeAsSize: currentSize]];
669 [
self initialiseGLWithSize: currentWindowSize];
680- (void) setDisplayMode:(
int)mode fullScreen:(BOOL)fsm
682 [
self setFullScreenMode: fsm];
685 [
self initialiseGLWithSize: [
self modeAsSize: mode]];
689- (
int) indexOfCurrentSize
695- (void) setScreenSize: (
int)sizeIndex
697 currentSize=sizeIndex;
699 [
self initialiseGLWithSize: [
self modeAsSize: currentSize]];
703- (NSMutableArray *)getScreenSizeArray
709- (NSSize) modeAsSize:(
int)sizeIndex
711 NSDictionary *
mode=[screenSizes objectAtIndex: sizeIndex];
725 [
self drawRect: NSMakeRect(0, 0, viewSize.width, viewSize.height)];
728- (void) drawRect:(NSRect)rect
730 [
self updateScreenWithVideoMode:YES];
733- (void) updateScreenWithVideoMode:(BOOL) v_mode
735 if ((viewSize.width != surface->w)||(viewSize.height != surface->h))
738 m_glContextInitialized = NO;
740 viewSize.width = surface->w;
741 viewSize.height = surface->h;
744 if (m_glContextInitialized == NO)
746 [
self initialiseGLWithSize:viewSize useVideoMode:v_mode];
754 if (
UNIVERSE) [UNIVERSE drawUniverse];
758 glClearColor( 0.0, 0.0, 0.0, 0.0);
759 glClear( GL_COLOR_BUFFER_BIT);
762 SDL_GL_SwapBuffers();
765- (void) initSplashScreen
767 if (!showSplashScreen)
return;
770 SDL_Surface *image=NULL;
773 NSString *imagesDir = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Images"];
775 image = SDL_LoadBMP([[imagesDir stringByAppendingPathComponent:
@"splash.bmp"] UTF8String]);
779 SDL_FreeSurface(image);
780 OOLogWARN(
@"sdl.gameStart",
@"%@",
@"image 'splash.bmp' not found!");
781 [
self endSplashScreen];
792 dest.x = (GetSystemMetrics(SM_CXSCREEN)- dest.w)/2;
793 dest.y = (GetSystemMetrics(SM_CYSCREEN)-dest.h)/2;
794 SetWindowLong(SDL_Window,GWL_STYLE,GetWindowLong(SDL_Window,GWL_STYLE) & ~WS_CAPTION & ~WS_THICKFRAME);
795 ShowWindow(SDL_Window,SW_RESTORE);
796 MoveWindow(SDL_Window,dest.x,dest.y,dest.w,dest.h,TRUE);
808 surface = SDL_SetVideoMode(dest.w, dest.h, 32, SDL_HWSURFACE | SDL_OPENGL);
814 glViewport( 0, 0, dest.w, dest.h);
816 glEnable( GL_TEXTURE_2D );
817 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
818 glClear( GL_COLOR_BUFFER_BIT );
820 [matrixManager resetProjection];
821 [matrixManager orthoLeft: 0.0f right: dest.w bottom: dest.h top: 0.0 near: -1.0 far: 1.0];
822 [matrixManager syncProjection];
824 [matrixManager resetModelView];
825 [matrixManager syncModelView];
828 GLenum texture_format;
832 nOfColors = image->format->BytesPerPixel;
835 if (image->format->Rmask == 0x000000ff)
836 texture_format = GL_RGBA;
838 texture_format = GL_BGRA;
840 else if (nOfColors == 3)
842 if (image->format->Rmask == 0x000000ff)
843 texture_format = GL_RGB;
845 texture_format = GL_BGR;
847 SDL_FreeSurface(image);
848 OOLog(
@"Sdl.GameStart",
@"%@",
@"----- Encoding error within image 'splash.bmp'");
849 [
self endSplashScreen];
853 glGenTextures( 1, &texture );
854 glBindTexture( GL_TEXTURE_2D, texture );
857 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
858 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
861 glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, image->w, image->h, 0,
862 texture_format, GL_UNSIGNED_BYTE, image->pixels );
864 glBindTexture( GL_TEXTURE_2D, texture );
867 glTexCoord2i( 0, 0 );
869 glTexCoord2i( 1, 0 );
870 glVertex2i( dest.w, 0 );
871 glTexCoord2i( 1, 1 );
872 glVertex2i( dest.w, dest.h );
873 glTexCoord2i( 0, 1 );
874 glVertex2i( 0, dest.h );
878 SDL_GL_SwapBuffers();
879 [matrixManager resetModelView];
880 [matrixManager syncModelView];
883 SDL_FreeSurface( image );
885 glDeleteTextures(1, &texture);
887 glDisable( GL_TEXTURE_2D );
893- (MONITORINFOEX) currentMonitorInfo
899- (BOOL) getCurrentMonitorInfo:(MONITORINFOEX *)mInfo
901 HMONITOR hMon = MonitorFromWindow(SDL_Window, MONITOR_DEFAULTTOPRIMARY);
902 ZeroMemory(mInfo,
sizeof(MONITORINFOEX));
903 mInfo->cbSize =
sizeof(MONITORINFOEX);
904 if (GetMonitorInfo (hMon, (LPMONITORINFO)mInfo))
912- (BOOL) isRunningOnPrimaryDisplayDevice
915 [
self getCurrentMonitorInfo:&monitorInfo];
916 if (!(monitorInfo.dwFlags & MONITORINFOF_PRIMARY))
924- (void) grabMouseInsideGameWindow:(BOOL) value
929 GetWindowRect(SDL_Window, &gameWindowRect);
930 ClipCursor(&gameWindowRect);
936 grabMouseStatus = !!value;
940- (void) stringToClipboard:(NSString *)stringToCopy
944 const char *clipboardText = [stringToCopy cStringUsingEncoding:NSUTF8StringEncoding];
945 const size_t clipboardTextLength = strlen(clipboardText) + 1;
946 HGLOBAL clipboardMem = GlobalAlloc(GMEM_MOVEABLE, clipboardTextLength);
949 memcpy(GlobalLock(clipboardMem), clipboardText, clipboardTextLength);
950 GlobalUnlock(clipboardMem);
953 if (!SetClipboardData(CF_TEXT, clipboardMem))
955 OOLog(
@"stringToClipboard.failed",
@"Failed to copy string %@ to clipboard", stringToCopy);
960 GlobalFree(clipboardMem);
972 SDLMod modState = SDL_GetModState();
973 Uint8 *keyState = SDL_GetKeyState(NULL);
974 BYTE keyboardStatus[256];
975 #define OO_RESET_SDLKEY_MODIFIER(vkCode, kModCode, sdlkCode) do {\
976 if (keyboardStatus[vkCode] & 0x0080) \
978 modState |= kModCode; \
979 keyState[sdlkCode] = SDL_PRESSED; \
983 modState &= ~kModCode; \
984 keyState[sdlkCode] = SDL_RELEASED; \
987 if (GetKeyboardState(keyboardStatus))
1000 OO_RESET_SDLKEY_MODIFIER(VK_LCONTROL, KMOD_LCTRL, SDLK_LCTRL);
1001 OO_RESET_SDLKEY_MODIFIER(VK_RCONTROL, KMOD_RCTRL, SDLK_RCTRL);
1002 ctrl = (modState & KMOD_LCTRL || modState & KMOD_RCTRL);
1005 OO_RESET_SDLKEY_MODIFIER(VK_LSHIFT, KMOD_LSHIFT, SDLK_LSHIFT);
1006 OO_RESET_SDLKEY_MODIFIER(VK_RSHIFT, KMOD_RSHIFT, SDLK_RSHIFT);
1007 shift = (modState & KMOD_LSHIFT || modState & KMOD_RSHIFT);
1010 if (GetKeyState(VK_CAPITAL) & 0x0001)
1012 modState |= KMOD_CAPS;
1013 keyState[SDLK_CAPSLOCK] = SDL_PRESSED;
1017 modState &= ~KMOD_CAPS;
1018 keyState[SDLK_CAPSLOCK] = SDL_RELEASED;
1022 SDL_SetModState(modState);
1026- (void) setWindowBorderless:(BOOL)borderless
1028 LONG currentWindowStyle = GetWindowLong(SDL_Window, GWL_STYLE);
1031 if ((!borderless && (currentWindowStyle & WS_CAPTION)) ||
1032 (borderless && !(currentWindowStyle & WS_CAPTION)))
return;
1036 SetWindowLong(SDL_Window, GWL_STYLE, currentWindowStyle & ~WS_CAPTION & ~WS_THICKFRAME);
1040 SetWindowLong(SDL_Window, GWL_STYLE, currentWindowStyle |
1041 WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX );
1042 [
self refreshDarKOrLightMode];
1044 SetWindowPos(SDL_Window, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
1048- (void) refreshDarKOrLightMode
1050 int shouldSetDarkMode = [
self isDarkModeOn];
1051 DwmSetWindowAttribute (SDL_Window, DWMWA_USE_IMMERSIVE_DARK_MODE, &shouldSetDarkMode,
sizeof(shouldSetDarkMode));
1055- (BOOL) isDarkModeOn
1058 DWORD bufferSize =
sizeof(buffer);
1061 HRESULT resultRegGetValue = RegGetValueW(HKEY_CURRENT_USER, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
1062 L
"AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, buffer, &bufferSize);
1063 if (resultRegGetValue != ERROR_SUCCESS)
1069 int i = (
int)(buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]);
1076- (BOOL) atDesktopResolution
1078 return atDesktopResolution;
1088- (BOOL) isOutputDisplayHDREnabled
1090 UINT32 pathCount, modeCount;
1091 DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
1092 DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
1093 UINT32 flags = QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE;
1094 LONG tempResult = ERROR_SUCCESS;
1100 tempResult = GetDisplayConfigBufferSizes(flags, &pathCount, &modeCount);
1102 if (tempResult != ERROR_SUCCESS)
1104 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1109 pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(pathCount *
sizeof(DISPLAYCONFIG_PATH_INFO));
1110 if (!pPathInfoArray)
1112 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: -1");
1116 pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(modeCount *
sizeof(DISPLAYCONFIG_MODE_INFO));
1117 if (!pModeInfoArray)
1120 free(pPathInfoArray);
1121 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: -1");
1126 tempResult = QueryDisplayConfig(flags, &pathCount, pPathInfoArray, &modeCount, pModeInfoArray, NULL);
1128 if (tempResult != ERROR_SUCCESS)
1130 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1135 pPathInfoArray = realloc(pPathInfoArray, pathCount *
sizeof(DISPLAYCONFIG_PATH_INFO));
1136 if (!pPathInfoArray)
1138 OOLogERR(
@"gameView.isOutputDisplayHDREnabled",
@"Failed ro reallocate pPathInfoArray");
1141 pModeInfoArray = realloc(pModeInfoArray, modeCount *
sizeof(DISPLAYCONFIG_MODE_INFO));
1142 if (!pModeInfoArray)
1144 OOLogERR(
@"gameView.isOutputDisplayHDREnabled",
@"Failed to reallocate pModeInfoArray");
1150 }
while (tempResult == ERROR_INSUFFICIENT_BUFFER);
1152 if (tempResult != ERROR_SUCCESS)
1154 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1160 for (i = 0; i < pathCount; i++)
1162 DISPLAYCONFIG_PATH_INFO *path = &pPathInfoArray[i];
1164 DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
1165 targetName.header.adapterId = path->targetInfo.adapterId;
1166 targetName.header.id = path->targetInfo.id;
1167 targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
1168 targetName.header.size =
sizeof(targetName);
1169 tempResult = DisplayConfigGetDeviceInfo(&targetName.header);
1171 if (tempResult != ERROR_SUCCESS)
1173 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1178 DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = {};
1179 advColorInfo.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
1180 advColorInfo.header.adapterId = path->targetInfo.adapterId;
1181 advColorInfo.header.id = path->targetInfo.id;
1182 advColorInfo.header.size =
sizeof(advColorInfo);
1184 tempResult = DisplayConfigGetDeviceInfo(&advColorInfo.header);
1186 if (tempResult != ERROR_SUCCESS)
1188 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %d", HRESULT_FROM_WIN32(tempResult));
1192 char saveDeviceName[64];
1193 wchar_t wcsDeviceID[256];
1195 ZeroMemory(&dd,
sizeof(dd));
1197 EnumDisplayDevices(NULL, i, &dd, 0);
1198 BOOL isPrimaryDisplayDevice = dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE;
1200 strncpy(saveDeviceName, dd.DeviceName, 33);
1201 EnumDisplayDevices(saveDeviceName, 0, &dd, 0x00000001);
1202 mbstowcs(wcsDeviceID, dd.DeviceID, 129);
1207 if (isPrimaryDisplayDevice && !wcscmp(targetName.monitorDevicePath, wcsDeviceID) &&
1208 advColorInfo.advancedColorSupported && advColorInfo.advancedColorEnabled && !advColorInfo.wideColorEnforced)
1215 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"HDR display output requested - checking availability: %@", result ?
@"YES" :
@"NO");
1217 free (pModeInfoArray);
1218 free (pPathInfoArray);
1224- (float) hdrMaxBrightness
1226 return _hdrMaxBrightness;
1230- (void) setHDRMaxBrightness: (
float)newMaxBrightness
1234 _hdrMaxBrightness = newMaxBrightness;
1236 [[NSUserDefaults standardUserDefaults] setFloat:_hdrMaxBrightness forKey:@"hdr-max-brightness"];
1240- (float) hdrPaperWhiteBrightness
1242 return _hdrPaperWhiteBrightness;
1246- (void) setHDRPaperWhiteBrightness: (
float)newPaperWhiteBrightness
1250 _hdrPaperWhiteBrightness = newPaperWhiteBrightness;
1252 [[NSUserDefaults standardUserDefaults] setFloat:_hdrPaperWhiteBrightness forKey:@"hdr-paperwhite-brightness"];
1259- (BOOL) isRunningOnPrimaryDisplayDevice
1265- (void) grabMouseInsideGameWindow:(BOOL) value
1271- (void) stringToClipboard:(NSString *)stringToCopy
1283- (void) setWindowBorderless:(BOOL)borderless
1295- (BOOL) isOutputDisplayHDREnabled
1303- (void) initialiseGLWithSize:(NSSize) v_size
1305 [
self initialiseGLWithSize:v_size useVideoMode:YES];
1309- (void) initialiseGLWithSize:(NSSize) v_size useVideoMode:(BOOL) v_mode
1312 NSSize oldViewSize = viewSize;
1315 OOLog(
@"display.initGL",
@"Requested a new surface of %d x %d, %@.", (
int)viewSize.width, (
int)viewSize.height,(fullScreen ?
@"fullscreen" :
@"windowed"));
1316 SDL_GL_SwapBuffers();
1319 if (!updateContext)
return;
1322 settings.dmSize =
sizeof(DEVMODE);
1323 settings.dmDriverExtra = 0;
1324 EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &settings);
1326 WINDOWPLACEMENT windowPlacement;
1327 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
1328 GetWindowPlacement(SDL_Window, &windowPlacement);
1330 static BOOL lastWindowPlacementMaximized = NO;
1331 if (fullScreen && (windowPlacement.showCmd == SW_SHOWMAXIMIZED))
1335 lastWindowPlacementMaximized = YES;
1339 if (lastWindowPlacementMaximized)
1341 windowPlacement.showCmd = SW_SHOWMAXIMIZED;
1346 BOOL changingResolution = [
self isRunningOnPrimaryDisplayDevice] &&
1347 ((fullScreen && (settings.dmPelsWidth != viewSize.width || settings.dmPelsHeight != viewSize.height)) ||
1348 (wasFullScreen && (settings.dmPelsWidth != [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayWidth] intValue]
1349 || settings.dmPelsHeight != [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayHeight] intValue])));
1361 [
self getCurrentMonitorInfo: &monitorInfo];
1363 settings.dmPelsWidth = viewSize.width;
1364 settings.dmPelsHeight = viewSize.height;
1365 settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1370 if(lastWindowPlacementMaximized)
1372 CopyRect(&lastGoodRect, &windowPlacement.rcNormalPosition);
1374 windowPlacement.showCmd = SW_SHOWNORMAL;
1375 SetWindowPlacement(SDL_Window, &windowPlacement);
1377 else GetWindowRect(SDL_Window, &lastGoodRect);
1380 SetForegroundWindow(SDL_Window);
1381 if (changingResolution)
1383 if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &settings, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
1385 m_glContextInitialized = YES;
1386 OOLogERR(
@"displayMode.change.error",
@"Could not switch to requested display mode.");
1389 atDesktopResolution = settings.dmPelsWidth == [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayWidth] intValue]
1390 && settings.dmPelsHeight == [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayHeight] intValue];
1393 MoveWindow(SDL_Window, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, (
int)viewSize.width, (
int)viewSize.height, TRUE);
1396 [
self setWindowBorderless:YES];
1400 else if ( wasFullScreen )
1402 if (changingResolution)
1405 if (ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL) == DISP_CHANGE_SUCCESSFUL)
1407 atDesktopResolution = YES;
1419 [
self getCurrentMonitorInfo: &monitorInfo];
1421 if (lastWindowPlacementMaximized) CopyRect(&windowPlacement.rcNormalPosition, &lastGoodRect);
1422 SetWindowPlacement(SDL_Window, &windowPlacement);
1423 if (!lastWindowPlacementMaximized)
1425 MoveWindow(SDL_Window, (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left - (
int)viewSize.width)/2 +
1426 monitorInfo.rcMonitor.left,
1427 (monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top - (
int)viewSize.height)/2 +
1428 monitorInfo.rcMonitor.top,
1429 (
int)viewSize.width, (
int)viewSize.height, TRUE);
1432 [
self setWindowBorderless:NO];
1434 lastWindowPlacementMaximized = NO;
1435 ShowWindow(SDL_Window,SW_SHOW);
1439 saveSize = !wasFullScreen;
1441 GetClientRect(SDL_Window, &wDC);
1443 if (!fullScreen && (bounds.size.width != wDC.right - wDC.left
1444 || bounds.size.height != wDC.bottom - wDC.top))
1453 RECT desiredClientRect;
1454 GetWindowRect(SDL_Window, &desiredClientRect);
1455 AdjustWindowRect(&desiredClientRect, WS_CAPTION | WS_THICKFRAME, FALSE);
1456 SetWindowPos(SDL_Window, NULL, desiredClientRect.left, desiredClientRect.top,
1457 desiredClientRect.right - desiredClientRect.left,
1458 desiredClientRect.bottom - desiredClientRect.top, 0);
1460 GetClientRect(SDL_Window, &wDC);
1461 viewSize.width = wDC.right - wDC.left;
1462 viewSize.height = wDC.bottom - wDC.top;
1466 bounds.size.width = viewSize.width = wDC.right - wDC.left;
1467 bounds.size.height = viewSize.height = wDC.bottom - wDC.top;
1471 bounds.origin.x = monitorInfo.rcMonitor.left;
1472 bounds.origin.y = monitorInfo.rcMonitor.top;
1474 wasFullScreen=fullScreen;
1478 int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL;
1481 videoModeFlags |= SDL_NOFRAME;
1482 if (fullScreen == YES)
1484 videoModeFlags |= SDL_FULLSCREEN;
1488 videoModeFlags |= SDL_RESIZABLE;
1490 surface = SDL_SetVideoMode((
int)viewSize.width, (
int)viewSize.height, 32, videoModeFlags);
1492 if (!surface && fullScreen == YES)
1494 [
self setFullScreenMode: NO];
1495 viewSize = oldViewSize;
1496 videoModeFlags &= ~SDL_FULLSCREEN;
1497 videoModeFlags |= SDL_RESIZABLE;
1498 surface = SDL_SetVideoMode((
int)viewSize.width, (
int)viewSize.height, 32, videoModeFlags);
1504 OOLogERR(
@"display.mode.error",
@"Unable to change display mode: %s",SDL_GetError());
1508 bounds.size.width = surface->w;
1509 bounds.size.height = surface->h;
1512 OOLog(
@"display.initGL",
@"Created a new surface of %d x %d, %@.", (
int)viewSize.width, (
int)viewSize.height,(fullScreen ?
@"fullscreen" :
@"windowed"));
1514 if (viewSize.width/viewSize.height > 4.0/3.0) {
1515 display_z = 480.0 * bounds.size.width/bounds.size.height;
1516 x_offset = 240.0 * bounds.size.width/bounds.size.height;
1521 y_offset = 320.0 * bounds.size.height/bounds.size.width;
1524 if (surface != 0) SDL_FreeSurface(surface);
1526 [
self autoShowMouse];
1528 [[
self gameController] setUpBasicOpenGLStateWithSize:viewSize];
1529 SDL_GL_SwapBuffers();
1532 m_glContextInitialized = YES;
1536- (float) colorSaturation
1538 return _colorSaturation;
1542- (void) adjustColorSaturation:(
float)colorSaturationAdjustment;
1544 _colorSaturation += colorSaturationAdjustment;