Remove the RaiseWindow call from OnWindowRestored for now.
It seems like a net improvement in all the scenarios Sam and I could
think of, and looking at hg history it was added for fullscreen
window management specifically. Much of that code has changed since
then, but maybe it needs to stay there for that and simply be moved
to a fullscreen condition check.
It would solve this issue:
https://bugzilla.libsdl.org/show_bug.cgi?id=2439
As well as cases where on SteamOS, we hide/show specific Steam
overlay windows while expecting them to stay in the background, since
changing the window stacking order really angers the NVIDIA driver.
CR: Sam.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 #include "../SDL_internal.h"
23 /* The high-level video driver subsystem */
26 #include "SDL_video.h"
27 #include "SDL_sysvideo.h"
29 #include "SDL_pixels_c.h"
30 #include "SDL_rect_c.h"
31 #include "../events/SDL_events_c.h"
32 #include "../timer/SDL_timer_c.h"
34 #include "SDL_syswm.h"
37 #include "SDL_opengl.h"
38 #endif /* SDL_VIDEO_OPENGL */
40 #if SDL_VIDEO_OPENGL_ES
41 #include "SDL_opengles.h"
42 #endif /* SDL_VIDEO_OPENGL_ES */
44 /* GL and GLES2 headers conflict on Linux 32 bits */
45 #if SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL
46 #include "SDL_opengles2.h"
47 #endif /* SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL */
49 /* On Windows, windows.h defines CreateWindow */
54 /* Available video drivers */
55 static VideoBootStrap *bootstrap[] = {
56 #if SDL_VIDEO_DRIVER_COCOA
59 #if SDL_VIDEO_DRIVER_X11
62 #if SDL_VIDEO_DRIVER_MIR
65 #if SDL_VIDEO_DRIVER_DIRECTFB
68 #if SDL_VIDEO_DRIVER_WINDOWS
71 #if SDL_VIDEO_DRIVER_WINRT
74 #if SDL_VIDEO_DRIVER_HAIKU
77 #if SDL_VIDEO_DRIVER_PANDORA
80 #if SDL_VIDEO_DRIVER_UIKIT
83 #if SDL_VIDEO_DRIVER_ANDROID
86 #if SDL_VIDEO_DRIVER_PSP
89 #if SDL_VIDEO_DRIVER_RPI
92 #if SDL_VIDEO_DRIVER_WAYLAND
95 #if SDL_VIDEO_DRIVER_DUMMY
101 static SDL_VideoDevice *_this = NULL;
103 #define CHECK_WINDOW_MAGIC(window, retval) \
105 SDL_UninitializedVideo(); \
108 if (!window || window->magic != &_this->window_magic) { \
109 SDL_SetError("Invalid window"); \
113 #define CHECK_DISPLAY_INDEX(displayIndex, retval) \
115 SDL_UninitializedVideo(); \
118 SDL_assert(_this->displays != NULL); \
119 if (displayIndex < 0 || displayIndex >= _this->num_displays) { \
120 SDL_SetError("displayIndex must be in the range 0 - %d", \
121 _this->num_displays - 1); \
125 #define FULLSCREEN_MASK ( SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN )
128 /* Support for Mac OS X fullscreen spaces */
129 extern SDL_bool Cocoa_IsWindowInFullscreenSpace(SDL_Window * window);
130 extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state);
134 /* Support for framebuffer emulation using an accelerated renderer */
136 #define SDL_WINDOWTEXTUREDATA "_SDL_WindowTextureData"
139 SDL_Renderer *renderer;
140 SDL_Texture *texture;
144 } SDL_WindowTextureData;
147 ShouldUseTextureFramebuffer()
151 /* If there's no native framebuffer support then there's no option */
152 if (!_this->CreateWindowFramebuffer) {
156 /* If the user has specified a software renderer we can't use a
157 texture framebuffer, or renderer creation will go recursive.
159 hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
160 if (hint && SDL_strcasecmp(hint, "software") == 0) {
164 /* See if the user or application wants a specific behavior */
165 hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
174 /* Each platform has different performance characteristics */
175 #if defined(__WIN32__)
176 /* GDI BitBlt() is way faster than Direct3D dynamic textures right now.
180 #elif defined(__MACOSX__)
181 /* Mac OS X uses OpenGL as the native fast path */
184 #elif defined(__LINUX__)
185 /* Properly configured OpenGL drivers are faster than MIT-SHM */
187 /* Ugh, find a way to cache this value! */
190 SDL_GLContext context;
191 SDL_bool hasAcceleratedOpenGL = SDL_FALSE;
193 window = SDL_CreateWindow("OpenGL test", -32, -32, 32, 32, SDL_WINDOW_OPENGL|SDL_WINDOW_HIDDEN);
195 context = SDL_GL_CreateContext(window);
197 const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
198 const char *vendor = NULL;
200 glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
201 if (glGetStringFunc) {
202 vendor = (const char *) glGetStringFunc(GL_VENDOR);
204 /* Add more vendors here at will... */
206 (SDL_strstr(vendor, "ATI Technologies") ||
207 SDL_strstr(vendor, "NVIDIA"))) {
208 hasAcceleratedOpenGL = SDL_TRUE;
210 SDL_GL_DeleteContext(context);
212 SDL_DestroyWindow(window);
214 return hasAcceleratedOpenGL;
216 #elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
217 /* Let's be optimistic about this! */
224 /* Play it safe, assume that if there is a framebuffer driver that it's
225 optimized for the current platform.
232 SDL_CreateWindowTexture(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
234 SDL_WindowTextureData *data;
235 SDL_RendererInfo info;
238 data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
240 SDL_Renderer *renderer = NULL;
241 SDL_RendererInfo info;
243 const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
245 /* Check to see if there's a specific driver requested */
246 if (hint && *hint != '0' && *hint != '1' &&
247 SDL_strcasecmp(hint, "software") != 0) {
248 for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
249 SDL_GetRenderDriverInfo(i, &info);
250 if (SDL_strcasecmp(info.name, hint) == 0) {
251 renderer = SDL_CreateRenderer(window, i, 0);
258 for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
259 SDL_GetRenderDriverInfo(i, &info);
260 if (SDL_strcmp(info.name, "software") != 0) {
261 renderer = SDL_CreateRenderer(window, i, 0);
269 return SDL_SetError("No hardware accelerated renderers available");
272 /* Create the data after we successfully create the renderer (bug #1116) */
273 data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
275 SDL_DestroyRenderer(renderer);
276 return SDL_OutOfMemory();
278 SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
280 data->renderer = renderer;
283 /* Free any old texture and pixel data */
285 SDL_DestroyTexture(data->texture);
286 data->texture = NULL;
288 SDL_free(data->pixels);
291 if (SDL_GetRendererInfo(data->renderer, &info) < 0) {
295 /* Find the first format without an alpha channel */
296 *format = info.texture_formats[0];
297 for (i = 0; i < info.num_texture_formats; ++i) {
298 if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
299 !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
300 *format = info.texture_formats[i];
305 data->texture = SDL_CreateTexture(data->renderer, *format,
306 SDL_TEXTUREACCESS_STREAMING,
307 window->w, window->h);
308 if (!data->texture) {
312 /* Create framebuffer data */
313 data->bytes_per_pixel = SDL_BYTESPERPIXEL(*format);
314 data->pitch = (((window->w * data->bytes_per_pixel) + 3) & ~3);
315 data->pixels = SDL_malloc(window->h * data->pitch);
317 return SDL_OutOfMemory();
320 *pixels = data->pixels;
321 *pitch = data->pitch;
323 /* Make sure we're not double-scaling the viewport */
324 SDL_RenderSetViewport(data->renderer, NULL);
330 SDL_UpdateWindowTexture(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
332 SDL_WindowTextureData *data;
336 data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
337 if (!data || !data->texture) {
338 return SDL_SetError("No window texture data");
341 /* Update a single rect that contains subrects for best DMA performance */
342 if (SDL_GetSpanEnclosingRect(window->w, window->h, numrects, rects, &rect)) {
343 src = (void *)((Uint8 *)data->pixels +
344 rect.y * data->pitch +
345 rect.x * data->bytes_per_pixel);
346 if (SDL_UpdateTexture(data->texture, &rect, src, data->pitch) < 0) {
350 if (SDL_RenderCopy(data->renderer, data->texture, NULL, NULL) < 0) {
354 SDL_RenderPresent(data->renderer);
360 SDL_DestroyWindowTexture(_THIS, SDL_Window * window)
362 SDL_WindowTextureData *data;
364 data = SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, NULL);
369 SDL_DestroyTexture(data->texture);
371 if (data->renderer) {
372 SDL_DestroyRenderer(data->renderer);
374 SDL_free(data->pixels);
380 cmpmodes(const void *A, const void *B)
382 const SDL_DisplayMode *a = (const SDL_DisplayMode *) A;
383 const SDL_DisplayMode *b = (const SDL_DisplayMode *) B;
386 } else if (a->w != b->w) {
388 } else if (a->h != b->h) {
390 } else if (SDL_BITSPERPIXEL(a->format) != SDL_BITSPERPIXEL(b->format)) {
391 return SDL_BITSPERPIXEL(b->format) - SDL_BITSPERPIXEL(a->format);
392 } else if (SDL_PIXELLAYOUT(a->format) != SDL_PIXELLAYOUT(b->format)) {
393 return SDL_PIXELLAYOUT(b->format) - SDL_PIXELLAYOUT(a->format);
394 } else if (a->refresh_rate != b->refresh_rate) {
395 return b->refresh_rate - a->refresh_rate;
401 SDL_UninitializedVideo()
403 return SDL_SetError("Video subsystem has not been initialized");
407 SDL_GetNumVideoDrivers(void)
409 return SDL_arraysize(bootstrap) - 1;
413 SDL_GetVideoDriver(int index)
415 if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
416 return bootstrap[index]->name;
422 * Initialize the video and event subsystems -- determine native pixel format
425 SDL_VideoInit(const char *driver_name)
427 SDL_VideoDevice *video;
431 SDL_bool allow_screensaver;
433 /* Check to make sure we don't overwrite '_this' */
438 #if !SDL_TIMERS_DISABLED
442 /* Start the event loop */
443 if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0 ||
444 SDL_KeyboardInit() < 0 ||
445 SDL_MouseInit() < 0 ||
446 SDL_TouchInit() < 0) {
450 /* Select the proper video driver */
453 if (driver_name == NULL) {
454 driver_name = SDL_getenv("SDL_VIDEODRIVER");
456 if (driver_name != NULL) {
457 for (i = 0; bootstrap[i]; ++i) {
458 if (SDL_strncasecmp(bootstrap[i]->name, driver_name, SDL_strlen(driver_name)) == 0) {
459 if (bootstrap[i]->available()) {
460 video = bootstrap[i]->create(index);
466 for (i = 0; bootstrap[i]; ++i) {
467 if (bootstrap[i]->available()) {
468 video = bootstrap[i]->create(index);
477 return SDL_SetError("%s not available", driver_name);
479 return SDL_SetError("No available video device");
482 _this->name = bootstrap[i]->name;
483 _this->next_object_id = 1;
486 /* Set some very sane GL defaults */
487 _this->gl_config.driver_loaded = 0;
488 _this->gl_config.dll_handle = NULL;
489 SDL_GL_ResetAttributes();
491 _this->current_glwin_tls = SDL_TLSCreate();
492 _this->current_glctx_tls = SDL_TLSCreate();
494 /* Initialize the video subsystem */
495 if (_this->VideoInit(_this) < 0) {
500 /* Make sure some displays were added */
501 if (_this->num_displays == 0) {
503 return SDL_SetError("The video driver did not add any displays");
506 /* Add the renderer framebuffer emulation if desired */
507 if (ShouldUseTextureFramebuffer()) {
508 _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
509 _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
510 _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
513 /* Disable the screen saver by default. This is a change from <= 2.0.1,
514 but most things using SDL are games or media players; you wouldn't
515 want a screensaver to trigger if you're playing exclusively with a
516 joystick, or passively watching a movie. Things that use SDL but
517 function more like a normal desktop app should explicitly reenable the
519 hint = SDL_GetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER);
521 allow_screensaver = SDL_atoi(hint) ? SDL_TRUE : SDL_FALSE;
523 allow_screensaver = SDL_FALSE;
525 if (!allow_screensaver) {
526 SDL_DisableScreenSaver();
529 /* If we don't use a screen keyboard, turn on text input by default,
530 otherwise programs that expect to get text events without enabling
531 UNICODE input won't get any events.
533 Actually, come to think of it, you needed to call SDL_EnableUNICODE(1)
534 in SDL 1.2 before you got text input events. Hmm...
536 if (!SDL_HasScreenKeyboardSupport()) {
537 SDL_StartTextInput();
540 /* We're ready to go! */
545 SDL_GetCurrentVideoDriver()
548 SDL_UninitializedVideo();
555 SDL_GetVideoDevice(void)
561 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
563 SDL_VideoDisplay display;
567 display.desktop_mode = *desktop_mode;
569 display.current_mode = display.desktop_mode;
571 return SDL_AddVideoDisplay(&display);
575 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
577 SDL_VideoDisplay *displays;
581 SDL_realloc(_this->displays,
582 (_this->num_displays + 1) * sizeof(*displays));
584 index = _this->num_displays++;
585 displays[index] = *display;
586 displays[index].device = _this;
587 _this->displays = displays;
590 displays[index].name = SDL_strdup(display->name);
594 SDL_itoa(index, name, 10);
595 displays[index].name = SDL_strdup(name);
604 SDL_GetNumVideoDisplays(void)
607 SDL_UninitializedVideo();
610 return _this->num_displays;
614 SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
618 for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
619 if (display == &_this->displays[displayIndex]) {
624 /* Couldn't find the display, just use index 0 */
629 SDL_GetDisplayDriverData( int displayIndex )
631 CHECK_DISPLAY_INDEX( displayIndex, NULL );
633 return _this->displays[displayIndex].driverdata;
637 SDL_GetDisplayName(int displayIndex)
639 CHECK_DISPLAY_INDEX(displayIndex, NULL);
641 return _this->displays[displayIndex].name;
645 SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
647 CHECK_DISPLAY_INDEX(displayIndex, -1);
650 SDL_VideoDisplay *display = &_this->displays[displayIndex];
652 if (_this->GetDisplayBounds) {
653 if (_this->GetDisplayBounds(_this, display, rect) == 0) {
658 /* Assume that the displays are left to right */
659 if (displayIndex == 0) {
663 SDL_GetDisplayBounds(displayIndex-1, rect);
666 rect->w = display->current_mode.w;
667 rect->h = display->current_mode.h;
673 SDL_AddDisplayMode(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
675 SDL_DisplayMode *modes;
678 /* Make sure we don't already have the mode in the list */
679 modes = display->display_modes;
680 nmodes = display->num_display_modes;
681 for (i = 0; i < nmodes; ++i) {
682 if (cmpmodes(mode, &modes[i]) == 0) {
687 /* Go ahead and add the new mode */
688 if (nmodes == display->max_display_modes) {
691 (display->max_display_modes + 32) * sizeof(*modes));
695 display->display_modes = modes;
696 display->max_display_modes += 32;
698 modes[nmodes] = *mode;
699 display->num_display_modes++;
701 /* Re-sort video modes */
702 SDL_qsort(display->display_modes, display->num_display_modes,
703 sizeof(SDL_DisplayMode), cmpmodes);
709 SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
711 if (!display->num_display_modes && _this->GetDisplayModes) {
712 _this->GetDisplayModes(_this, display);
713 SDL_qsort(display->display_modes, display->num_display_modes,
714 sizeof(SDL_DisplayMode), cmpmodes);
716 return display->num_display_modes;
720 SDL_GetNumDisplayModes(int displayIndex)
722 CHECK_DISPLAY_INDEX(displayIndex, -1);
724 return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
728 SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
730 SDL_VideoDisplay *display;
732 CHECK_DISPLAY_INDEX(displayIndex, -1);
734 display = &_this->displays[displayIndex];
735 if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
736 return SDL_SetError("index must be in the range of 0 - %d",
737 SDL_GetNumDisplayModesForDisplay(display) - 1);
740 *mode = display->display_modes[index];
746 SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
748 SDL_VideoDisplay *display;
750 CHECK_DISPLAY_INDEX(displayIndex, -1);
752 display = &_this->displays[displayIndex];
754 *mode = display->desktop_mode;
760 SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
762 SDL_VideoDisplay *display;
764 CHECK_DISPLAY_INDEX(displayIndex, -1);
766 display = &_this->displays[displayIndex];
768 *mode = display->current_mode;
773 static SDL_DisplayMode *
774 SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
775 const SDL_DisplayMode * mode,
776 SDL_DisplayMode * closest)
778 Uint32 target_format;
779 int target_refresh_rate;
781 SDL_DisplayMode *current, *match;
783 if (!mode || !closest) {
784 SDL_SetError("Missing desired mode or closest mode parameter");
788 /* Default to the desktop format */
790 target_format = mode->format;
792 target_format = display->desktop_mode.format;
795 /* Default to the desktop refresh rate */
796 if (mode->refresh_rate) {
797 target_refresh_rate = mode->refresh_rate;
799 target_refresh_rate = display->desktop_mode.refresh_rate;
803 for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
804 current = &display->display_modes[i];
806 if (current->w && (current->w < mode->w)) {
807 /* Out of sorted modes large enough here */
810 if (current->h && (current->h < mode->h)) {
811 if (current->w && (current->w == mode->w)) {
812 /* Out of sorted modes large enough here */
815 /* Wider, but not tall enough, due to a different
816 aspect ratio. This mode must be skipped, but closer
817 modes may still follow. */
820 if (!match || current->w < match->w || current->h < match->h) {
824 if (current->format != match->format) {
825 /* Sorted highest depth to lowest */
826 if (current->format == target_format ||
827 (SDL_BITSPERPIXEL(current->format) >=
828 SDL_BITSPERPIXEL(target_format)
829 && SDL_PIXELTYPE(current->format) ==
830 SDL_PIXELTYPE(target_format))) {
835 if (current->refresh_rate != match->refresh_rate) {
836 /* Sorted highest refresh to lowest */
837 if (current->refresh_rate >= target_refresh_rate) {
844 closest->format = match->format;
846 closest->format = mode->format;
848 if (match->w && match->h) {
849 closest->w = match->w;
850 closest->h = match->h;
852 closest->w = mode->w;
853 closest->h = mode->h;
855 if (match->refresh_rate) {
856 closest->refresh_rate = match->refresh_rate;
858 closest->refresh_rate = mode->refresh_rate;
860 closest->driverdata = match->driverdata;
863 * Pick some reasonable defaults if the app and driver don't
866 if (!closest->format) {
867 closest->format = SDL_PIXELFORMAT_RGB888;
881 SDL_GetClosestDisplayMode(int displayIndex,
882 const SDL_DisplayMode * mode,
883 SDL_DisplayMode * closest)
885 SDL_VideoDisplay *display;
887 CHECK_DISPLAY_INDEX(displayIndex, NULL);
889 display = &_this->displays[displayIndex];
890 return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
894 SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
896 SDL_DisplayMode display_mode;
897 SDL_DisplayMode current_mode;
900 display_mode = *mode;
902 /* Default to the current mode */
903 if (!display_mode.format) {
904 display_mode.format = display->current_mode.format;
906 if (!display_mode.w) {
907 display_mode.w = display->current_mode.w;
909 if (!display_mode.h) {
910 display_mode.h = display->current_mode.h;
912 if (!display_mode.refresh_rate) {
913 display_mode.refresh_rate = display->current_mode.refresh_rate;
916 /* Get a good video mode, the closest one possible */
917 if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
918 return SDL_SetError("No video mode large enough for %dx%d",
919 display_mode.w, display_mode.h);
922 display_mode = display->desktop_mode;
925 /* See if there's anything left to do */
926 current_mode = display->current_mode;
927 if (SDL_memcmp(&display_mode, ¤t_mode, sizeof(display_mode)) == 0) {
931 /* Actually change the display mode */
932 if (!_this->SetDisplayMode) {
933 return SDL_SetError("Video driver doesn't support changing display mode");
935 if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
938 display->current_mode = display_mode;
943 SDL_GetWindowDisplayIndex(SDL_Window * window)
948 int closest_dist = 0x7FFFFFFF;
953 CHECK_WINDOW_MAGIC(window, -1);
955 if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
956 SDL_WINDOWPOS_ISCENTERED(window->x)) {
957 displayIndex = (window->x & 0xFFFF);
958 if (displayIndex >= _this->num_displays) {
963 if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
964 SDL_WINDOWPOS_ISCENTERED(window->y)) {
965 displayIndex = (window->y & 0xFFFF);
966 if (displayIndex >= _this->num_displays) {
972 /* Find the display containing the window */
973 for (i = 0; i < _this->num_displays; ++i) {
974 SDL_VideoDisplay *display = &_this->displays[i];
976 if (display->fullscreen_window == window) {
980 center.x = window->x + window->w / 2;
981 center.y = window->y + window->h / 2;
982 for (i = 0; i < _this->num_displays; ++i) {
983 SDL_GetDisplayBounds(i, &rect);
984 if (SDL_EnclosePoints(¢er, 1, &rect, NULL)) {
988 delta.x = center.x - (rect.x + rect.w / 2);
989 delta.y = center.y - (rect.y + rect.h / 2);
990 dist = (delta.x*delta.x + delta.y*delta.y);
991 if (dist < closest_dist) {
997 SDL_SetError("Couldn't find any displays");
1003 SDL_GetDisplayForWindow(SDL_Window *window)
1005 int displayIndex = SDL_GetWindowDisplayIndex(window);
1006 if (displayIndex >= 0) {
1007 return &_this->displays[displayIndex];
1014 SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
1016 CHECK_WINDOW_MAGIC(window, -1);
1019 window->fullscreen_mode = *mode;
1021 SDL_zero(window->fullscreen_mode);
1027 SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
1029 SDL_DisplayMode fullscreen_mode;
1030 SDL_VideoDisplay *display;
1033 return SDL_InvalidParamError("mode");
1036 CHECK_WINDOW_MAGIC(window, -1);
1038 fullscreen_mode = window->fullscreen_mode;
1039 if (!fullscreen_mode.w) {
1040 fullscreen_mode.w = window->w;
1042 if (!fullscreen_mode.h) {
1043 fullscreen_mode.h = window->h;
1046 display = SDL_GetDisplayForWindow(window);
1048 /* if in desktop size mode, just return the size of the desktop */
1049 if ( ( window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP )
1051 fullscreen_mode = display->desktop_mode;
1053 else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
1055 &fullscreen_mode)) {
1056 return SDL_SetError("Couldn't find display mode match");
1060 *mode = fullscreen_mode;
1066 SDL_GetWindowPixelFormat(SDL_Window * window)
1068 SDL_VideoDisplay *display;
1070 CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
1072 display = SDL_GetDisplayForWindow(window);
1073 return display->current_mode.format;
1077 SDL_RestoreMousePosition(SDL_Window *window)
1081 if (window == SDL_GetMouseFocus()) {
1082 SDL_GetMouseState(&x, &y);
1083 SDL_WarpMouseInWindow(window, x, y);
1088 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
1090 SDL_VideoDisplay *display;
1094 if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
1095 window->last_fullscreen_flags = window->flags;
1100 display = SDL_GetDisplayForWindow(window);
1103 /* Hide any other fullscreen windows */
1104 if (display->fullscreen_window &&
1105 display->fullscreen_window != window) {
1106 SDL_MinimizeWindow(display->fullscreen_window);
1110 /* See if anything needs to be done now */
1111 if ((display->fullscreen_window == window) == fullscreen) {
1112 if ((window->last_fullscreen_flags & FULLSCREEN_MASK) == (window->flags & FULLSCREEN_MASK)) {
1117 /* See if there are any fullscreen windows */
1118 for (other = _this->windows; other; other = other->next) {
1119 SDL_bool setDisplayMode = SDL_FALSE;
1121 if (other == window) {
1122 setDisplayMode = fullscreen;
1123 } else if (FULLSCREEN_VISIBLE(other) &&
1124 SDL_GetDisplayForWindow(other) == display) {
1125 setDisplayMode = SDL_TRUE;
1128 if (setDisplayMode) {
1129 SDL_DisplayMode fullscreen_mode;
1131 SDL_zero(fullscreen_mode);
1133 if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
1134 SDL_bool resized = SDL_TRUE;
1136 if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
1137 resized = SDL_FALSE;
1140 /* only do the mode change if we want exclusive fullscreen */
1141 if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
1142 SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
1144 SDL_SetDisplayModeForDisplay(display, NULL);
1147 if (_this->SetWindowFullscreen) {
1148 _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
1150 display->fullscreen_window = other;
1152 /* Generate a mode change event here */
1154 SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
1155 fullscreen_mode.w, fullscreen_mode.h);
1157 SDL_OnWindowResized(other);
1160 SDL_RestoreMousePosition(other);
1162 window->last_fullscreen_flags = window->flags;
1168 /* Nope, restore the desktop mode */
1169 SDL_SetDisplayModeForDisplay(display, NULL);
1171 if (_this->SetWindowFullscreen) {
1172 _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
1174 display->fullscreen_window = NULL;
1176 /* Generate a mode change event here */
1177 SDL_OnWindowResized(window);
1179 /* Restore the cursor position */
1180 SDL_RestoreMousePosition(window);
1182 window->last_fullscreen_flags = window->flags;
1185 #define CREATE_FLAGS \
1186 (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI)
1189 SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
1191 window->windowed.x = window->x;
1192 window->windowed.y = window->y;
1193 window->windowed.w = window->w;
1194 window->windowed.h = window->h;
1196 if (flags & SDL_WINDOW_MAXIMIZED) {
1197 SDL_MaximizeWindow(window);
1199 if (flags & SDL_WINDOW_MINIMIZED) {
1200 SDL_MinimizeWindow(window);
1202 if (flags & SDL_WINDOW_FULLSCREEN) {
1203 SDL_SetWindowFullscreen(window, flags);
1205 if (flags & SDL_WINDOW_INPUT_GRABBED) {
1206 SDL_SetWindowGrab(window, SDL_TRUE);
1208 if (!(flags & SDL_WINDOW_HIDDEN)) {
1209 SDL_ShowWindow(window);
1214 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
1220 /* Initialize the video system if needed */
1221 if (SDL_VideoInit(NULL) < 0) {
1226 /* Some platforms can't create zero-sized windows */
1234 /* Some platforms have OpenGL enabled by default */
1235 #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__
1236 flags |= SDL_WINDOW_OPENGL;
1238 if (flags & SDL_WINDOW_OPENGL) {
1239 if (!_this->GL_CreateContext) {
1240 SDL_SetError("No OpenGL support in video driver");
1243 if (SDL_GL_LoadLibrary(NULL) < 0) {
1248 /* Unless the user has specified the high-DPI disabling hint, respect the
1249 * SDL_WINDOW_ALLOW_HIGHDPI flag.
1251 if (flags & SDL_WINDOW_ALLOW_HIGHDPI) {
1252 hint = SDL_GetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED);
1253 if (hint && SDL_atoi(hint) > 0) {
1254 flags &= ~SDL_WINDOW_ALLOW_HIGHDPI;
1258 window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
1263 window->magic = &_this->window_magic;
1264 window->id = _this->next_object_id++;
1269 if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
1270 SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
1271 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1275 displayIndex = SDL_GetIndexOfDisplay(display);
1276 SDL_GetDisplayBounds(displayIndex, &bounds);
1277 if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
1278 window->x = bounds.x + (bounds.w - w) / 2;
1280 if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
1281 window->y = bounds.y + (bounds.h - h) / 2;
1284 window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
1285 window->last_fullscreen_flags = window->flags;
1286 window->brightness = 1.0f;
1287 window->next = _this->windows;
1288 window->is_destroying = SDL_FALSE;
1290 if (_this->windows) {
1291 _this->windows->prev = window;
1293 _this->windows = window;
1295 if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
1296 SDL_DestroyWindow(window);
1301 SDL_SetWindowTitle(window, title);
1303 SDL_FinishWindowCreation(window, flags);
1305 /* If the window was created fullscreen, make sure the mode code matches */
1306 SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
1312 SDL_CreateWindowFrom(const void *data)
1317 SDL_UninitializedVideo();
1320 window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
1325 window->magic = &_this->window_magic;
1326 window->id = _this->next_object_id++;
1327 window->flags = SDL_WINDOW_FOREIGN;
1328 window->last_fullscreen_flags = window->flags;
1329 window->is_destroying = SDL_FALSE;
1330 window->brightness = 1.0f;
1331 window->next = _this->windows;
1332 if (_this->windows) {
1333 _this->windows->prev = window;
1335 _this->windows = window;
1337 if (!_this->CreateWindowFrom ||
1338 _this->CreateWindowFrom(_this, window, data) < 0) {
1339 SDL_DestroyWindow(window);
1346 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
1348 char *title = window->title;
1349 SDL_Surface *icon = window->icon;
1351 if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
1352 return SDL_SetError("No OpenGL support in video driver");
1355 if (window->flags & SDL_WINDOW_FOREIGN) {
1356 /* Can't destroy and re-create foreign windows, hrm */
1357 flags |= SDL_WINDOW_FOREIGN;
1359 flags &= ~SDL_WINDOW_FOREIGN;
1362 /* Restore video mode, etc. */
1363 SDL_HideWindow(window);
1365 /* Tear down the old native window */
1366 if (window->surface) {
1367 window->surface->flags &= ~SDL_DONTFREE;
1368 SDL_FreeSurface(window->surface);
1370 if (_this->DestroyWindowFramebuffer) {
1371 _this->DestroyWindowFramebuffer(_this, window);
1373 if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
1374 _this->DestroyWindow(_this, window);
1377 if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
1378 if (flags & SDL_WINDOW_OPENGL) {
1379 if (SDL_GL_LoadLibrary(NULL) < 0) {
1383 SDL_GL_UnloadLibrary();
1387 window->title = NULL;
1388 window->icon = NULL;
1389 window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
1390 window->last_fullscreen_flags = window->flags;
1391 window->is_destroying = SDL_FALSE;
1393 if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
1394 if (_this->CreateWindow(_this, window) < 0) {
1395 if (flags & SDL_WINDOW_OPENGL) {
1396 SDL_GL_UnloadLibrary();
1403 SDL_SetWindowTitle(window, title);
1407 SDL_SetWindowIcon(window, icon);
1408 SDL_FreeSurface(icon);
1410 SDL_FinishWindowCreation(window, flags);
1416 SDL_GetWindowID(SDL_Window * window)
1418 CHECK_WINDOW_MAGIC(window, 0);
1424 SDL_GetWindowFromID(Uint32 id)
1431 for (window = _this->windows; window; window = window->next) {
1432 if (window->id == id) {
1440 SDL_GetWindowFlags(SDL_Window * window)
1442 CHECK_WINDOW_MAGIC(window, 0);
1444 return window->flags;
1448 SDL_SetWindowTitle(SDL_Window * window, const char *title)
1450 CHECK_WINDOW_MAGIC(window, );
1452 if (title == window->title) {
1455 SDL_free(window->title);
1456 if (title && *title) {
1457 window->title = SDL_strdup(title);
1459 window->title = NULL;
1462 if (_this->SetWindowTitle) {
1463 _this->SetWindowTitle(_this, window);
1468 SDL_GetWindowTitle(SDL_Window * window)
1470 CHECK_WINDOW_MAGIC(window, "");
1472 return window->title ? window->title : "";
1476 SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
1478 CHECK_WINDOW_MAGIC(window, );
1484 SDL_FreeSurface(window->icon);
1486 /* Convert the icon into ARGB8888 */
1487 window->icon = SDL_ConvertSurfaceFormat(icon, SDL_PIXELFORMAT_ARGB8888, 0);
1488 if (!window->icon) {
1492 if (_this->SetWindowIcon) {
1493 _this->SetWindowIcon(_this, window, window->icon);
1498 SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
1500 SDL_WindowUserData *prev, *data;
1502 CHECK_WINDOW_MAGIC(window, NULL);
1504 /* Input validation */
1505 if (name == NULL || name[0] == '\0') {
1506 SDL_InvalidParamError("name");
1510 /* See if the named data already exists */
1512 for (data = window->data; data; prev = data, data = data->next) {
1513 if (data->name && SDL_strcmp(data->name, name) == 0) {
1514 void *last_value = data->data;
1517 /* Set the new value */
1518 data->data = userdata;
1520 /* Delete this value */
1522 prev->next = data->next;
1524 window->data = data->next;
1526 SDL_free(data->name);
1533 /* Add new data to the window */
1535 data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
1536 data->name = SDL_strdup(name);
1537 data->data = userdata;
1538 data->next = window->data;
1539 window->data = data;
1545 SDL_GetWindowData(SDL_Window * window, const char *name)
1547 SDL_WindowUserData *data;
1549 CHECK_WINDOW_MAGIC(window, NULL);
1551 /* Input validation */
1552 if (name == NULL || name[0] == '\0') {
1553 SDL_InvalidParamError("name");
1557 for (data = window->data; data; data = data->next) {
1558 if (data->name && SDL_strcmp(data->name, name) == 0) {
1566 SDL_SetWindowPosition(SDL_Window * window, int x, int y)
1568 CHECK_WINDOW_MAGIC(window, );
1570 if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
1571 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1577 displayIndex = SDL_GetIndexOfDisplay(display);
1578 SDL_GetDisplayBounds(displayIndex, &bounds);
1579 if (SDL_WINDOWPOS_ISCENTERED(x)) {
1580 x = bounds.x + (bounds.w - window->w) / 2;
1582 if (SDL_WINDOWPOS_ISCENTERED(y)) {
1583 y = bounds.y + (bounds.h - window->h) / 2;
1587 if ((window->flags & SDL_WINDOW_FULLSCREEN)) {
1588 if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
1589 window->windowed.x = x;
1591 if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
1592 window->windowed.y = y;
1595 if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
1598 if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
1602 if (_this->SetWindowPosition) {
1603 _this->SetWindowPosition(_this, window);
1605 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
1610 SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
1612 CHECK_WINDOW_MAGIC(window, );
1614 /* Fullscreen windows are always at their display's origin */
1615 if (window->flags & SDL_WINDOW_FULLSCREEN) {
1633 SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered)
1635 CHECK_WINDOW_MAGIC(window, );
1636 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1637 const int want = (bordered != SDL_FALSE); /* normalize the flag. */
1638 const int have = ((window->flags & SDL_WINDOW_BORDERLESS) == 0);
1639 if ((want != have) && (_this->SetWindowBordered)) {
1641 window->flags &= ~SDL_WINDOW_BORDERLESS;
1643 window->flags |= SDL_WINDOW_BORDERLESS;
1645 _this->SetWindowBordered(_this, window, (SDL_bool) want);
1651 SDL_SetWindowSize(SDL_Window * window, int w, int h)
1653 CHECK_WINDOW_MAGIC(window, );
1655 SDL_InvalidParamError("w");
1659 SDL_InvalidParamError("h");
1663 /* Make sure we don't exceed any window size limits */
1664 if (window->min_w && w < window->min_w)
1668 if (window->max_w && w > window->max_w)
1672 if (window->min_h && h < window->min_h)
1676 if (window->max_h && h > window->max_h)
1681 /* FIXME: Should this change fullscreen modes? */
1682 if (window->flags & SDL_WINDOW_FULLSCREEN) {
1683 window->windowed.w = w;
1684 window->windowed.h = h;
1688 if (_this->SetWindowSize) {
1689 _this->SetWindowSize(_this, window);
1691 if (window->w == w && window->h == h) {
1692 /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
1693 SDL_OnWindowResized(window);
1699 SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
1701 CHECK_WINDOW_MAGIC(window, );
1711 SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h)
1713 CHECK_WINDOW_MAGIC(window, );
1715 SDL_InvalidParamError("min_w");
1719 SDL_InvalidParamError("min_h");
1723 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1724 window->min_w = min_w;
1725 window->min_h = min_h;
1726 if (_this->SetWindowMinimumSize) {
1727 _this->SetWindowMinimumSize(_this, window);
1729 /* Ensure that window is not smaller than minimal size */
1730 SDL_SetWindowSize(window, SDL_max(window->w, window->min_w), SDL_max(window->h, window->min_h));
1735 SDL_GetWindowMinimumSize(SDL_Window * window, int *min_w, int *min_h)
1737 CHECK_WINDOW_MAGIC(window, );
1739 *min_w = window->min_w;
1742 *min_h = window->min_h;
1747 SDL_SetWindowMaximumSize(SDL_Window * window, int max_w, int max_h)
1749 CHECK_WINDOW_MAGIC(window, );
1751 SDL_InvalidParamError("max_w");
1755 SDL_InvalidParamError("max_h");
1759 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1760 window->max_w = max_w;
1761 window->max_h = max_h;
1762 if (_this->SetWindowMaximumSize) {
1763 _this->SetWindowMaximumSize(_this, window);
1765 /* Ensure that window is not larger than maximal size */
1766 SDL_SetWindowSize(window, SDL_min(window->w, window->max_w), SDL_min(window->h, window->max_h));
1771 SDL_GetWindowMaximumSize(SDL_Window * window, int *max_w, int *max_h)
1773 CHECK_WINDOW_MAGIC(window, );
1775 *max_w = window->max_w;
1778 *max_h = window->max_h;
1783 SDL_ShowWindow(SDL_Window * window)
1785 CHECK_WINDOW_MAGIC(window, );
1787 if (window->flags & SDL_WINDOW_SHOWN) {
1791 if (_this->ShowWindow) {
1792 _this->ShowWindow(_this, window);
1794 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
1798 SDL_HideWindow(SDL_Window * window)
1800 CHECK_WINDOW_MAGIC(window, );
1802 if (!(window->flags & SDL_WINDOW_SHOWN)) {
1806 SDL_UpdateFullscreenMode(window, SDL_FALSE);
1808 if (_this->HideWindow) {
1809 _this->HideWindow(_this, window);
1811 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
1815 SDL_RaiseWindow(SDL_Window * window)
1817 CHECK_WINDOW_MAGIC(window, );
1819 if (!(window->flags & SDL_WINDOW_SHOWN)) {
1822 if (_this->RaiseWindow) {
1823 _this->RaiseWindow(_this, window);
1828 SDL_MaximizeWindow(SDL_Window * window)
1830 CHECK_WINDOW_MAGIC(window, );
1832 if (window->flags & SDL_WINDOW_MAXIMIZED) {
1836 /* !!! FIXME: should this check if the window is resizable? */
1838 if (_this->MaximizeWindow) {
1839 _this->MaximizeWindow(_this, window);
1844 SDL_MinimizeWindow(SDL_Window * window)
1846 CHECK_WINDOW_MAGIC(window, );
1848 if (window->flags & SDL_WINDOW_MINIMIZED) {
1852 SDL_UpdateFullscreenMode(window, SDL_FALSE);
1854 if (_this->MinimizeWindow) {
1855 _this->MinimizeWindow(_this, window);
1860 SDL_RestoreWindow(SDL_Window * window)
1862 CHECK_WINDOW_MAGIC(window, );
1864 if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
1868 if (_this->RestoreWindow) {
1869 _this->RestoreWindow(_this, window);
1874 SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
1876 CHECK_WINDOW_MAGIC(window, -1);
1878 flags &= FULLSCREEN_MASK;
1880 if ( flags == (window->flags & FULLSCREEN_MASK) ) {
1884 /* clear the previous flags and OR in the new ones */
1885 window->flags &= ~FULLSCREEN_MASK;
1886 window->flags |= flags;
1888 SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
1893 static SDL_Surface *
1894 SDL_CreateWindowFramebuffer(SDL_Window * window)
1900 Uint32 Rmask, Gmask, Bmask, Amask;
1902 if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
1906 if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
1910 if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
1914 return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
1918 SDL_GetWindowSurface(SDL_Window * window)
1920 CHECK_WINDOW_MAGIC(window, NULL);
1922 if (!window->surface_valid) {
1923 if (window->surface) {
1924 window->surface->flags &= ~SDL_DONTFREE;
1925 SDL_FreeSurface(window->surface);
1927 window->surface = SDL_CreateWindowFramebuffer(window);
1928 if (window->surface) {
1929 window->surface_valid = SDL_TRUE;
1930 window->surface->flags |= SDL_DONTFREE;
1933 return window->surface;
1937 SDL_UpdateWindowSurface(SDL_Window * window)
1941 CHECK_WINDOW_MAGIC(window, -1);
1945 full_rect.w = window->w;
1946 full_rect.h = window->h;
1947 return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
1951 SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
1954 CHECK_WINDOW_MAGIC(window, -1);
1956 if (!window->surface_valid) {
1957 return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
1960 return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
1964 SDL_SetWindowBrightness(SDL_Window * window, float brightness)
1969 CHECK_WINDOW_MAGIC(window, -1);
1971 SDL_CalculateGammaRamp(brightness, ramp);
1972 status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
1974 window->brightness = brightness;
1980 SDL_GetWindowBrightness(SDL_Window * window)
1982 CHECK_WINDOW_MAGIC(window, 1.0f);
1984 return window->brightness;
1988 SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
1989 const Uint16 * green,
1990 const Uint16 * blue)
1992 CHECK_WINDOW_MAGIC(window, -1);
1994 if (!_this->SetWindowGammaRamp) {
1995 return SDL_Unsupported();
1998 if (!window->gamma) {
1999 if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
2005 SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
2008 SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
2011 SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
2013 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
2014 return _this->SetWindowGammaRamp(_this, window, window->gamma);
2021 SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
2025 CHECK_WINDOW_MAGIC(window, -1);
2027 if (!window->gamma) {
2030 window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
2031 if (!window->gamma) {
2032 return SDL_OutOfMemory();
2034 window->saved_gamma = window->gamma + 3*256;
2036 if (_this->GetWindowGammaRamp) {
2037 if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
2041 /* Create an identity gamma ramp */
2042 for (i = 0; i < 256; ++i) {
2043 Uint16 value = (Uint16)((i << 8) | i);
2045 window->gamma[0*256+i] = value;
2046 window->gamma[1*256+i] = value;
2047 window->gamma[2*256+i] = value;
2050 SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
2054 SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
2057 SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
2060 SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
2066 SDL_UpdateWindowGrab(SDL_Window * window)
2068 if (_this->SetWindowGrab) {
2070 if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
2071 (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
2074 grabbed = SDL_FALSE;
2076 _this->SetWindowGrab(_this, window, grabbed);
2081 SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
2083 CHECK_WINDOW_MAGIC(window, );
2085 if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
2089 window->flags |= SDL_WINDOW_INPUT_GRABBED;
2091 window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
2093 SDL_UpdateWindowGrab(window);
2097 SDL_GetWindowGrab(SDL_Window * window)
2099 CHECK_WINDOW_MAGIC(window, SDL_FALSE);
2101 return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
2105 SDL_OnWindowShown(SDL_Window * window)
2107 SDL_OnWindowRestored(window);
2111 SDL_OnWindowHidden(SDL_Window * window)
2113 SDL_UpdateFullscreenMode(window, SDL_FALSE);
2117 SDL_OnWindowResized(SDL_Window * window)
2119 window->surface_valid = SDL_FALSE;
2120 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
2124 SDL_OnWindowMinimized(SDL_Window * window)
2126 SDL_UpdateFullscreenMode(window, SDL_FALSE);
2130 SDL_OnWindowRestored(SDL_Window * window)
2133 * FIXME: Is this fine to just remove this, or should it be preserved just
2134 * for the fullscreen case? In principle it seems like just hiding/showing
2135 * windows shouldn't affect the stacking order; maybe the right fix is to
2136 * re-decouple OnWindowShown and OnWindowRestored.
2138 //SDL_RaiseWindow(window);
2140 if (FULLSCREEN_VISIBLE(window)) {
2141 SDL_UpdateFullscreenMode(window, SDL_TRUE);
2146 SDL_OnWindowEnter(SDL_Window * window)
2148 if (_this->OnWindowEnter) {
2149 _this->OnWindowEnter(_this, window);
2154 SDL_OnWindowLeave(SDL_Window * window)
2159 SDL_OnWindowFocusGained(SDL_Window * window)
2161 SDL_Mouse *mouse = SDL_GetMouse();
2163 if (window->gamma && _this->SetWindowGammaRamp) {
2164 _this->SetWindowGammaRamp(_this, window, window->gamma);
2167 if (mouse && mouse->relative_mode) {
2168 SDL_SetMouseFocus(window);
2169 SDL_WarpMouseInWindow(window, window->w/2, window->h/2);
2172 SDL_UpdateWindowGrab(window);
2176 ShouldMinimizeOnFocusLoss(SDL_Window * window)
2180 if (!(window->flags & SDL_WINDOW_FULLSCREEN) || window->is_destroying) {
2185 if (Cocoa_IsWindowInFullscreenSpace(window)) {
2190 hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
2203 SDL_OnWindowFocusLost(SDL_Window * window)
2205 if (window->gamma && _this->SetWindowGammaRamp) {
2206 _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
2209 SDL_UpdateWindowGrab(window);
2211 if (ShouldMinimizeOnFocusLoss(window)) {
2212 SDL_MinimizeWindow(window);
2217 SDL_GetFocusWindow(void)
2224 for (window = _this->windows; window; window = window->next) {
2225 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
2233 SDL_DestroyWindow(SDL_Window * window)
2235 SDL_VideoDisplay *display;
2237 CHECK_WINDOW_MAGIC(window, );
2239 window->is_destroying = SDL_TRUE;
2241 /* Restore video mode, etc. */
2242 SDL_HideWindow(window);
2244 /* Make sure this window no longer has focus */
2245 if (SDL_GetKeyboardFocus() == window) {
2246 SDL_SetKeyboardFocus(NULL);
2248 if (SDL_GetMouseFocus() == window) {
2249 SDL_SetMouseFocus(NULL);
2252 /* make no context current if this is the current context window. */
2253 if (window->flags & SDL_WINDOW_OPENGL) {
2254 if (_this->current_glwin == window) {
2255 SDL_GL_MakeCurrent(window, NULL);
2259 if (window->surface) {
2260 window->surface->flags &= ~SDL_DONTFREE;
2261 SDL_FreeSurface(window->surface);
2263 if (_this->DestroyWindowFramebuffer) {
2264 _this->DestroyWindowFramebuffer(_this, window);
2266 if (_this->DestroyWindow) {
2267 _this->DestroyWindow(_this, window);
2269 if (window->flags & SDL_WINDOW_OPENGL) {
2270 SDL_GL_UnloadLibrary();
2273 display = SDL_GetDisplayForWindow(window);
2274 if (display->fullscreen_window == window) {
2275 display->fullscreen_window = NULL;
2278 /* Now invalidate magic */
2279 window->magic = NULL;
2281 /* Free memory associated with the window */
2282 SDL_free(window->title);
2283 SDL_FreeSurface(window->icon);
2284 SDL_free(window->gamma);
2285 while (window->data) {
2286 SDL_WindowUserData *data = window->data;
2288 window->data = data->next;
2289 SDL_free(data->name);
2293 /* Unlink the window from the list */
2295 window->next->prev = window->prev;
2298 window->prev->next = window->next;
2300 _this->windows = window->next;
2307 SDL_IsScreenSaverEnabled()
2312 return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
2316 SDL_EnableScreenSaver()
2321 if (!_this->suspend_screensaver) {
2324 _this->suspend_screensaver = SDL_FALSE;
2325 if (_this->SuspendScreenSaver) {
2326 _this->SuspendScreenSaver(_this);
2331 SDL_DisableScreenSaver()
2336 if (_this->suspend_screensaver) {
2339 _this->suspend_screensaver = SDL_TRUE;
2340 if (_this->SuspendScreenSaver) {
2341 _this->SuspendScreenSaver(_this);
2354 /* Halt event processing before doing anything else */
2358 SDL_QuitSubSystem(SDL_INIT_EVENTS);
2360 SDL_EnableScreenSaver();
2362 /* Clean up the system video */
2363 while (_this->windows) {
2364 SDL_DestroyWindow(_this->windows);
2366 _this->VideoQuit(_this);
2368 for (i = 0; i < _this->num_displays; ++i) {
2369 SDL_VideoDisplay *display = &_this->displays[i];
2370 for (j = display->num_display_modes; j--;) {
2371 SDL_free(display->display_modes[j].driverdata);
2372 display->display_modes[j].driverdata = NULL;
2374 SDL_free(display->display_modes);
2375 display->display_modes = NULL;
2376 SDL_free(display->desktop_mode.driverdata);
2377 display->desktop_mode.driverdata = NULL;
2378 SDL_free(display->driverdata);
2379 display->driverdata = NULL;
2381 if (_this->displays) {
2382 for (i = 0; i < _this->num_displays; ++i) {
2383 SDL_free(_this->displays[i].name);
2385 SDL_free(_this->displays);
2386 _this->displays = NULL;
2387 _this->num_displays = 0;
2389 SDL_free(_this->clipboard_text);
2390 _this->clipboard_text = NULL;
2396 SDL_GL_LoadLibrary(const char *path)
2401 return SDL_UninitializedVideo();
2403 if (_this->gl_config.driver_loaded) {
2404 if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
2405 return SDL_SetError("OpenGL library already loaded");
2409 if (!_this->GL_LoadLibrary) {
2410 return SDL_SetError("No dynamic GL support in video driver");
2412 retval = _this->GL_LoadLibrary(_this, path);
2415 ++_this->gl_config.driver_loaded;
2417 if (_this->GL_UnloadLibrary) {
2418 _this->GL_UnloadLibrary(_this);
2425 SDL_GL_GetProcAddress(const char *proc)
2430 SDL_UninitializedVideo();
2434 if (_this->GL_GetProcAddress) {
2435 if (_this->gl_config.driver_loaded) {
2436 func = _this->GL_GetProcAddress(_this, proc);
2438 SDL_SetError("No GL driver has been loaded");
2441 SDL_SetError("No dynamic GL support in video driver");
2447 SDL_GL_UnloadLibrary(void)
2450 SDL_UninitializedVideo();
2453 if (_this->gl_config.driver_loaded > 0) {
2454 if (--_this->gl_config.driver_loaded > 0) {
2457 if (_this->GL_UnloadLibrary) {
2458 _this->GL_UnloadLibrary(_this);
2463 static SDL_INLINE SDL_bool
2464 isAtLeastGL3(const char *verstr)
2466 return ( verstr && (SDL_atoi(verstr) >= 3) );
2470 SDL_GL_ExtensionSupported(const char *extension)
2472 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2473 const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
2474 const char *extensions;
2476 const char *where, *terminator;
2478 /* Extension names should not have spaces. */
2479 where = SDL_strchr(extension, ' ');
2480 if (where || *extension == '\0') {
2483 /* See if there's an environment variable override */
2484 start = SDL_getenv(extension);
2485 if (start && *start == '0') {
2489 /* Lookup the available extensions */
2491 glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
2492 if (!glGetStringFunc) {
2496 if (isAtLeastGL3((const char *) glGetStringFunc(GL_VERSION))) {
2497 const GLubyte *(APIENTRY * glGetStringiFunc) (GLenum, GLuint);
2498 void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
2502 glGetStringiFunc = SDL_GL_GetProcAddress("glGetStringi");
2503 glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
2504 if ((!glGetStringiFunc) || (!glGetIntegervFunc)) {
2508 #ifndef GL_NUM_EXTENSIONS
2509 #define GL_NUM_EXTENSIONS 0x821D
2511 glGetIntegervFunc(GL_NUM_EXTENSIONS, &num_exts);
2512 for (i = 0; i < num_exts; i++) {
2513 const char *thisext = (const char *) glGetStringiFunc(GL_EXTENSIONS, i);
2514 if (SDL_strcmp(thisext, extension) == 0) {
2522 /* Try the old way with glGetString(GL_EXTENSIONS) ... */
2524 extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
2529 * It takes a bit of care to be fool-proof about parsing the OpenGL
2530 * extensions string. Don't be fooled by sub-strings, etc.
2536 where = SDL_strstr(start, extension);
2540 terminator = where + SDL_strlen(extension);
2541 if (where == start || *(where - 1) == ' ')
2542 if (*terminator == ' ' || *terminator == '\0')
2554 SDL_GL_ResetAttributes()
2560 _this->gl_config.red_size = 3;
2561 _this->gl_config.green_size = 3;
2562 _this->gl_config.blue_size = 2;
2563 _this->gl_config.alpha_size = 0;
2564 _this->gl_config.buffer_size = 0;
2565 _this->gl_config.depth_size = 16;
2566 _this->gl_config.stencil_size = 0;
2567 _this->gl_config.double_buffer = 1;
2568 _this->gl_config.accum_red_size = 0;
2569 _this->gl_config.accum_green_size = 0;
2570 _this->gl_config.accum_blue_size = 0;
2571 _this->gl_config.accum_alpha_size = 0;
2572 _this->gl_config.stereo = 0;
2573 _this->gl_config.multisamplebuffers = 0;
2574 _this->gl_config.multisamplesamples = 0;
2575 _this->gl_config.retained_backing = 1;
2576 _this->gl_config.accelerated = -1; /* accelerated or not, both are fine */
2577 _this->gl_config.profile_mask = 0;
2578 #if SDL_VIDEO_OPENGL
2579 _this->gl_config.major_version = 2;
2580 _this->gl_config.minor_version = 1;
2581 #elif SDL_VIDEO_OPENGL_ES2
2582 _this->gl_config.major_version = 2;
2583 _this->gl_config.minor_version = 0;
2584 _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
2585 #elif SDL_VIDEO_OPENGL_ES
2586 _this->gl_config.major_version = 1;
2587 _this->gl_config.minor_version = 1;
2588 _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
2590 _this->gl_config.flags = 0;
2591 _this->gl_config.framebuffer_srgb_capable = 0;
2593 _this->gl_config.share_with_current_context = 0;
2597 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
2599 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2603 return SDL_UninitializedVideo();
2607 case SDL_GL_RED_SIZE:
2608 _this->gl_config.red_size = value;
2610 case SDL_GL_GREEN_SIZE:
2611 _this->gl_config.green_size = value;
2613 case SDL_GL_BLUE_SIZE:
2614 _this->gl_config.blue_size = value;
2616 case SDL_GL_ALPHA_SIZE:
2617 _this->gl_config.alpha_size = value;
2619 case SDL_GL_DOUBLEBUFFER:
2620 _this->gl_config.double_buffer = value;
2622 case SDL_GL_BUFFER_SIZE:
2623 _this->gl_config.buffer_size = value;
2625 case SDL_GL_DEPTH_SIZE:
2626 _this->gl_config.depth_size = value;
2628 case SDL_GL_STENCIL_SIZE:
2629 _this->gl_config.stencil_size = value;
2631 case SDL_GL_ACCUM_RED_SIZE:
2632 _this->gl_config.accum_red_size = value;
2634 case SDL_GL_ACCUM_GREEN_SIZE:
2635 _this->gl_config.accum_green_size = value;
2637 case SDL_GL_ACCUM_BLUE_SIZE:
2638 _this->gl_config.accum_blue_size = value;
2640 case SDL_GL_ACCUM_ALPHA_SIZE:
2641 _this->gl_config.accum_alpha_size = value;
2644 _this->gl_config.stereo = value;
2646 case SDL_GL_MULTISAMPLEBUFFERS:
2647 _this->gl_config.multisamplebuffers = value;
2649 case SDL_GL_MULTISAMPLESAMPLES:
2650 _this->gl_config.multisamplesamples = value;
2652 case SDL_GL_ACCELERATED_VISUAL:
2653 _this->gl_config.accelerated = value;
2655 case SDL_GL_RETAINED_BACKING:
2656 _this->gl_config.retained_backing = value;
2658 case SDL_GL_CONTEXT_MAJOR_VERSION:
2659 _this->gl_config.major_version = value;
2661 case SDL_GL_CONTEXT_MINOR_VERSION:
2662 _this->gl_config.minor_version = value;
2664 case SDL_GL_CONTEXT_EGL:
2665 /* FIXME: SDL_GL_CONTEXT_EGL to be deprecated in SDL 2.1 */
2667 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
2669 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
2672 case SDL_GL_CONTEXT_FLAGS:
2673 if( value & ~(SDL_GL_CONTEXT_DEBUG_FLAG |
2674 SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG |
2675 SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG |
2676 SDL_GL_CONTEXT_RESET_ISOLATION_FLAG) ) {
2677 retval = SDL_SetError("Unknown OpenGL context flag %d", value);
2680 _this->gl_config.flags = value;
2682 case SDL_GL_CONTEXT_PROFILE_MASK:
2684 value != SDL_GL_CONTEXT_PROFILE_CORE &&
2685 value != SDL_GL_CONTEXT_PROFILE_COMPATIBILITY &&
2686 value != SDL_GL_CONTEXT_PROFILE_ES ) {
2687 retval = SDL_SetError("Unknown OpenGL context profile %d", value);
2690 _this->gl_config.profile_mask = value;
2692 case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
2693 _this->gl_config.share_with_current_context = value;
2695 case SDL_GL_FRAMEBUFFER_SRGB_CAPABLE:
2696 _this->gl_config.framebuffer_srgb_capable = value;
2699 retval = SDL_SetError("Unknown OpenGL attribute");
2704 return SDL_Unsupported();
2705 #endif /* SDL_VIDEO_OPENGL */
2709 SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
2711 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2712 void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
2713 GLenum(APIENTRY * glGetErrorFunc) (void);
2717 glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
2718 if (!glGetIntegervFunc) {
2722 glGetErrorFunc = SDL_GL_GetProcAddress("glGetError");
2723 if (!glGetErrorFunc) {
2727 /* Clear value in any case */
2731 case SDL_GL_RED_SIZE:
2732 attrib = GL_RED_BITS;
2734 case SDL_GL_BLUE_SIZE:
2735 attrib = GL_BLUE_BITS;
2737 case SDL_GL_GREEN_SIZE:
2738 attrib = GL_GREEN_BITS;
2740 case SDL_GL_ALPHA_SIZE:
2741 attrib = GL_ALPHA_BITS;
2743 case SDL_GL_DOUBLEBUFFER:
2744 #if SDL_VIDEO_OPENGL
2745 attrib = GL_DOUBLEBUFFER;
2748 /* OpenGL ES 1.0 and above specifications have EGL_SINGLE_BUFFER */
2749 /* parameter which switches double buffer to single buffer. OpenGL ES */
2750 /* SDL driver must set proper value after initialization */
2751 *value = _this->gl_config.double_buffer;
2754 case SDL_GL_DEPTH_SIZE:
2755 attrib = GL_DEPTH_BITS;
2757 case SDL_GL_STENCIL_SIZE:
2758 attrib = GL_STENCIL_BITS;
2760 #if SDL_VIDEO_OPENGL
2761 case SDL_GL_ACCUM_RED_SIZE:
2762 attrib = GL_ACCUM_RED_BITS;
2764 case SDL_GL_ACCUM_GREEN_SIZE:
2765 attrib = GL_ACCUM_GREEN_BITS;
2767 case SDL_GL_ACCUM_BLUE_SIZE:
2768 attrib = GL_ACCUM_BLUE_BITS;
2770 case SDL_GL_ACCUM_ALPHA_SIZE:
2771 attrib = GL_ACCUM_ALPHA_BITS;
2777 case SDL_GL_ACCUM_RED_SIZE:
2778 case SDL_GL_ACCUM_GREEN_SIZE:
2779 case SDL_GL_ACCUM_BLUE_SIZE:
2780 case SDL_GL_ACCUM_ALPHA_SIZE:
2782 /* none of these are supported in OpenGL ES */
2786 case SDL_GL_MULTISAMPLEBUFFERS:
2787 #if SDL_VIDEO_OPENGL
2788 attrib = GL_SAMPLE_BUFFERS_ARB;
2790 attrib = GL_SAMPLE_BUFFERS;
2793 case SDL_GL_MULTISAMPLESAMPLES:
2794 #if SDL_VIDEO_OPENGL
2795 attrib = GL_SAMPLES_ARB;
2797 attrib = GL_SAMPLES;
2800 case SDL_GL_BUFFER_SIZE:
2806 * there doesn't seem to be a single flag in OpenGL
2809 glGetIntegervFunc(GL_RED_BITS, &component);
2811 glGetIntegervFunc(GL_GREEN_BITS, &component);
2813 glGetIntegervFunc(GL_BLUE_BITS, &component);
2815 glGetIntegervFunc(GL_ALPHA_BITS, &component);
2821 case SDL_GL_ACCELERATED_VISUAL:
2823 /* FIXME: How do we get this information? */
2824 *value = (_this->gl_config.accelerated != 0);
2827 case SDL_GL_RETAINED_BACKING:
2829 *value = _this->gl_config.retained_backing;
2832 case SDL_GL_CONTEXT_MAJOR_VERSION:
2834 *value = _this->gl_config.major_version;
2837 case SDL_GL_CONTEXT_MINOR_VERSION:
2839 *value = _this->gl_config.minor_version;
2842 case SDL_GL_CONTEXT_EGL:
2843 /* FIXME: SDL_GL_CONTEXT_EGL to be deprecated in SDL 2.1 */
2845 if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
2853 case SDL_GL_CONTEXT_FLAGS:
2855 *value = _this->gl_config.flags;
2858 case SDL_GL_CONTEXT_PROFILE_MASK:
2860 *value = _this->gl_config.profile_mask;
2863 case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
2865 *value = _this->gl_config.share_with_current_context;
2868 case SDL_GL_FRAMEBUFFER_SRGB_CAPABLE:
2870 *value = _this->gl_config.framebuffer_srgb_capable;
2874 return SDL_SetError("Unknown OpenGL attribute");
2877 glGetIntegervFunc(attrib, (GLint *) value);
2878 error = glGetErrorFunc();
2879 if (error != GL_NO_ERROR) {
2880 if (error == GL_INVALID_ENUM) {
2881 return SDL_SetError("OpenGL error: GL_INVALID_ENUM");
2882 } else if (error == GL_INVALID_VALUE) {
2883 return SDL_SetError("OpenGL error: GL_INVALID_VALUE");
2885 return SDL_SetError("OpenGL error: %08X", error);
2889 return SDL_Unsupported();
2890 #endif /* SDL_VIDEO_OPENGL */
2894 SDL_GL_CreateContext(SDL_Window * window)
2896 SDL_GLContext ctx = NULL;
2897 CHECK_WINDOW_MAGIC(window, NULL);
2899 if (!(window->flags & SDL_WINDOW_OPENGL)) {
2900 SDL_SetError("The specified window isn't an OpenGL window");
2904 ctx = _this->GL_CreateContext(_this, window);
2906 /* Creating a context is assumed to make it current in the SDL driver. */
2908 _this->current_glwin = window;
2909 _this->current_glctx = ctx;
2910 SDL_TLSSet(_this->current_glwin_tls, window, NULL);
2911 SDL_TLSSet(_this->current_glctx_tls, ctx, NULL);
2917 SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx)
2921 if (window == SDL_GL_GetCurrentWindow() &&
2922 ctx == SDL_GL_GetCurrentContext()) {
2923 /* We're already current. */
2930 CHECK_WINDOW_MAGIC(window, -1);
2932 if (!(window->flags & SDL_WINDOW_OPENGL)) {
2933 return SDL_SetError("The specified window isn't an OpenGL window");
2937 retval = _this->GL_MakeCurrent(_this, window, ctx);
2939 _this->current_glwin = window;
2940 _this->current_glctx = ctx;
2941 SDL_TLSSet(_this->current_glwin_tls, window, NULL);
2942 SDL_TLSSet(_this->current_glctx_tls, ctx, NULL);
2948 SDL_GL_GetCurrentWindow(void)
2951 SDL_UninitializedVideo();
2954 return (SDL_Window *)SDL_TLSGet(_this->current_glwin_tls);
2958 SDL_GL_GetCurrentContext(void)
2961 SDL_UninitializedVideo();
2964 return (SDL_GLContext)SDL_TLSGet(_this->current_glctx_tls);
2967 void SDL_GL_GetDrawableSize(SDL_Window * window, int *w, int *h)
2969 CHECK_WINDOW_MAGIC(window, );
2971 if (_this->GL_GetDrawableSize) {
2972 _this->GL_GetDrawableSize(_this, window, w, h);
2974 SDL_GetWindowSize(window, w, h);
2979 SDL_GL_SetSwapInterval(int interval)
2982 return SDL_UninitializedVideo();
2983 } else if (SDL_GL_GetCurrentContext() == NULL) {
2984 return SDL_SetError("No OpenGL context has been made current");
2985 } else if (_this->GL_SetSwapInterval) {
2986 return _this->GL_SetSwapInterval(_this, interval);
2988 return SDL_SetError("Setting the swap interval is not supported");
2993 SDL_GL_GetSwapInterval(void)
2997 } else if (SDL_GL_GetCurrentContext() == NULL) {
2999 } else if (_this->GL_GetSwapInterval) {
3000 return _this->GL_GetSwapInterval(_this);
3007 SDL_GL_SwapWindow(SDL_Window * window)
3009 CHECK_WINDOW_MAGIC(window, );
3011 if (!(window->flags & SDL_WINDOW_OPENGL)) {
3012 SDL_SetError("The specified window isn't an OpenGL window");
3016 if (SDL_GL_GetCurrentWindow() != window) {
3017 SDL_SetError("The specified window has not been made current");
3021 _this->GL_SwapWindow(_this, window);
3025 SDL_GL_DeleteContext(SDL_GLContext context)
3027 if (!_this || !context) {
3031 if (SDL_GL_GetCurrentContext() == context) {
3032 SDL_GL_MakeCurrent(NULL, NULL);
3035 _this->GL_DeleteContext(_this, context);
3040 * Utility function used by SDL_WM_SetIcon(); flags & 1 for color key, flags
3041 * & 2 for alpha channel.
3044 CreateMaskFromColorKeyOrAlpha(SDL_Surface * icon, Uint8 * mask, int flags)
3048 #define SET_MASKBIT(icon, x, y, mask) \
3049 mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
3051 colorkey = icon->format->colorkey;
3052 switch (icon->format->BytesPerPixel) {
3056 for (y = 0; y < icon->h; ++y) {
3057 pixels = (Uint8 *) icon->pixels + y * icon->pitch;
3058 for (x = 0; x < icon->w; ++x) {
3059 if (*pixels++ == colorkey) {
3060 SET_MASKBIT(icon, x, y, mask);
3070 for (y = 0; y < icon->h; ++y) {
3071 pixels = (Uint16 *) icon->pixels + y * icon->pitch / 2;
3072 for (x = 0; x < icon->w; ++x) {
3073 if ((flags & 1) && *pixels == colorkey) {
3074 SET_MASKBIT(icon, x, y, mask);
3075 } else if ((flags & 2)
3076 && (*pixels & icon->format->Amask) == 0) {
3077 SET_MASKBIT(icon, x, y, mask);
3088 for (y = 0; y < icon->h; ++y) {
3089 pixels = (Uint32 *) icon->pixels + y * icon->pitch / 4;
3090 for (x = 0; x < icon->w; ++x) {
3091 if ((flags & 1) && *pixels == colorkey) {
3092 SET_MASKBIT(icon, x, y, mask);
3093 } else if ((flags & 2)
3094 && (*pixels & icon->format->Amask) == 0) {
3095 SET_MASKBIT(icon, x, y, mask);
3106 * Sets the window manager icon for the display window.
3109 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
3111 if (icon && _this->SetIcon) {
3112 /* Generate a mask if necessary, and create the icon! */
3114 int mask_len = icon->h * (icon->w + 7) / 8;
3116 mask = (Uint8 *) SDL_malloc(mask_len);
3120 SDL_memset(mask, ~0, mask_len);
3121 if (icon->flags & SDL_SRCCOLORKEY)
3123 if (icon->flags & SDL_SRCALPHA)
3126 CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
3128 _this->SetIcon(_this, icon, mask);
3131 _this->SetIcon(_this, icon, mask);
3138 SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info)
3140 CHECK_WINDOW_MAGIC(window, SDL_FALSE);
3145 info->subsystem = SDL_SYSWM_UNKNOWN;
3147 if (!_this->GetWindowWMInfo) {
3150 return (_this->GetWindowWMInfo(_this, window, info));
3154 SDL_StartTextInput(void)
3158 /* First, enable text events */
3159 SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE);
3160 SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
3162 /* Then show the on-screen keyboard, if any */
3163 window = SDL_GetFocusWindow();
3164 if (window && _this && _this->ShowScreenKeyboard) {
3165 _this->ShowScreenKeyboard(_this, window);
3168 /* Finally start the text input system */
3169 if (_this && _this->StartTextInput) {
3170 _this->StartTextInput(_this);
3175 SDL_IsTextInputActive(void)
3177 return (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE);
3181 SDL_StopTextInput(void)
3185 /* Stop the text input system */
3186 if (_this && _this->StopTextInput) {
3187 _this->StopTextInput(_this);
3190 /* Hide the on-screen keyboard, if any */
3191 window = SDL_GetFocusWindow();
3192 if (window && _this && _this->HideScreenKeyboard) {
3193 _this->HideScreenKeyboard(_this, window);
3196 /* Finally disable text events */
3197 SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
3198 SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
3202 SDL_SetTextInputRect(SDL_Rect *rect)
3204 if (_this && _this->SetTextInputRect) {
3205 _this->SetTextInputRect(_this, rect);
3210 SDL_HasScreenKeyboardSupport(void)
3212 if (_this && _this->HasScreenKeyboardSupport) {
3213 return _this->HasScreenKeyboardSupport(_this);
3219 SDL_IsScreenKeyboardShown(SDL_Window *window)
3221 if (window && _this && _this->IsScreenKeyboardShown) {
3222 return _this->IsScreenKeyboardShown(_this, window);
3227 #if SDL_VIDEO_DRIVER_WINDOWS
3228 #include "windows/SDL_windowsmessagebox.h"
3230 #if SDL_VIDEO_DRIVER_WINRT
3231 #include "winrt/SDL_winrtmessagebox.h"
3233 #if SDL_VIDEO_DRIVER_COCOA
3234 #include "cocoa/SDL_cocoamessagebox.h"
3236 #if SDL_VIDEO_DRIVER_UIKIT
3237 #include "uikit/SDL_uikitmessagebox.h"
3239 #if SDL_VIDEO_DRIVER_X11
3240 #include "x11/SDL_x11messagebox.h"
3243 static SDL_bool SDL_MessageboxValidForDriver(const SDL_MessageBoxData *messageboxdata, SDL_SYSWM_TYPE drivertype)
3246 SDL_Window *window = messageboxdata->window;
3252 SDL_VERSION(&info.version);
3253 if (!SDL_GetWindowWMInfo(window, &info)) {
3256 return (info.subsystem == drivertype);
3261 SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
3265 SDL_bool relative_mode;
3266 int show_cursor_prev;
3268 if (!messageboxdata) {
3269 return SDL_InvalidParamError("messageboxdata");
3272 relative_mode = SDL_GetRelativeMouseMode();
3273 SDL_SetRelativeMouseMode(SDL_FALSE);
3274 show_cursor_prev = SDL_ShowCursor(1);
3277 buttonid = &dummybutton;
3280 if (_this && _this->ShowMessageBox) {
3281 retval = _this->ShowMessageBox(_this, messageboxdata, buttonid);
3284 /* It's completely fine to call this function before video is initialized */
3285 #if SDL_VIDEO_DRIVER_WINDOWS
3287 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WINDOWS) &&
3288 WIN_ShowMessageBox(messageboxdata, buttonid) == 0) {
3292 #if SDL_VIDEO_DRIVER_WINRT
3294 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WINRT) &&
3295 WINRT_ShowMessageBox(messageboxdata, buttonid) == 0) {
3299 #if SDL_VIDEO_DRIVER_COCOA
3301 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_COCOA) &&
3302 Cocoa_ShowMessageBox(messageboxdata, buttonid) == 0) {
3306 #if SDL_VIDEO_DRIVER_UIKIT
3308 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_UIKIT) &&
3309 UIKit_ShowMessageBox(messageboxdata, buttonid) == 0) {
3313 #if SDL_VIDEO_DRIVER_X11
3315 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_X11) &&
3316 X11_ShowMessageBox(messageboxdata, buttonid) == 0) {
3321 SDL_SetError("No message system available");
3324 SDL_ShowCursor(show_cursor_prev);
3325 SDL_SetRelativeMouseMode(relative_mode);
3331 SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window)
3333 SDL_MessageBoxData data;
3334 SDL_MessageBoxButtonData button;
3339 data.message = message;
3340 data.numbuttons = 1;
3341 data.buttons = &button;
3342 data.window = window;
3345 button.flags |= SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
3346 button.flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
3349 return SDL_ShowMessageBox(&data, NULL);
3353 SDL_ShouldAllowTopmost(void)
3355 const char *hint = SDL_GetHint(SDL_HINT_ALLOW_TOPMOST);
3366 /* vi: set ts=4 sw=4 expandtab: */