src/video/SDL_video.c
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Wed, 24 Apr 2013 12:20:51 -0700
changeset 7107 2fcf7bf1d2b2
parent 7091 ff07fad908f8
child 7112 a1a723edea64
permissions -rw-r--r--
Move cursor into window when enabling relative mode or gaining focus in relative mode.

This prevents wonky behavior where the clicks won't go to the window
because the cursor was outside it when we enabled relative mode.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     4 
     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.
     8 
     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:
    12 
    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.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* The high-level video driver subsystem */
    24 
    25 #include "SDL.h"
    26 #include "SDL_video.h"
    27 #include "SDL_sysvideo.h"
    28 #include "SDL_blit.h"
    29 #include "SDL_pixels_c.h"
    30 #include "SDL_rect_c.h"
    31 #include "../events/SDL_events_c.h"
    32 
    33 #if SDL_VIDEO_OPENGL
    34 #include "SDL_opengl.h"
    35 #endif /* SDL_VIDEO_OPENGL */
    36 
    37 #if SDL_VIDEO_OPENGL_ES
    38 #include "SDL_opengles.h"
    39 #endif /* SDL_VIDEO_OPENGL_ES */
    40 
    41 #if SDL_VIDEO_OPENGL_ES2
    42 #include "SDL_opengles2.h"
    43 #endif /* SDL_VIDEO_OPENGL_ES2 */
    44 
    45 #include "SDL_syswm.h"
    46 
    47 /* On Windows, windows.h defines CreateWindow */
    48 #ifdef CreateWindow
    49 #undef CreateWindow
    50 #endif
    51 
    52 /* Available video drivers */
    53 static VideoBootStrap *bootstrap[] = {
    54 #if SDL_VIDEO_DRIVER_COCOA
    55     &COCOA_bootstrap,
    56 #endif
    57 #if SDL_VIDEO_DRIVER_X11
    58     &X11_bootstrap,
    59 #endif
    60 #if SDL_VIDEO_DRIVER_DIRECTFB
    61     &DirectFB_bootstrap,
    62 #endif
    63 #if SDL_VIDEO_DRIVER_WINDOWS
    64     &WINDOWS_bootstrap,
    65 #endif
    66 #if SDL_VIDEO_DRIVER_BWINDOW
    67     &BWINDOW_bootstrap,
    68 #endif
    69 #if SDL_VIDEO_DRIVER_PANDORA
    70     &PND_bootstrap,
    71 #endif
    72 #if SDL_VIDEO_DRIVER_UIKIT
    73     &UIKIT_bootstrap,
    74 #endif
    75 #if SDL_VIDEO_DRIVER_ANDROID
    76     &Android_bootstrap,
    77 #endif
    78 #if SDL_VIDEO_DRIVER_PSP
    79     &PSP_bootstrap,
    80 #endif
    81 #if SDL_VIDEO_DRIVER_DUMMY
    82     &DUMMY_bootstrap,
    83 #endif
    84     NULL
    85 };
    86 
    87 static SDL_VideoDevice *_this = NULL;
    88 
    89 #define CHECK_WINDOW_MAGIC(window, retval) \
    90     if (!_this) { \
    91         SDL_UninitializedVideo(); \
    92         return retval; \
    93     } \
    94     if (!window || window->magic != &_this->window_magic) { \
    95         SDL_SetError("Invalid window"); \
    96         return retval; \
    97     }
    98 
    99 #define CHECK_DISPLAY_INDEX(displayIndex, retval) \
   100     if (!_this) { \
   101         SDL_UninitializedVideo(); \
   102         return retval; \
   103     } \
   104     if (displayIndex < 0 || displayIndex >= _this->num_displays) { \
   105         SDL_SetError("displayIndex must be in the range 0 - %d", \
   106                      _this->num_displays - 1); \
   107         return retval; \
   108     }
   109 
   110 /* Support for framebuffer emulation using an accelerated renderer */
   111 
   112 #define SDL_WINDOWTEXTUREDATA   "_SDL_WindowTextureData"
   113 
   114 typedef struct {
   115     SDL_Renderer *renderer;
   116     SDL_Texture *texture;
   117     void *pixels;
   118     int pitch;
   119     int bytes_per_pixel;
   120 } SDL_WindowTextureData;
   121 
   122 static SDL_bool
   123 ShouldUseTextureFramebuffer()
   124 {
   125     const char *hint;
   126 
   127     /* If there's no native framebuffer support then there's no option */
   128     if (!_this->CreateWindowFramebuffer) {
   129         return SDL_TRUE;
   130     }
   131 
   132     /* If the user has specified a software renderer we can't use a
   133        texture framebuffer, or renderer creation will go recursive.
   134      */
   135     hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
   136     if (hint && SDL_strcasecmp(hint, "software") == 0) {
   137         return SDL_FALSE;
   138     }
   139 
   140     /* See if the user or application wants a specific behavior */
   141     hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
   142     if (hint) {
   143         if (*hint == '0') {
   144             return SDL_FALSE;
   145         } else {
   146             return SDL_TRUE;
   147         }
   148     }
   149 
   150     /* Each platform has different performance characteristics */
   151 #if defined(__WIN32__)
   152     /* GDI BitBlt() is way faster than Direct3D dynamic textures right now.
   153      */
   154     return SDL_FALSE;
   155 
   156 #elif defined(__MACOSX__)
   157     /* Mac OS X uses OpenGL as the native fast path */
   158     return SDL_TRUE;
   159 
   160 #elif defined(__LINUX__)
   161     /* Properly configured OpenGL drivers are faster than MIT-SHM */
   162 #if SDL_VIDEO_OPENGL
   163     /* Ugh, find a way to cache this value! */
   164     {
   165         SDL_Window *window;
   166         SDL_GLContext context;
   167         SDL_bool hasAcceleratedOpenGL = SDL_FALSE;
   168 
   169         window = SDL_CreateWindow("OpenGL test", -32, -32, 32, 32, SDL_WINDOW_OPENGL|SDL_WINDOW_HIDDEN);
   170         if (window) {
   171             context = SDL_GL_CreateContext(window);
   172             if (context) {
   173                 const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
   174                 const char *vendor = NULL;
   175 
   176                 glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
   177                 if (glGetStringFunc) {
   178                     vendor = (const char *) glGetStringFunc(GL_VENDOR);
   179                 }
   180                 /* Add more vendors here at will... */
   181                 if (vendor &&
   182                     (SDL_strstr(vendor, "ATI Technologies") ||
   183                      SDL_strstr(vendor, "NVIDIA"))) {
   184                     hasAcceleratedOpenGL = SDL_TRUE;
   185                 }
   186                 SDL_GL_DeleteContext(context);
   187             }
   188             SDL_DestroyWindow(window);
   189         }
   190         return hasAcceleratedOpenGL;
   191     }
   192 #elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
   193     /* Let's be optimistic about this! */
   194     return SDL_TRUE;
   195 #else
   196     return SDL_FALSE;
   197 #endif
   198 
   199 #else
   200     /* Play it safe, assume that if there is a framebuffer driver that it's
   201        optimized for the current platform.
   202     */
   203     return SDL_FALSE;
   204 #endif
   205 }
   206 
   207 static int
   208 SDL_CreateWindowTexture(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
   209 {
   210     SDL_WindowTextureData *data;
   211     SDL_RendererInfo info;
   212     Uint32 i;
   213 
   214     data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
   215     if (!data) {
   216         SDL_Renderer *renderer = NULL;
   217         SDL_RendererInfo info;
   218         int i;
   219         const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
   220 
   221         /* Check to see if there's a specific driver requested */
   222         if (hint && *hint != '0' && *hint != '1' &&
   223             SDL_strcasecmp(hint, "software") != 0) {
   224             for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
   225                 SDL_GetRenderDriverInfo(i, &info);
   226                 if (SDL_strcasecmp(info.name, hint) == 0) {
   227                     renderer = SDL_CreateRenderer(window, i, 0);
   228                     break;
   229                 }
   230             }
   231         }
   232 
   233         if (!renderer) {
   234             for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
   235                 SDL_GetRenderDriverInfo(i, &info);
   236                 if (SDL_strcmp(info.name, "software") != 0) {
   237                     renderer = SDL_CreateRenderer(window, i, 0);
   238                     if (renderer) {
   239                         break;
   240                     }
   241                 }
   242             }
   243         }
   244         if (!renderer) {
   245             return SDL_SetError("No hardware accelerated renderers available");
   246         }
   247 
   248         /* Create the data after we successfully create the renderer (bug #1116) */
   249         data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
   250         if (!data) {
   251             SDL_DestroyRenderer(renderer);
   252             return SDL_OutOfMemory();
   253         }
   254         SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
   255 
   256         data->renderer = renderer;
   257     }
   258 
   259     /* Free any old texture and pixel data */
   260     if (data->texture) {
   261         SDL_DestroyTexture(data->texture);
   262         data->texture = NULL;
   263     }
   264     if (data->pixels) {
   265         SDL_free(data->pixels);
   266         data->pixels = NULL;
   267     }
   268 
   269     if (SDL_GetRendererInfo(data->renderer, &info) < 0) {
   270         return -1;
   271     }
   272 
   273     /* Find the first format without an alpha channel */
   274     *format = info.texture_formats[0];
   275     for (i = 0; i < info.num_texture_formats; ++i) {
   276         if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
   277             !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
   278             *format = info.texture_formats[i];
   279             break;
   280         }
   281     }
   282 
   283     data->texture = SDL_CreateTexture(data->renderer, *format,
   284                                       SDL_TEXTUREACCESS_STREAMING,
   285                                       window->w, window->h);
   286     if (!data->texture) {
   287         return -1;
   288     }
   289 
   290     /* Create framebuffer data */
   291     data->bytes_per_pixel = SDL_BYTESPERPIXEL(*format);
   292     data->pitch = (((window->w * data->bytes_per_pixel) + 3) & ~3);
   293     data->pixels = SDL_malloc(window->h * data->pitch);
   294     if (!data->pixels) {
   295         return SDL_OutOfMemory();
   296     }
   297 
   298     *pixels = data->pixels;
   299     *pitch = data->pitch;
   300 
   301     /* Make sure we're not double-scaling the viewport */
   302     SDL_RenderSetViewport(data->renderer, NULL);
   303 
   304     return 0;
   305 }
   306 
   307 static int
   308 SDL_UpdateWindowTexture(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
   309 {
   310     SDL_WindowTextureData *data;
   311     SDL_Rect rect;
   312     void *src;
   313 
   314     data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
   315     if (!data || !data->texture) {
   316         return SDL_SetError("No window texture data");
   317     }
   318 
   319     /* Update a single rect that contains subrects for best DMA performance */
   320     if (SDL_GetSpanEnclosingRect(window->w, window->h, numrects, rects, &rect)) {
   321         src = (void *)((Uint8 *)data->pixels +
   322                         rect.y * data->pitch +
   323                         rect.x * data->bytes_per_pixel);
   324         if (SDL_UpdateTexture(data->texture, &rect, src, data->pitch) < 0) {
   325             return -1;
   326         }
   327 
   328         if (SDL_RenderCopy(data->renderer, data->texture, NULL, NULL) < 0) {
   329             return -1;
   330         }
   331 
   332         SDL_RenderPresent(data->renderer);
   333     }
   334     return 0;
   335 }
   336 
   337 static void
   338 SDL_DestroyWindowTexture(_THIS, SDL_Window * window)
   339 {
   340     SDL_WindowTextureData *data;
   341 
   342     data = SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, NULL);
   343     if (!data) {
   344         return;
   345     }
   346     if (data->texture) {
   347         SDL_DestroyTexture(data->texture);
   348     }
   349     if (data->renderer) {
   350         SDL_DestroyRenderer(data->renderer);
   351     }
   352     if (data->pixels) {
   353         SDL_free(data->pixels);
   354     }
   355     SDL_free(data);
   356 }
   357 
   358 
   359 static int
   360 cmpmodes(const void *A, const void *B)
   361 {
   362     SDL_DisplayMode a = *(const SDL_DisplayMode *) A;
   363     SDL_DisplayMode b = *(const SDL_DisplayMode *) B;
   364 
   365     if (a.w != b.w) {
   366         return b.w - a.w;
   367     }
   368     if (a.h != b.h) {
   369         return b.h - a.h;
   370     }
   371     if (SDL_BITSPERPIXEL(a.format) != SDL_BITSPERPIXEL(b.format)) {
   372         return SDL_BITSPERPIXEL(b.format) - SDL_BITSPERPIXEL(a.format);
   373     }
   374     if (SDL_PIXELLAYOUT(a.format) != SDL_PIXELLAYOUT(b.format)) {
   375         return SDL_PIXELLAYOUT(b.format) - SDL_PIXELLAYOUT(a.format);
   376     }
   377     if (a.refresh_rate != b.refresh_rate) {
   378         return b.refresh_rate - a.refresh_rate;
   379     }
   380     return 0;
   381 }
   382 
   383 static int
   384 SDL_UninitializedVideo()
   385 {
   386     return SDL_SetError("Video subsystem has not been initialized");
   387 }
   388 
   389 int
   390 SDL_GetNumVideoDrivers(void)
   391 {
   392     return SDL_arraysize(bootstrap) - 1;
   393 }
   394 
   395 const char *
   396 SDL_GetVideoDriver(int index)
   397 {
   398     if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
   399         return bootstrap[index]->name;
   400     }
   401     return NULL;
   402 }
   403 
   404 /*
   405  * Initialize the video and event subsystems -- determine native pixel format
   406  */
   407 int
   408 SDL_VideoInit(const char *driver_name)
   409 {
   410     SDL_VideoDevice *video;
   411     int index;
   412     int i;
   413 
   414     /* Check to make sure we don't overwrite '_this' */
   415     if (_this != NULL) {
   416         SDL_VideoQuit();
   417     }
   418 
   419     /* Start the event loop */
   420     if (SDL_StartEventLoop() < 0 ||
   421         SDL_KeyboardInit() < 0 ||
   422         SDL_MouseInit() < 0 ||
   423         SDL_TouchInit() < 0 ||
   424         SDL_QuitInit() < 0) {
   425         return -1;
   426     }
   427 
   428     /* Select the proper video driver */
   429     index = 0;
   430     video = NULL;
   431     if (driver_name == NULL) {
   432         driver_name = SDL_getenv("SDL_VIDEODRIVER");
   433     }
   434     if (driver_name != NULL) {
   435         for (i = 0; bootstrap[i]; ++i) {
   436             if (SDL_strncasecmp(bootstrap[i]->name, driver_name, SDL_strlen(driver_name)) == 0) {
   437                 video = bootstrap[i]->create(index);
   438                 break;
   439             }
   440         }
   441     } else {
   442         for (i = 0; bootstrap[i]; ++i) {
   443             if (bootstrap[i]->available()) {
   444                 video = bootstrap[i]->create(index);
   445                 if (video != NULL) {
   446                     break;
   447                 }
   448             }
   449         }
   450     }
   451     if (video == NULL) {
   452         if (driver_name) {
   453             return SDL_SetError("%s not available", driver_name);
   454         }
   455         return SDL_SetError("No available video device");
   456     }
   457     _this = video;
   458     _this->name = bootstrap[i]->name;
   459     _this->next_object_id = 1;
   460 
   461 
   462     /* Set some very sane GL defaults */
   463     _this->gl_config.driver_loaded = 0;
   464     _this->gl_config.dll_handle = NULL;
   465     _this->gl_config.red_size = 3;
   466     _this->gl_config.green_size = 3;
   467     _this->gl_config.blue_size = 2;
   468     _this->gl_config.alpha_size = 0;
   469     _this->gl_config.buffer_size = 0;
   470     _this->gl_config.depth_size = 16;
   471     _this->gl_config.stencil_size = 0;
   472     _this->gl_config.double_buffer = 1;
   473     _this->gl_config.accum_red_size = 0;
   474     _this->gl_config.accum_green_size = 0;
   475     _this->gl_config.accum_blue_size = 0;
   476     _this->gl_config.accum_alpha_size = 0;
   477     _this->gl_config.stereo = 0;
   478     _this->gl_config.multisamplebuffers = 0;
   479     _this->gl_config.multisamplesamples = 0;
   480     _this->gl_config.retained_backing = 1;
   481     _this->gl_config.accelerated = -1;  /* accelerated or not, both are fine */
   482 #if SDL_VIDEO_OPENGL
   483     _this->gl_config.major_version = 2;
   484     _this->gl_config.minor_version = 1;
   485     _this->gl_config.use_egl = 0;
   486 #elif SDL_VIDEO_OPENGL_ES
   487     _this->gl_config.major_version = 1;
   488     _this->gl_config.minor_version = 1;
   489     _this->gl_config.use_egl = 1;
   490 #elif SDL_VIDEO_OPENGL_ES2
   491     _this->gl_config.major_version = 2;
   492     _this->gl_config.minor_version = 0;
   493     _this->gl_config.use_egl = 1;
   494 #endif
   495     _this->gl_config.flags = 0;
   496     _this->gl_config.profile_mask = 0;
   497     _this->gl_config.share_with_current_context = 0;
   498 
   499     /* Initialize the video subsystem */
   500     if (_this->VideoInit(_this) < 0) {
   501         SDL_VideoQuit();
   502         return -1;
   503     }
   504 
   505     /* Make sure some displays were added */
   506     if (_this->num_displays == 0) {
   507         SDL_VideoQuit();
   508         return SDL_SetError("The video driver did not add any displays");
   509     }
   510 
   511     /* Add the renderer framebuffer emulation if desired */
   512     if (ShouldUseTextureFramebuffer()) {
   513         _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
   514         _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
   515         _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
   516     }
   517 
   518     /* If we don't use a screen keyboard, turn on text input by default,
   519        otherwise programs that expect to get text events without enabling
   520        UNICODE input won't get any events.
   521 
   522        Actually, come to think of it, you needed to call SDL_EnableUNICODE(1)
   523        in SDL 1.2 before you got text input events.  Hmm...
   524      */
   525     if (!SDL_HasScreenKeyboardSupport()) {
   526         SDL_StartTextInput();
   527     }
   528 
   529     /* We're ready to go! */
   530     return 0;
   531 }
   532 
   533 const char *
   534 SDL_GetCurrentVideoDriver()
   535 {
   536     if (!_this) {
   537         SDL_UninitializedVideo();
   538         return NULL;
   539     }
   540     return _this->name;
   541 }
   542 
   543 SDL_VideoDevice *
   544 SDL_GetVideoDevice(void)
   545 {
   546     return _this;
   547 }
   548 
   549 int
   550 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
   551 {
   552     SDL_VideoDisplay display;
   553 
   554     SDL_zero(display);
   555     if (desktop_mode) {
   556         display.desktop_mode = *desktop_mode;
   557     }
   558     display.current_mode = display.desktop_mode;
   559 
   560     return SDL_AddVideoDisplay(&display);
   561 }
   562 
   563 int
   564 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
   565 {
   566     SDL_VideoDisplay *displays;
   567     int index = -1;
   568 
   569     displays =
   570         SDL_realloc(_this->displays,
   571                     (_this->num_displays + 1) * sizeof(*displays));
   572     if (displays) {
   573         index = _this->num_displays++;
   574         displays[index] = *display;
   575         displays[index].device = _this;
   576         _this->displays = displays;
   577 
   578         if (display->name) {
   579             displays[index].name = SDL_strdup(display->name);
   580         } else {
   581             char name[32];
   582 
   583             SDL_itoa(index, name, 10);
   584             displays[index].name = SDL_strdup(name);
   585         }
   586     } else {
   587         SDL_OutOfMemory();
   588     }
   589     return index;
   590 }
   591 
   592 int
   593 SDL_GetNumVideoDisplays(void)
   594 {
   595     if (!_this) {
   596         SDL_UninitializedVideo();
   597         return 0;
   598     }
   599     return _this->num_displays;
   600 }
   601 
   602 static int
   603 SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
   604 {
   605     int displayIndex;
   606 
   607     for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
   608         if (display == &_this->displays[displayIndex]) {
   609             return displayIndex;
   610         }
   611     }
   612 
   613     /* Couldn't find the display, just use index 0 */
   614     return 0;
   615 }
   616 
   617 const char *
   618 SDL_GetDisplayName(int displayIndex)
   619 {
   620     CHECK_DISPLAY_INDEX(displayIndex, NULL);
   621 
   622     return _this->displays[displayIndex].name;
   623 }
   624 
   625 int
   626 SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
   627 {
   628     CHECK_DISPLAY_INDEX(displayIndex, -1);
   629 
   630     if (rect) {
   631         SDL_VideoDisplay *display = &_this->displays[displayIndex];
   632 
   633         if (_this->GetDisplayBounds) {
   634             if (_this->GetDisplayBounds(_this, display, rect) == 0) {
   635                 return 0;
   636             }
   637         }
   638 
   639         /* Assume that the displays are left to right */
   640         if (displayIndex == 0) {
   641             rect->x = 0;
   642             rect->y = 0;
   643         } else {
   644             SDL_GetDisplayBounds(displayIndex-1, rect);
   645             rect->x += rect->w;
   646         }
   647         rect->w = display->current_mode.w;
   648         rect->h = display->current_mode.h;
   649     }
   650     return 0;
   651 }
   652 
   653 SDL_bool
   654 SDL_AddDisplayMode(SDL_VideoDisplay * display,  const SDL_DisplayMode * mode)
   655 {
   656     SDL_DisplayMode *modes;
   657     int i, nmodes;
   658 
   659     /* Make sure we don't already have the mode in the list */
   660     modes = display->display_modes;
   661     nmodes = display->num_display_modes;
   662     for (i = nmodes; i--;) {
   663         if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) {
   664             return SDL_FALSE;
   665         }
   666     }
   667 
   668     /* Go ahead and add the new mode */
   669     if (nmodes == display->max_display_modes) {
   670         modes =
   671             SDL_realloc(modes,
   672                         (display->max_display_modes + 32) * sizeof(*modes));
   673         if (!modes) {
   674             return SDL_FALSE;
   675         }
   676         display->display_modes = modes;
   677         display->max_display_modes += 32;
   678     }
   679     modes[nmodes] = *mode;
   680     display->num_display_modes++;
   681 
   682     /* Re-sort video modes */
   683     SDL_qsort(display->display_modes, display->num_display_modes,
   684               sizeof(SDL_DisplayMode), cmpmodes);
   685 
   686     return SDL_TRUE;
   687 }
   688 
   689 static int
   690 SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
   691 {
   692     if (!display->num_display_modes && _this->GetDisplayModes) {
   693         _this->GetDisplayModes(_this, display);
   694         SDL_qsort(display->display_modes, display->num_display_modes,
   695                   sizeof(SDL_DisplayMode), cmpmodes);
   696     }
   697     return display->num_display_modes;
   698 }
   699 
   700 int
   701 SDL_GetNumDisplayModes(int displayIndex)
   702 {
   703     CHECK_DISPLAY_INDEX(displayIndex, -1);
   704 
   705     return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
   706 }
   707 
   708 int
   709 SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
   710 {
   711     SDL_VideoDisplay *display;
   712 
   713     CHECK_DISPLAY_INDEX(displayIndex, -1);
   714 
   715     display = &_this->displays[displayIndex];
   716     if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
   717         return SDL_SetError("index must be in the range of 0 - %d",
   718                             SDL_GetNumDisplayModesForDisplay(display) - 1);
   719     }
   720     if (mode) {
   721         *mode = display->display_modes[index];
   722     }
   723     return 0;
   724 }
   725 
   726 int
   727 SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
   728 {
   729     SDL_VideoDisplay *display;
   730 
   731     CHECK_DISPLAY_INDEX(displayIndex, -1);
   732 
   733     display = &_this->displays[displayIndex];
   734     if (mode) {
   735         *mode = display->desktop_mode;
   736     }
   737     return 0;
   738 }
   739 
   740 int
   741 SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
   742 {
   743     SDL_VideoDisplay *display;
   744 
   745     CHECK_DISPLAY_INDEX(displayIndex, -1);
   746 
   747     display = &_this->displays[displayIndex];
   748     if (mode) {
   749         *mode = display->current_mode;
   750     }
   751     return 0;
   752 }
   753 
   754 static SDL_DisplayMode *
   755 SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
   756                                     const SDL_DisplayMode * mode,
   757                                     SDL_DisplayMode * closest)
   758 {
   759     Uint32 target_format;
   760     int target_refresh_rate;
   761     int i;
   762     SDL_DisplayMode *current, *match;
   763 
   764     if (!mode || !closest) {
   765         SDL_SetError("Missing desired mode or closest mode parameter");
   766         return NULL;
   767     }
   768 
   769     /* Default to the desktop format */
   770     if (mode->format) {
   771         target_format = mode->format;
   772     } else {
   773         target_format = display->desktop_mode.format;
   774     }
   775 
   776     /* Default to the desktop refresh rate */
   777     if (mode->refresh_rate) {
   778         target_refresh_rate = mode->refresh_rate;
   779     } else {
   780         target_refresh_rate = display->desktop_mode.refresh_rate;
   781     }
   782 
   783     match = NULL;
   784     for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
   785         current = &display->display_modes[i];
   786 
   787         if (current->w && (current->w < mode->w)) {
   788             /* Out of sorted modes large enough here */
   789             break;
   790         }
   791         if (current->h && (current->h < mode->h)) {
   792             if (current->w && (current->w == mode->w)) {
   793                 /* Out of sorted modes large enough here */
   794                 break;
   795             }
   796             /* Wider, but not tall enough, due to a different
   797                aspect ratio. This mode must be skipped, but closer
   798                modes may still follow. */
   799             continue;
   800         }
   801         if (!match || current->w < match->w || current->h < match->h) {
   802             match = current;
   803             continue;
   804         }
   805         if (current->format != match->format) {
   806             /* Sorted highest depth to lowest */
   807             if (current->format == target_format ||
   808                 (SDL_BITSPERPIXEL(current->format) >=
   809                  SDL_BITSPERPIXEL(target_format)
   810                  && SDL_PIXELTYPE(current->format) ==
   811                  SDL_PIXELTYPE(target_format))) {
   812                 match = current;
   813             }
   814             continue;
   815         }
   816         if (current->refresh_rate != match->refresh_rate) {
   817             /* Sorted highest refresh to lowest */
   818             if (current->refresh_rate >= target_refresh_rate) {
   819                 match = current;
   820             }
   821         }
   822     }
   823     if (match) {
   824         if (match->format) {
   825             closest->format = match->format;
   826         } else {
   827             closest->format = mode->format;
   828         }
   829         if (match->w && match->h) {
   830             closest->w = match->w;
   831             closest->h = match->h;
   832         } else {
   833             closest->w = mode->w;
   834             closest->h = mode->h;
   835         }
   836         if (match->refresh_rate) {
   837             closest->refresh_rate = match->refresh_rate;
   838         } else {
   839             closest->refresh_rate = mode->refresh_rate;
   840         }
   841         closest->driverdata = match->driverdata;
   842 
   843         /*
   844          * Pick some reasonable defaults if the app and driver don't
   845          * care
   846          */
   847         if (!closest->format) {
   848             closest->format = SDL_PIXELFORMAT_RGB888;
   849         }
   850         if (!closest->w) {
   851             closest->w = 640;
   852         }
   853         if (!closest->h) {
   854             closest->h = 480;
   855         }
   856         return closest;
   857     }
   858     return NULL;
   859 }
   860 
   861 SDL_DisplayMode *
   862 SDL_GetClosestDisplayMode(int displayIndex,
   863                           const SDL_DisplayMode * mode,
   864                           SDL_DisplayMode * closest)
   865 {
   866     SDL_VideoDisplay *display;
   867 
   868     CHECK_DISPLAY_INDEX(displayIndex, NULL);
   869 
   870     display = &_this->displays[displayIndex];
   871     return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
   872 }
   873 
   874 static int
   875 SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
   876 {
   877     SDL_DisplayMode display_mode;
   878     SDL_DisplayMode current_mode;
   879 
   880     if (mode) {
   881         display_mode = *mode;
   882 
   883         /* Default to the current mode */
   884         if (!display_mode.format) {
   885             display_mode.format = display->current_mode.format;
   886         }
   887         if (!display_mode.w) {
   888             display_mode.w = display->current_mode.w;
   889         }
   890         if (!display_mode.h) {
   891             display_mode.h = display->current_mode.h;
   892         }
   893         if (!display_mode.refresh_rate) {
   894             display_mode.refresh_rate = display->current_mode.refresh_rate;
   895         }
   896 
   897         /* Get a good video mode, the closest one possible */
   898         if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
   899             return SDL_SetError("No video mode large enough for %dx%d",
   900                                 display_mode.w, display_mode.h);
   901         }
   902     } else {
   903         display_mode = display->desktop_mode;
   904     }
   905 
   906     /* See if there's anything left to do */
   907     current_mode = display->current_mode;
   908     if (SDL_memcmp(&display_mode, &current_mode, sizeof(display_mode)) == 0) {
   909         return 0;
   910     }
   911 
   912     /* Actually change the display mode */
   913     if (!_this->SetDisplayMode) {
   914         return SDL_SetError("Video driver doesn't support changing display mode");
   915     }
   916     if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
   917         return -1;
   918     }
   919     display->current_mode = display_mode;
   920     return 0;
   921 }
   922 
   923 int
   924 SDL_GetWindowDisplayIndex(SDL_Window * window)
   925 {
   926     int displayIndex;
   927     int i, dist;
   928     int closest = -1;
   929     int closest_dist = 0x7FFFFFFF;
   930     SDL_Point center;
   931     SDL_Point delta;
   932     SDL_Rect rect;
   933 
   934     CHECK_WINDOW_MAGIC(window, -1);
   935 
   936     if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
   937         SDL_WINDOWPOS_ISCENTERED(window->x)) {
   938         displayIndex = (window->x & 0xFFFF);
   939         if (displayIndex >= _this->num_displays) {
   940             displayIndex = 0;
   941         }
   942         return displayIndex;
   943     }
   944     if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
   945         SDL_WINDOWPOS_ISCENTERED(window->y)) {
   946         displayIndex = (window->y & 0xFFFF);
   947         if (displayIndex >= _this->num_displays) {
   948             displayIndex = 0;
   949         }
   950         return displayIndex;
   951     }
   952 
   953     /* Find the display containing the window */
   954     for (i = 0; i < _this->num_displays; ++i) {
   955         SDL_VideoDisplay *display = &_this->displays[i];
   956 
   957         if (display->fullscreen_window == window) {
   958             return i;
   959         }
   960     }
   961     center.x = window->x + window->w / 2;
   962     center.y = window->y + window->h / 2;
   963     for (i = 0; i < _this->num_displays; ++i) {
   964         SDL_GetDisplayBounds(i, &rect);
   965         if (SDL_EnclosePoints(&center, 1, &rect, NULL)) {
   966             return i;
   967         }
   968 
   969         delta.x = center.x - (rect.x + rect.w / 2);
   970         delta.y = center.y - (rect.y + rect.h / 2);
   971         dist = (delta.x*delta.x + delta.y*delta.y);
   972         if (dist < closest_dist) {
   973             closest = i;
   974             closest_dist = dist;
   975         }
   976     }
   977     if (closest < 0) {
   978         SDL_SetError("Couldn't find any displays");
   979     }
   980     return closest;
   981 }
   982 
   983 SDL_VideoDisplay *
   984 SDL_GetDisplayForWindow(SDL_Window *window)
   985 {
   986     int displayIndex = SDL_GetWindowDisplayIndex(window);
   987     if (displayIndex >= 0) {
   988         return &_this->displays[displayIndex];
   989     } else {
   990         return NULL;
   991     }
   992 }
   993 
   994 int
   995 SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
   996 {
   997     CHECK_WINDOW_MAGIC(window, -1);
   998 
   999     if (mode) {
  1000         window->fullscreen_mode = *mode;
  1001     } else {
  1002         SDL_zero(window->fullscreen_mode);
  1003     }
  1004     return 0;
  1005 }
  1006 
  1007 int
  1008 SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
  1009 {
  1010     SDL_DisplayMode fullscreen_mode;
  1011 	SDL_VideoDisplay *display;
  1012 
  1013     if (!mode) {
  1014       return SDL_InvalidParamError("mode");
  1015     }
  1016     
  1017     CHECK_WINDOW_MAGIC(window, -1);
  1018 
  1019     fullscreen_mode = window->fullscreen_mode;
  1020     if (!fullscreen_mode.w) {
  1021         fullscreen_mode.w = window->w;
  1022     }
  1023     if (!fullscreen_mode.h) {
  1024         fullscreen_mode.h = window->h;
  1025     }
  1026 	
  1027 	display = SDL_GetDisplayForWindow(window);
  1028 
  1029 	/* if in desktop size mode, just return the size of the desktop */
  1030 	if ( ( window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP ) 
  1031 	{
  1032 		fullscreen_mode = display->desktop_mode;
  1033 	}
  1034 	else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
  1035                                              &fullscreen_mode,
  1036                                              &fullscreen_mode)) {
  1037         return SDL_SetError("Couldn't find display mode match");
  1038     }
  1039 
  1040     if (mode) {
  1041         *mode = fullscreen_mode;
  1042     }
  1043     return 0;
  1044 }
  1045 
  1046 Uint32
  1047 SDL_GetWindowPixelFormat(SDL_Window * window)
  1048 {
  1049     SDL_VideoDisplay *display;
  1050 
  1051     CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
  1052 
  1053     display = SDL_GetDisplayForWindow(window);
  1054     return display->current_mode.format;
  1055 }
  1056 
  1057 static void
  1058 SDL_RestoreMousePosition(SDL_Window *window)
  1059 {
  1060     int x, y;
  1061 
  1062     if (window == SDL_GetMouseFocus()) {
  1063         SDL_GetMouseState(&x, &y);
  1064         SDL_WarpMouseInWindow(window, x, y);
  1065     }
  1066 }
  1067 
  1068 static void
  1069 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
  1070 {
  1071     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
  1072     SDL_Window *other;
  1073 
  1074     if (fullscreen) {
  1075         /* Hide any other fullscreen windows */
  1076         if (display->fullscreen_window &&
  1077             display->fullscreen_window != window) {
  1078             SDL_MinimizeWindow(display->fullscreen_window);
  1079         }
  1080     }
  1081 
  1082     /* See if anything needs to be done now */
  1083     if ((display->fullscreen_window == window) == fullscreen) {
  1084         return;
  1085     }
  1086 
  1087     /* See if there are any fullscreen windows */
  1088     for (other = _this->windows; other; other = other->next) {
  1089         SDL_bool setDisplayMode = SDL_FALSE;
  1090 
  1091         if (other == window) {
  1092             setDisplayMode = fullscreen;
  1093         } else if (FULLSCREEN_VISIBLE(other) &&
  1094                    SDL_GetDisplayForWindow(other) == display) {
  1095             setDisplayMode = SDL_TRUE;
  1096         }
  1097 
  1098         if (setDisplayMode) {
  1099             SDL_DisplayMode fullscreen_mode;
  1100 
  1101             if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
  1102                 SDL_bool resized = SDL_TRUE;
  1103 
  1104                 if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
  1105                     resized = SDL_FALSE;
  1106                 }
  1107 
  1108 				/* only do the mode change if we want exclusive fullscreen */
  1109 				if ( ( window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) != SDL_WINDOW_FULLSCREEN_DESKTOP ) 
  1110 					SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
  1111 				else
  1112 					SDL_SetDisplayModeForDisplay(display, NULL);
  1113 
  1114 				
  1115                 if (_this->SetWindowFullscreen) {
  1116                     _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
  1117                 }
  1118                 display->fullscreen_window = other;
  1119 
  1120                 /* Generate a mode change event here */
  1121                 if (resized) {
  1122                     SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
  1123                                         fullscreen_mode.w, fullscreen_mode.h);
  1124                 } else {
  1125                     SDL_OnWindowResized(other);
  1126                 }
  1127 
  1128                 SDL_RestoreMousePosition(other);
  1129                 return;
  1130             }
  1131         }
  1132     }
  1133 
  1134     /* Nope, restore the desktop mode */
  1135     SDL_SetDisplayModeForDisplay(display, NULL);
  1136 
  1137     if (_this->SetWindowFullscreen) {
  1138         _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
  1139     }
  1140     display->fullscreen_window = NULL;
  1141 
  1142     /* Generate a mode change event here */
  1143     SDL_OnWindowResized(window);
  1144 
  1145     /* Restore the cursor position */
  1146     SDL_RestoreMousePosition(window);
  1147 }
  1148 
  1149 #define CREATE_FLAGS \
  1150     (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE)
  1151 
  1152 static void
  1153 SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
  1154 {
  1155     window->windowed.x = window->x;
  1156     window->windowed.y = window->y;
  1157     window->windowed.w = window->w;
  1158     window->windowed.h = window->h;
  1159 
  1160     if (flags & SDL_WINDOW_MAXIMIZED) {
  1161         SDL_MaximizeWindow(window);
  1162     }
  1163     if (flags & SDL_WINDOW_MINIMIZED) {
  1164         SDL_MinimizeWindow(window);
  1165     }
  1166     if (flags & SDL_WINDOW_FULLSCREEN) {
  1167         SDL_SetWindowFullscreen(window, flags);
  1168     }
  1169     if (flags & SDL_WINDOW_INPUT_GRABBED) {
  1170         SDL_SetWindowGrab(window, SDL_TRUE);
  1171     }
  1172     if (!(flags & SDL_WINDOW_HIDDEN)) {
  1173         SDL_ShowWindow(window);
  1174     }
  1175 }
  1176 
  1177 SDL_Window *
  1178 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
  1179 {
  1180     SDL_Window *window;
  1181 
  1182     if (!_this) {
  1183         /* Initialize the video system if needed */
  1184         if (SDL_VideoInit(NULL) < 0) {
  1185             return NULL;
  1186         }
  1187     }
  1188 
  1189     /* Some platforms can't create zero-sized windows */
  1190     if (w < 1) {
  1191         w = 1;
  1192     }
  1193     if (h < 1) {
  1194         h = 1;
  1195     }
  1196 
  1197     /* Some platforms have OpenGL enabled by default */
  1198 #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__
  1199     flags |= SDL_WINDOW_OPENGL;
  1200 #endif
  1201     if (flags & SDL_WINDOW_OPENGL) {
  1202         if (!_this->GL_CreateContext) {
  1203             SDL_SetError("No OpenGL support in video driver");
  1204             return NULL;
  1205         }
  1206         if (SDL_GL_LoadLibrary(NULL) < 0) {
  1207             return NULL;
  1208         }
  1209     }
  1210     window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
  1211     window->magic = &_this->window_magic;
  1212     window->id = _this->next_object_id++;
  1213     window->x = x;
  1214     window->y = y;
  1215     window->w = w;
  1216     window->h = h;
  1217     if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
  1218         SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
  1219         SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
  1220         int displayIndex;
  1221         SDL_Rect bounds;
  1222 
  1223         displayIndex = SDL_GetIndexOfDisplay(display);
  1224         SDL_GetDisplayBounds(displayIndex, &bounds);
  1225         if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
  1226             window->x = bounds.x + (bounds.w - w) / 2;
  1227         }
  1228         if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
  1229             window->y = bounds.y + (bounds.h - h) / 2;
  1230         }
  1231     }
  1232     window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
  1233     window->brightness = 1.0f;
  1234     window->next = _this->windows;
  1235     if (_this->windows) {
  1236         _this->windows->prev = window;
  1237     }
  1238     _this->windows = window;
  1239 
  1240     if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
  1241         SDL_DestroyWindow(window);
  1242         return NULL;
  1243     }
  1244 
  1245     if (title) {
  1246         SDL_SetWindowTitle(window, title);
  1247     }
  1248     SDL_FinishWindowCreation(window, flags);
  1249     
  1250     /* If the window was created fullscreen, make sure the mode code matches */
  1251     SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
  1252 
  1253     return window;
  1254 }
  1255 
  1256 SDL_Window *
  1257 SDL_CreateWindowFrom(const void *data)
  1258 {
  1259     SDL_Window *window;
  1260 
  1261     if (!_this) {
  1262         SDL_UninitializedVideo();
  1263         return NULL;
  1264     }
  1265     window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
  1266     window->magic = &_this->window_magic;
  1267     window->id = _this->next_object_id++;
  1268     window->flags = SDL_WINDOW_FOREIGN;
  1269     window->brightness = 1.0f;
  1270     window->next = _this->windows;
  1271     if (_this->windows) {
  1272         _this->windows->prev = window;
  1273     }
  1274     _this->windows = window;
  1275 
  1276     if (!_this->CreateWindowFrom ||
  1277         _this->CreateWindowFrom(_this, window, data) < 0) {
  1278         SDL_DestroyWindow(window);
  1279         return NULL;
  1280     }
  1281     return window;
  1282 }
  1283 
  1284 int
  1285 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
  1286 {
  1287     char *title = window->title;
  1288 
  1289     if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
  1290         return SDL_SetError("No OpenGL support in video driver");
  1291     }
  1292 
  1293     if (window->flags & SDL_WINDOW_FOREIGN) {
  1294         /* Can't destroy and re-create foreign windows, hrm */
  1295         flags |= SDL_WINDOW_FOREIGN;
  1296     } else {
  1297         flags &= ~SDL_WINDOW_FOREIGN;
  1298     }
  1299 
  1300     /* Restore video mode, etc. */
  1301     SDL_HideWindow(window);
  1302 
  1303     /* Tear down the old native window */
  1304     if (window->surface) {
  1305         window->surface->flags &= ~SDL_DONTFREE;
  1306         SDL_FreeSurface(window->surface);
  1307     }
  1308     if (_this->DestroyWindowFramebuffer) {
  1309         _this->DestroyWindowFramebuffer(_this, window);
  1310     }
  1311     if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
  1312         _this->DestroyWindow(_this, window);
  1313     }
  1314 
  1315     if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
  1316         if (flags & SDL_WINDOW_OPENGL) {
  1317             if (SDL_GL_LoadLibrary(NULL) < 0) {
  1318                 return -1;
  1319             }
  1320         } else {
  1321             SDL_GL_UnloadLibrary();
  1322         }
  1323     }
  1324 
  1325     window->title = NULL;
  1326     window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
  1327 
  1328     if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
  1329         if (_this->CreateWindow(_this, window) < 0) {
  1330             if (flags & SDL_WINDOW_OPENGL) {
  1331                 SDL_GL_UnloadLibrary();
  1332             }
  1333             return -1;
  1334         }
  1335     }
  1336 
  1337     if (title) {
  1338         SDL_SetWindowTitle(window, title);
  1339         SDL_free(title);
  1340     }
  1341     SDL_FinishWindowCreation(window, flags);
  1342 
  1343     return 0;
  1344 }
  1345 
  1346 Uint32
  1347 SDL_GetWindowID(SDL_Window * window)
  1348 {
  1349     CHECK_WINDOW_MAGIC(window, 0);
  1350 
  1351     return window->id;
  1352 }
  1353 
  1354 SDL_Window *
  1355 SDL_GetWindowFromID(Uint32 id)
  1356 {
  1357     SDL_Window *window;
  1358 
  1359     if (!_this) {
  1360         return NULL;
  1361     }
  1362     for (window = _this->windows; window; window = window->next) {
  1363         if (window->id == id) {
  1364             return window;
  1365         }
  1366     }
  1367     return NULL;
  1368 }
  1369 
  1370 Uint32
  1371 SDL_GetWindowFlags(SDL_Window * window)
  1372 {
  1373     CHECK_WINDOW_MAGIC(window, 0);
  1374 
  1375     return window->flags;
  1376 }
  1377 
  1378 void
  1379 SDL_SetWindowTitle(SDL_Window * window, const char *title)
  1380 {
  1381     CHECK_WINDOW_MAGIC(window, );
  1382 
  1383     if (title == window->title) {
  1384         return;
  1385     }
  1386     if (window->title) {
  1387         SDL_free(window->title);
  1388     }
  1389     if (title && *title) {
  1390         window->title = SDL_strdup(title);
  1391     } else {
  1392         window->title = NULL;
  1393     }
  1394 
  1395     if (_this->SetWindowTitle) {
  1396         _this->SetWindowTitle(_this, window);
  1397     }
  1398 }
  1399 
  1400 const char *
  1401 SDL_GetWindowTitle(SDL_Window * window)
  1402 {
  1403     CHECK_WINDOW_MAGIC(window, "");
  1404 
  1405     return window->title ? window->title : "";
  1406 }
  1407 
  1408 void
  1409 SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
  1410 {
  1411     CHECK_WINDOW_MAGIC(window, );
  1412 
  1413     if (!icon) {
  1414         return;
  1415     }
  1416 
  1417     if (_this->SetWindowIcon) {
  1418         _this->SetWindowIcon(_this, window, icon);
  1419     }
  1420 }
  1421 
  1422 void*
  1423 SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
  1424 {
  1425     SDL_WindowUserData *prev, *data;
  1426 
  1427     CHECK_WINDOW_MAGIC(window, NULL);
  1428     
  1429     /* Input validation */
  1430     if (name == NULL || SDL_strlen(name) == 0) {
  1431       SDL_InvalidParamError("name");
  1432       return NULL;
  1433     }
  1434 
  1435     /* See if the named data already exists */
  1436     prev = NULL;
  1437     for (data = window->data; data; prev = data, data = data->next) {
  1438         if (data->name && SDL_strcmp(data->name, name) == 0) {
  1439             void *last_value = data->data;
  1440 
  1441             if (userdata) {
  1442                 /* Set the new value */
  1443                 data->data = userdata;
  1444             } else {
  1445                 /* Delete this value */
  1446                 if (prev) {
  1447                     prev->next = data->next;
  1448                 } else {
  1449                     window->data = data->next;
  1450                 }
  1451                 SDL_free(data->name);
  1452                 SDL_free(data);
  1453             }
  1454             return last_value;
  1455         }
  1456     }
  1457 
  1458     /* Add new data to the window */
  1459     if (userdata) {
  1460         data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
  1461         data->name = SDL_strdup(name);
  1462         data->data = userdata;
  1463         data->next = window->data;
  1464         window->data = data;
  1465     }
  1466     return NULL;
  1467 }
  1468 
  1469 void *
  1470 SDL_GetWindowData(SDL_Window * window, const char *name)
  1471 {
  1472     SDL_WindowUserData *data;
  1473 
  1474     CHECK_WINDOW_MAGIC(window, NULL);
  1475 
  1476     /* Input validation */
  1477     if (name == NULL || SDL_strlen(name) == 0) {
  1478       SDL_InvalidParamError("name");
  1479       return NULL;
  1480     }
  1481 
  1482     for (data = window->data; data; data = data->next) {
  1483         if (data->name && SDL_strcmp(data->name, name) == 0) {
  1484             return data->data;
  1485         }
  1486     }
  1487     return NULL;
  1488 }
  1489 
  1490 void
  1491 SDL_SetWindowPosition(SDL_Window * window, int x, int y)
  1492 {
  1493     CHECK_WINDOW_MAGIC(window, );
  1494 
  1495     if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
  1496         window->x = x;
  1497     }
  1498     if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
  1499         window->y = y;
  1500     }
  1501     if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
  1502         SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
  1503         int displayIndex;
  1504         SDL_Rect bounds;
  1505 
  1506         displayIndex = SDL_GetIndexOfDisplay(display);
  1507         SDL_GetDisplayBounds(displayIndex, &bounds);
  1508         if (SDL_WINDOWPOS_ISCENTERED(x)) {
  1509             window->x = bounds.x + (bounds.w - window->w) / 2;
  1510         }
  1511         if (SDL_WINDOWPOS_ISCENTERED(y)) {
  1512             window->y = bounds.y + (bounds.h - window->h) / 2;
  1513         }
  1514     }
  1515     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
  1516         if (_this->SetWindowPosition) {
  1517             _this->SetWindowPosition(_this, window);
  1518         }
  1519         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
  1520     }
  1521 }
  1522 
  1523 void
  1524 SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
  1525 {
  1526     CHECK_WINDOW_MAGIC(window, );
  1527 
  1528     /* Fullscreen windows are always at their display's origin */
  1529     if (window->flags & SDL_WINDOW_FULLSCREEN) {
  1530         if (x) {
  1531             *x = 0;
  1532         }
  1533         if (y) {
  1534             *y = 0;
  1535         }
  1536     } else {
  1537         if (x) {
  1538             *x = window->x;
  1539         }
  1540         if (y) {
  1541             *y = window->y;
  1542         }
  1543     }
  1544 }
  1545 
  1546 void
  1547 SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered)
  1548 {
  1549     CHECK_WINDOW_MAGIC(window, );
  1550     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
  1551         const int want = (bordered != SDL_FALSE);  /* normalize the flag. */
  1552         const int have = ((window->flags & SDL_WINDOW_BORDERLESS) == 0);
  1553         if ((want != have) && (_this->SetWindowBordered)) {
  1554             if (want) {
  1555                 window->flags &= ~SDL_WINDOW_BORDERLESS;
  1556             } else {
  1557                 window->flags |= SDL_WINDOW_BORDERLESS;
  1558             }
  1559             _this->SetWindowBordered(_this, window, (SDL_bool) want);
  1560         }
  1561     }
  1562 }
  1563 
  1564 void
  1565 SDL_SetWindowSize(SDL_Window * window, int w, int h)
  1566 {
  1567     CHECK_WINDOW_MAGIC(window, );
  1568     if (w <= 0) {
  1569         SDL_InvalidParamError("w");
  1570         return;
  1571     }
  1572     if (h <= 0) {
  1573         SDL_InvalidParamError("h");
  1574         return;
  1575     }
  1576 
  1577     /* FIXME: Should this change fullscreen modes? */
  1578     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
  1579         window->w = w;
  1580         window->h = h;
  1581         if (_this->SetWindowSize) {
  1582             _this->SetWindowSize(_this, window);
  1583         }
  1584         if (window->w == w && window->h == h) {
  1585             /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
  1586             SDL_OnWindowResized(window);
  1587         }
  1588     }
  1589 }
  1590 
  1591 void
  1592 SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
  1593 {
  1594     CHECK_WINDOW_MAGIC(window, );
  1595     if (w) {
  1596         *w = window->w;
  1597     }
  1598     if (h) {
  1599         *h = window->h;
  1600     }                                
  1601 }
  1602 
  1603 void
  1604 SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h)
  1605 {
  1606     CHECK_WINDOW_MAGIC(window, );
  1607     if (min_w <= 0) {
  1608         SDL_InvalidParamError("min_w");
  1609         return;
  1610     }
  1611     if (min_h <= 0) {
  1612         SDL_InvalidParamError("min_h");
  1613         return;
  1614     }
  1615     
  1616     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
  1617         window->min_w = min_w;
  1618         window->min_h = min_h;
  1619         if (_this->SetWindowMinimumSize) {
  1620             _this->SetWindowMinimumSize(_this, window);
  1621         }
  1622         /* Ensure that window is not smaller than minimal size */
  1623         SDL_SetWindowSize(window, SDL_max(window->w, window->min_w), SDL_max(window->h, window->min_h));
  1624     }
  1625 }
  1626 
  1627 void
  1628 SDL_GetWindowMinimumSize(SDL_Window * window, int *min_w, int *min_h)
  1629 {
  1630     CHECK_WINDOW_MAGIC(window, );
  1631     if (min_w) {
  1632         *min_w = window->min_w;
  1633     }
  1634     if (min_h) {
  1635         *min_h = window->min_h;
  1636     }
  1637 }
  1638 
  1639 void
  1640 SDL_SetWindowMaximumSize(SDL_Window * window, int max_w, int max_h)
  1641 {
  1642     CHECK_WINDOW_MAGIC(window, );
  1643     if (max_w <= 0) {
  1644         SDL_InvalidParamError("max_w");
  1645         return;
  1646     }
  1647     if (max_h <= 0) {
  1648         SDL_InvalidParamError("max_h");
  1649         return;
  1650     }
  1651     
  1652     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
  1653         window->max_w = max_w;
  1654         window->max_h = max_h;
  1655         if (_this->SetWindowMaximumSize) {
  1656             _this->SetWindowMaximumSize(_this, window);
  1657         }
  1658         /* Ensure that window is not larger than maximal size */
  1659         SDL_SetWindowSize(window, SDL_min(window->w, window->max_w), SDL_min(window->h, window->max_h));
  1660     }
  1661 }
  1662 
  1663 void
  1664 SDL_GetWindowMaximumSize(SDL_Window * window, int *max_w, int *max_h)
  1665 {
  1666     CHECK_WINDOW_MAGIC(window, );
  1667     if (max_w) {
  1668         *max_w = window->max_w;
  1669     }
  1670     if (max_h) {
  1671         *max_h = window->max_h;
  1672     }
  1673 }
  1674 
  1675 void
  1676 SDL_ShowWindow(SDL_Window * window)
  1677 {
  1678     CHECK_WINDOW_MAGIC(window, );
  1679 
  1680     if (window->flags & SDL_WINDOW_SHOWN) {
  1681         return;
  1682     }
  1683 
  1684     if (_this->ShowWindow) {
  1685         _this->ShowWindow(_this, window);
  1686     }
  1687     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
  1688 }
  1689 
  1690 void
  1691 SDL_HideWindow(SDL_Window * window)
  1692 {
  1693     CHECK_WINDOW_MAGIC(window, );
  1694 
  1695     if (!(window->flags & SDL_WINDOW_SHOWN)) {
  1696         return;
  1697     }
  1698 
  1699     SDL_UpdateFullscreenMode(window, SDL_FALSE);
  1700 
  1701     if (_this->HideWindow) {
  1702         _this->HideWindow(_this, window);
  1703     }
  1704     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
  1705 }
  1706 
  1707 void
  1708 SDL_RaiseWindow(SDL_Window * window)
  1709 {
  1710     CHECK_WINDOW_MAGIC(window, );
  1711 
  1712     if (!(window->flags & SDL_WINDOW_SHOWN)) {
  1713         return;
  1714     }
  1715     if (_this->RaiseWindow) {
  1716         _this->RaiseWindow(_this, window);
  1717     }
  1718 }
  1719 
  1720 void
  1721 SDL_MaximizeWindow(SDL_Window * window)
  1722 {
  1723     CHECK_WINDOW_MAGIC(window, );
  1724 
  1725     if (window->flags & SDL_WINDOW_MAXIMIZED) {
  1726         return;
  1727     }
  1728 
  1729     if (_this->MaximizeWindow) {
  1730         _this->MaximizeWindow(_this, window);
  1731     }
  1732 }
  1733 
  1734 void
  1735 SDL_MinimizeWindow(SDL_Window * window)
  1736 {
  1737     CHECK_WINDOW_MAGIC(window, );
  1738 
  1739     if (window->flags & SDL_WINDOW_MINIMIZED) {
  1740         return;
  1741     }
  1742 
  1743     SDL_UpdateFullscreenMode(window, SDL_FALSE);
  1744 
  1745     if (_this->MinimizeWindow) {
  1746         _this->MinimizeWindow(_this, window);
  1747     }
  1748 }
  1749 
  1750 void
  1751 SDL_RestoreWindow(SDL_Window * window)
  1752 {
  1753     CHECK_WINDOW_MAGIC(window, );
  1754 
  1755     if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
  1756         return;
  1757     }
  1758 
  1759     if (_this->RestoreWindow) {
  1760         _this->RestoreWindow(_this, window);
  1761     }
  1762 }
  1763 
  1764 #define FULLSCREEN_MASK ( SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN )
  1765 int
  1766 SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
  1767 {
  1768     CHECK_WINDOW_MAGIC(window, -1);
  1769 
  1770 	flags &= FULLSCREEN_MASK;
  1771 	
  1772     if ( flags == (window->flags & FULLSCREEN_MASK) ) {
  1773         return 0;
  1774     }
  1775 	
  1776 	/* clear the previous flags and OR in the new ones */
  1777 	window->flags &= ~FULLSCREEN_MASK;
  1778     window->flags |= flags;
  1779 
  1780     SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
  1781 
  1782     return 0;
  1783 }
  1784 
  1785 static SDL_Surface *
  1786 SDL_CreateWindowFramebuffer(SDL_Window * window)
  1787 {
  1788     Uint32 format;
  1789     void *pixels;
  1790     int pitch;
  1791     int bpp;
  1792     Uint32 Rmask, Gmask, Bmask, Amask;
  1793 
  1794     if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
  1795         return NULL;
  1796     }
  1797 
  1798     if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
  1799         return NULL;
  1800     }
  1801 
  1802     if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
  1803         return NULL;
  1804     }
  1805 
  1806     return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
  1807 }
  1808 
  1809 SDL_Surface *
  1810 SDL_GetWindowSurface(SDL_Window * window)
  1811 {
  1812     CHECK_WINDOW_MAGIC(window, NULL);
  1813 
  1814     if (!window->surface_valid) {
  1815         if (window->surface) {
  1816             window->surface->flags &= ~SDL_DONTFREE;
  1817             SDL_FreeSurface(window->surface);
  1818         }
  1819         window->surface = SDL_CreateWindowFramebuffer(window);
  1820         if (window->surface) {
  1821             window->surface_valid = SDL_TRUE;
  1822             window->surface->flags |= SDL_DONTFREE;
  1823         }
  1824     }
  1825     return window->surface;
  1826 }
  1827 
  1828 int
  1829 SDL_UpdateWindowSurface(SDL_Window * window)
  1830 {
  1831     SDL_Rect full_rect;
  1832 
  1833     CHECK_WINDOW_MAGIC(window, -1);
  1834 
  1835     full_rect.x = 0;
  1836     full_rect.y = 0;
  1837     full_rect.w = window->w;
  1838     full_rect.h = window->h;
  1839     return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
  1840 }
  1841 
  1842 int
  1843 SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
  1844                              int numrects)
  1845 {
  1846     CHECK_WINDOW_MAGIC(window, -1);
  1847 
  1848     if (!window->surface_valid) {
  1849         return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
  1850     }
  1851 
  1852     return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
  1853 }
  1854 
  1855 int
  1856 SDL_SetWindowBrightness(SDL_Window * window, float brightness)
  1857 {
  1858     Uint16 ramp[256];
  1859     int status;
  1860 
  1861     CHECK_WINDOW_MAGIC(window, -1);
  1862 
  1863     SDL_CalculateGammaRamp(brightness, ramp);
  1864     status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
  1865     if (status == 0) {
  1866         window->brightness = brightness;
  1867     }
  1868     return status;
  1869 }
  1870 
  1871 float
  1872 SDL_GetWindowBrightness(SDL_Window * window)
  1873 {
  1874     CHECK_WINDOW_MAGIC(window, 1.0f);
  1875 
  1876     return window->brightness;
  1877 }
  1878 
  1879 int
  1880 SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
  1881                                             const Uint16 * green,
  1882                                             const Uint16 * blue)
  1883 {
  1884     CHECK_WINDOW_MAGIC(window, -1);
  1885 
  1886     if (!_this->SetWindowGammaRamp) {
  1887         return SDL_Unsupported();
  1888     }
  1889 
  1890     if (!window->gamma) {
  1891         if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
  1892             return -1;
  1893         }
  1894     }
  1895 
  1896     if (red) {
  1897         SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
  1898     }
  1899     if (green) {
  1900         SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
  1901     }
  1902     if (blue) {
  1903         SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
  1904     }
  1905     if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
  1906         return _this->SetWindowGammaRamp(_this, window, window->gamma);
  1907     } else {
  1908         return 0;
  1909     }
  1910 }
  1911 
  1912 int
  1913 SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
  1914                                             Uint16 * green,
  1915                                             Uint16 * blue)
  1916 {
  1917     CHECK_WINDOW_MAGIC(window, -1);
  1918 
  1919     if (!window->gamma) {
  1920         int i;
  1921 
  1922         window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
  1923         if (!window->gamma) {
  1924             return SDL_OutOfMemory();
  1925         }
  1926         window->saved_gamma = window->gamma + 3*256;
  1927 
  1928         if (_this->GetWindowGammaRamp) {
  1929             if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
  1930                 return -1;
  1931             }
  1932         } else {
  1933             /* Create an identity gamma ramp */
  1934             for (i = 0; i < 256; ++i) {
  1935                 Uint16 value = (Uint16)((i << 8) | i);
  1936 
  1937                 window->gamma[0*256+i] = value;
  1938                 window->gamma[1*256+i] = value;
  1939                 window->gamma[2*256+i] = value;
  1940             }
  1941         }
  1942         SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
  1943     }
  1944 
  1945     if (red) {
  1946         SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
  1947     }
  1948     if (green) {
  1949         SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
  1950     }
  1951     if (blue) {
  1952         SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
  1953     }
  1954     return 0;
  1955 }
  1956 
  1957 void
  1958 SDL_UpdateWindowGrab(SDL_Window * window)
  1959 {
  1960     if (_this->SetWindowGrab) {
  1961         SDL_bool grabbed;
  1962         if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
  1963             (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
  1964             grabbed = SDL_TRUE;
  1965         } else {
  1966             grabbed = SDL_FALSE;
  1967         }
  1968         _this->SetWindowGrab(_this, window, grabbed);
  1969     }
  1970 }
  1971 
  1972 void
  1973 SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
  1974 {
  1975     CHECK_WINDOW_MAGIC(window, );
  1976 
  1977     if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
  1978         return;
  1979     }
  1980     if (grabbed) {
  1981         window->flags |= SDL_WINDOW_INPUT_GRABBED;
  1982     } else {
  1983         window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
  1984     }
  1985     SDL_UpdateWindowGrab(window);
  1986 }
  1987 
  1988 SDL_bool
  1989 SDL_GetWindowGrab(SDL_Window * window)
  1990 {
  1991     CHECK_WINDOW_MAGIC(window, SDL_FALSE);
  1992 
  1993     return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
  1994 }
  1995 
  1996 void
  1997 SDL_OnWindowShown(SDL_Window * window)
  1998 {
  1999     SDL_OnWindowRestored(window);
  2000 }
  2001 
  2002 void
  2003 SDL_OnWindowHidden(SDL_Window * window)
  2004 {
  2005     SDL_UpdateFullscreenMode(window, SDL_FALSE);
  2006 }
  2007 
  2008 void
  2009 SDL_OnWindowResized(SDL_Window * window)
  2010 {
  2011     window->surface_valid = SDL_FALSE;
  2012     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
  2013 }
  2014 
  2015 void
  2016 SDL_OnWindowMinimized(SDL_Window * window)
  2017 {
  2018     SDL_UpdateFullscreenMode(window, SDL_FALSE);
  2019 }
  2020 
  2021 void
  2022 SDL_OnWindowRestored(SDL_Window * window)
  2023 {
  2024     SDL_RaiseWindow(window);
  2025 
  2026     if (FULLSCREEN_VISIBLE(window)) {
  2027         SDL_UpdateFullscreenMode(window, SDL_TRUE);
  2028     }
  2029 }
  2030 
  2031 void
  2032 SDL_OnWindowEnter(SDL_Window * window)
  2033 {
  2034     if (_this->OnWindowEnter) {
  2035         _this->OnWindowEnter(_this, window);
  2036     }
  2037 }
  2038 
  2039 void
  2040 SDL_OnWindowLeave(SDL_Window * window)
  2041 {
  2042 }
  2043 
  2044 void
  2045 SDL_OnWindowFocusGained(SDL_Window * window)
  2046 {
  2047     SDL_Mouse *mouse = SDL_GetMouse();
  2048 
  2049     if (window->gamma && _this->SetWindowGammaRamp) {
  2050         _this->SetWindowGammaRamp(_this, window, window->gamma);
  2051     }
  2052 
  2053     if (mouse && mouse->relative_mode) {
  2054         SDL_SetMouseFocus(window);
  2055         SDL_WarpMouseInWindow(window, window->w/2, window->h/2);
  2056     }
  2057 
  2058     SDL_UpdateWindowGrab(window);
  2059 }
  2060 
  2061 static SDL_bool ShouldMinimizeOnFocusLoss()
  2062 {
  2063 	const char *hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
  2064 	if (hint) {
  2065 		if (*hint == '0') {
  2066 			return SDL_FALSE;
  2067 		} else {
  2068 			return SDL_TRUE;
  2069 		}
  2070 	}
  2071 	return SDL_TRUE;
  2072 }
  2073 
  2074 void
  2075 SDL_OnWindowFocusLost(SDL_Window * window)
  2076 {
  2077     SDL_Mouse *mouse = SDL_GetMouse();
  2078 
  2079     if (window->gamma && _this->SetWindowGammaRamp) {
  2080         _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
  2081     }
  2082 
  2083     if (mouse && mouse->relative_mode) {
  2084         /* Restore the expected mouse position */
  2085         SDL_WarpMouseInWindow(window, mouse->original_x, mouse->original_y);
  2086     }
  2087 
  2088     SDL_UpdateWindowGrab(window);
  2089 
  2090     /* If we're fullscreen on a single-head system and lose focus, minimize */
  2091 	 if ((window->flags & SDL_WINDOW_FULLSCREEN) && ShouldMinimizeOnFocusLoss() ) {
  2092 			SDL_MinimizeWindow(window);
  2093     }
  2094 }
  2095 
  2096 SDL_Window *
  2097 SDL_GetFocusWindow(void)
  2098 {
  2099     SDL_Window *window;
  2100 
  2101     if (!_this) {
  2102         return NULL;
  2103     }
  2104     for (window = _this->windows; window; window = window->next) {
  2105         if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
  2106             return window;
  2107         }
  2108     }
  2109     return NULL;
  2110 }
  2111 
  2112 void
  2113 SDL_DestroyWindow(SDL_Window * window)
  2114 {
  2115     SDL_VideoDisplay *display;
  2116 
  2117     CHECK_WINDOW_MAGIC(window, );
  2118 
  2119     /* Restore video mode, etc. */
  2120     SDL_HideWindow(window);
  2121 
  2122     /* Make sure this window no longer has focus */
  2123     if (SDL_GetKeyboardFocus() == window) {
  2124         SDL_SetKeyboardFocus(NULL);
  2125     }
  2126     if (SDL_GetMouseFocus() == window) {
  2127         SDL_SetMouseFocus(NULL);
  2128     }
  2129 
  2130     /* make no context current if this is the current context window. */
  2131     if (window->flags & SDL_WINDOW_OPENGL) {
  2132         if (_this->current_glwin == window) {
  2133             SDL_GL_MakeCurrent(window, NULL);
  2134         }
  2135     }
  2136 
  2137     if (window->surface) {
  2138         window->surface->flags &= ~SDL_DONTFREE;
  2139         SDL_FreeSurface(window->surface);
  2140     }
  2141     if (_this->DestroyWindowFramebuffer) {
  2142         _this->DestroyWindowFramebuffer(_this, window);
  2143     }
  2144     if (_this->DestroyWindow) {
  2145         _this->DestroyWindow(_this, window);
  2146     }
  2147     if (window->flags & SDL_WINDOW_OPENGL) {
  2148         SDL_GL_UnloadLibrary();
  2149     }
  2150 
  2151     display = SDL_GetDisplayForWindow(window);
  2152     if (display->fullscreen_window == window) {
  2153         display->fullscreen_window = NULL;
  2154     }
  2155 
  2156     /* Now invalidate magic */
  2157     window->magic = NULL;
  2158 
  2159     /* Free memory associated with the window */
  2160     if (window->title) {
  2161         SDL_free(window->title);
  2162     }
  2163     if (window->gamma) {
  2164         SDL_free(window->gamma);
  2165     }
  2166     while (window->data) {
  2167         SDL_WindowUserData *data = window->data;
  2168 
  2169         window->data = data->next;
  2170         SDL_free(data->name);
  2171         SDL_free(data);
  2172     }
  2173 
  2174     /* Unlink the window from the list */
  2175     if (window->next) {
  2176         window->next->prev = window->prev;
  2177     }
  2178     if (window->prev) {
  2179         window->prev->next = window->next;
  2180     } else {
  2181         _this->windows = window->next;
  2182     }
  2183 
  2184     SDL_free(window);
  2185 }
  2186 
  2187 SDL_bool
  2188 SDL_IsScreenSaverEnabled()
  2189 {
  2190     if (!_this) {
  2191         return SDL_TRUE;
  2192     }
  2193     return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
  2194 }
  2195 
  2196 void
  2197 SDL_EnableScreenSaver()
  2198 {
  2199     if (!_this) {
  2200         return;
  2201     }
  2202     if (!_this->suspend_screensaver) {
  2203         return;
  2204     }
  2205     _this->suspend_screensaver = SDL_FALSE;
  2206     if (_this->SuspendScreenSaver) {
  2207         _this->SuspendScreenSaver(_this);
  2208     }
  2209 }
  2210 
  2211 void
  2212 SDL_DisableScreenSaver()
  2213 {
  2214     if (!_this) {
  2215         return;
  2216     }
  2217     if (_this->suspend_screensaver) {
  2218         return;
  2219     }
  2220     _this->suspend_screensaver = SDL_TRUE;
  2221     if (_this->SuspendScreenSaver) {
  2222         _this->SuspendScreenSaver(_this);
  2223     }
  2224 }
  2225 
  2226 void
  2227 SDL_VideoQuit(void)
  2228 {
  2229     int i, j;
  2230 
  2231     if (!_this) {
  2232         return;
  2233     }
  2234 
  2235     /* Halt event processing before doing anything else */
  2236     SDL_QuitQuit();
  2237     SDL_MouseQuit();
  2238     SDL_KeyboardQuit();
  2239     SDL_StopEventLoop();
  2240 
  2241     SDL_EnableScreenSaver();
  2242 
  2243     /* Clean up the system video */
  2244     while (_this->windows) {
  2245         SDL_DestroyWindow(_this->windows);
  2246     }
  2247     _this->VideoQuit(_this);
  2248 
  2249     for (i = _this->num_displays; i--;) {
  2250         SDL_VideoDisplay *display = &_this->displays[i];
  2251         for (j = display->num_display_modes; j--;) {
  2252             if (display->display_modes[j].driverdata) {
  2253                 SDL_free(display->display_modes[j].driverdata);
  2254                 display->display_modes[j].driverdata = NULL;
  2255             }
  2256         }
  2257         if (display->display_modes) {
  2258             SDL_free(display->display_modes);
  2259             display->display_modes = NULL;
  2260         }
  2261         if (display->desktop_mode.driverdata) {
  2262             SDL_free(display->desktop_mode.driverdata);
  2263             display->desktop_mode.driverdata = NULL;
  2264         }
  2265         if (display->driverdata) {
  2266             SDL_free(display->driverdata);
  2267             display->driverdata = NULL;
  2268         }
  2269     }
  2270     if (_this->displays) {
  2271         for (i = 0; i < _this->num_displays; ++i) {
  2272             SDL_free(_this->displays[i].name);
  2273         }
  2274         SDL_free(_this->displays);
  2275         _this->displays = NULL;
  2276         _this->num_displays = 0;
  2277     }
  2278     if (_this->clipboard_text) {
  2279         SDL_free(_this->clipboard_text);
  2280         _this->clipboard_text = NULL;
  2281     }
  2282     _this->free(_this);
  2283     _this = NULL;
  2284 }
  2285 
  2286 int
  2287 SDL_GL_LoadLibrary(const char *path)
  2288 {
  2289     int retval;
  2290 
  2291     if (!_this) {
  2292         return SDL_UninitializedVideo();
  2293     }
  2294     if (_this->gl_config.driver_loaded) {
  2295         if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
  2296             return SDL_SetError("OpenGL library already loaded");
  2297         }
  2298         retval = 0;
  2299     } else {
  2300         if (!_this->GL_LoadLibrary) {
  2301             return  SDL_SetError("No dynamic GL support in video driver");
  2302         }
  2303         retval = _this->GL_LoadLibrary(_this, path);
  2304     }
  2305     if (retval == 0) {
  2306         ++_this->gl_config.driver_loaded;
  2307     }
  2308     return (retval);
  2309 }
  2310 
  2311 void *
  2312 SDL_GL_GetProcAddress(const char *proc)
  2313 {
  2314     void *func;
  2315 
  2316     if (!_this) {
  2317         SDL_UninitializedVideo();
  2318         return NULL;
  2319     }
  2320     func = NULL;
  2321     if (_this->GL_GetProcAddress) {
  2322         if (_this->gl_config.driver_loaded) {
  2323             func = _this->GL_GetProcAddress(_this, proc);
  2324         } else {
  2325             SDL_SetError("No GL driver has been loaded");
  2326         }
  2327     } else {
  2328         SDL_SetError("No dynamic GL support in video driver");
  2329     }
  2330     return func;
  2331 }
  2332 
  2333 void
  2334 SDL_GL_UnloadLibrary(void)
  2335 {
  2336     if (!_this) {
  2337         SDL_UninitializedVideo();
  2338         return;
  2339     }
  2340     if (_this->gl_config.driver_loaded > 0) {
  2341         if (--_this->gl_config.driver_loaded > 0) {
  2342             return;
  2343         }
  2344         if (_this->GL_UnloadLibrary) {
  2345             _this->GL_UnloadLibrary(_this);
  2346         }
  2347     }
  2348 }
  2349 
  2350 SDL_bool
  2351 SDL_GL_ExtensionSupported(const char *extension)
  2352 {
  2353 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
  2354     const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
  2355     const char *extensions;
  2356     const char *start;
  2357     const char *where, *terminator;
  2358 
  2359     /* Extension names should not have spaces. */
  2360     where = SDL_strchr(extension, ' ');
  2361     if (where || *extension == '\0') {
  2362         return SDL_FALSE;
  2363     }
  2364     /* See if there's an environment variable override */
  2365     start = SDL_getenv(extension);
  2366     if (start && *start == '0') {
  2367         return SDL_FALSE;
  2368     }
  2369     /* Lookup the available extensions */
  2370     glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
  2371     if (glGetStringFunc) {
  2372         extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
  2373     } else {
  2374         extensions = NULL;
  2375     }
  2376     if (!extensions) {
  2377         return SDL_FALSE;
  2378     }
  2379     /*
  2380      * It takes a bit of care to be fool-proof about parsing the OpenGL
  2381      * extensions string. Don't be fooled by sub-strings, etc.
  2382      */
  2383 
  2384     start = extensions;
  2385 
  2386     for (;;) {
  2387         where = SDL_strstr(start, extension);
  2388         if (!where)
  2389             break;
  2390 
  2391         terminator = where + SDL_strlen(extension);
  2392         if (where == start || *(where - 1) == ' ')
  2393             if (*terminator == ' ' || *terminator == '\0')
  2394                 return SDL_TRUE;
  2395 
  2396         start = terminator;
  2397     }
  2398     return SDL_FALSE;
  2399 #else
  2400     return SDL_FALSE;
  2401 #endif
  2402 }
  2403 
  2404 int
  2405 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
  2406 {
  2407 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
  2408     int retval;
  2409 
  2410     if (!_this) {
  2411         return SDL_UninitializedVideo();
  2412     }
  2413     retval = 0;
  2414     switch (attr) {
  2415     case SDL_GL_RED_SIZE:
  2416         _this->gl_config.red_size = value;
  2417         break;
  2418     case SDL_GL_GREEN_SIZE:
  2419         _this->gl_config.green_size = value;
  2420         break;
  2421     case SDL_GL_BLUE_SIZE:
  2422         _this->gl_config.blue_size = value;
  2423         break;
  2424     case SDL_GL_ALPHA_SIZE:
  2425         _this->gl_config.alpha_size = value;
  2426         break;
  2427     case SDL_GL_DOUBLEBUFFER:
  2428         _this->gl_config.double_buffer = value;
  2429         break;
  2430     case SDL_GL_BUFFER_SIZE:
  2431         _this->gl_config.buffer_size = value;
  2432         break;
  2433     case SDL_GL_DEPTH_SIZE:
  2434         _this->gl_config.depth_size = value;
  2435         break;
  2436     case SDL_GL_STENCIL_SIZE:
  2437         _this->gl_config.stencil_size = value;
  2438         break;
  2439     case SDL_GL_ACCUM_RED_SIZE:
  2440         _this->gl_config.accum_red_size = value;
  2441         break;
  2442     case SDL_GL_ACCUM_GREEN_SIZE:
  2443         _this->gl_config.accum_green_size = value;
  2444         break;
  2445     case SDL_GL_ACCUM_BLUE_SIZE:
  2446         _this->gl_config.accum_blue_size = value;
  2447         break;
  2448     case SDL_GL_ACCUM_ALPHA_SIZE:
  2449         _this->gl_config.accum_alpha_size = value;
  2450         break;
  2451     case SDL_GL_STEREO:
  2452         _this->gl_config.stereo = value;
  2453         break;
  2454     case SDL_GL_MULTISAMPLEBUFFERS:
  2455         _this->gl_config.multisamplebuffers = value;
  2456         break;
  2457     case SDL_GL_MULTISAMPLESAMPLES:
  2458         _this->gl_config.multisamplesamples = value;
  2459         break;
  2460     case SDL_GL_ACCELERATED_VISUAL:
  2461         _this->gl_config.accelerated = value;
  2462         break;
  2463     case SDL_GL_RETAINED_BACKING:
  2464         _this->gl_config.retained_backing = value;
  2465         break;
  2466     case SDL_GL_CONTEXT_MAJOR_VERSION:
  2467         _this->gl_config.major_version = value;
  2468         break;
  2469     case SDL_GL_CONTEXT_MINOR_VERSION:
  2470         _this->gl_config.minor_version = value;
  2471         break;
  2472     case SDL_GL_CONTEXT_EGL:
  2473         _this->gl_config.use_egl = value;
  2474         break;
  2475     case SDL_GL_CONTEXT_FLAGS:
  2476         if( value & ~(SDL_GL_CONTEXT_DEBUG_FLAG |
  2477 		      SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG |
  2478 		      SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG |
  2479 		      SDL_GL_CONTEXT_RESET_ISOLATION_FLAG) ) {
  2480 	    retval = SDL_SetError("Unknown OpenGL context flag %d", value);
  2481 	    break;
  2482 	}
  2483         _this->gl_config.flags = value;
  2484         break;
  2485     case SDL_GL_CONTEXT_PROFILE_MASK:
  2486         if( value != 0 &&
  2487 	    value != SDL_GL_CONTEXT_PROFILE_CORE &&
  2488 	    value != SDL_GL_CONTEXT_PROFILE_COMPATIBILITY &&
  2489 	    value != SDL_GL_CONTEXT_PROFILE_ES ) {
  2490 	    retval = SDL_SetError("Unknown OpenGL context profile %d", value);
  2491 	    break;
  2492 	}
  2493         _this->gl_config.profile_mask = value;
  2494         break;
  2495     case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
  2496         _this->gl_config.share_with_current_context = value;
  2497 	break;
  2498     default:
  2499         retval = SDL_SetError("Unknown OpenGL attribute");
  2500         break;
  2501     }
  2502     return retval;
  2503 #else
  2504     return SDL_Unsupported();
  2505 #endif /* SDL_VIDEO_OPENGL */
  2506 }
  2507 
  2508 int
  2509 SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
  2510 {
  2511 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
  2512     void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
  2513     GLenum(APIENTRY * glGetErrorFunc) (void);
  2514     GLenum attrib = 0;
  2515     GLenum error = 0;
  2516 
  2517     glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
  2518     if (!glGetIntegervFunc) {
  2519         return -1;
  2520     }
  2521 
  2522     glGetErrorFunc = SDL_GL_GetProcAddress("glGetError");
  2523     if (!glGetErrorFunc) {
  2524         return -1;
  2525     }
  2526 
  2527     /* Clear value in any case */
  2528     *value = 0;
  2529 
  2530     switch (attr) {
  2531     case SDL_GL_RED_SIZE:
  2532         attrib = GL_RED_BITS;
  2533         break;
  2534     case SDL_GL_BLUE_SIZE:
  2535         attrib = GL_BLUE_BITS;
  2536         break;
  2537     case SDL_GL_GREEN_SIZE:
  2538         attrib = GL_GREEN_BITS;
  2539         break;
  2540     case SDL_GL_ALPHA_SIZE:
  2541         attrib = GL_ALPHA_BITS;
  2542         break;
  2543     case SDL_GL_DOUBLEBUFFER:
  2544 #if SDL_VIDEO_OPENGL
  2545         attrib = GL_DOUBLEBUFFER;
  2546         break;
  2547 #else
  2548         /* OpenGL ES 1.0 and above specifications have EGL_SINGLE_BUFFER      */
  2549         /* parameter which switches double buffer to single buffer. OpenGL ES */
  2550         /* SDL driver must set proper value after initialization              */
  2551         *value = _this->gl_config.double_buffer;
  2552         return 0;
  2553 #endif
  2554     case SDL_GL_DEPTH_SIZE:
  2555         attrib = GL_DEPTH_BITS;
  2556         break;
  2557     case SDL_GL_STENCIL_SIZE:
  2558         attrib = GL_STENCIL_BITS;
  2559         break;
  2560 #if SDL_VIDEO_OPENGL
  2561     case SDL_GL_ACCUM_RED_SIZE:
  2562         attrib = GL_ACCUM_RED_BITS;
  2563         break;
  2564     case SDL_GL_ACCUM_GREEN_SIZE:
  2565         attrib = GL_ACCUM_GREEN_BITS;
  2566         break;
  2567     case SDL_GL_ACCUM_BLUE_SIZE:
  2568         attrib = GL_ACCUM_BLUE_BITS;
  2569         break;
  2570     case SDL_GL_ACCUM_ALPHA_SIZE:
  2571         attrib = GL_ACCUM_ALPHA_BITS;
  2572         break;
  2573     case SDL_GL_STEREO:
  2574         attrib = GL_STEREO;
  2575         break;
  2576 #else
  2577     case SDL_GL_ACCUM_RED_SIZE:
  2578     case SDL_GL_ACCUM_GREEN_SIZE:
  2579     case SDL_GL_ACCUM_BLUE_SIZE:
  2580     case SDL_GL_ACCUM_ALPHA_SIZE:
  2581     case SDL_GL_STEREO:
  2582         /* none of these are supported in OpenGL ES */
  2583         *value = 0;
  2584         return 0;
  2585 #endif
  2586     case SDL_GL_MULTISAMPLEBUFFERS:
  2587 #if SDL_VIDEO_OPENGL
  2588         attrib = GL_SAMPLE_BUFFERS_ARB;
  2589 #else
  2590         attrib = GL_SAMPLE_BUFFERS;
  2591 #endif
  2592         break;
  2593     case SDL_GL_MULTISAMPLESAMPLES:
  2594 #if SDL_VIDEO_OPENGL
  2595         attrib = GL_SAMPLES_ARB;
  2596 #else
  2597         attrib = GL_SAMPLES;
  2598 #endif
  2599         break;
  2600     case SDL_GL_BUFFER_SIZE:
  2601         {
  2602             GLint bits = 0;
  2603             GLint component;
  2604 
  2605             /*
  2606              * there doesn't seem to be a single flag in OpenGL
  2607              * for this!
  2608              */
  2609             glGetIntegervFunc(GL_RED_BITS, &component);
  2610             bits += component;
  2611             glGetIntegervFunc(GL_GREEN_BITS, &component);
  2612             bits += component;
  2613             glGetIntegervFunc(GL_BLUE_BITS, &component);
  2614             bits += component;
  2615             glGetIntegervFunc(GL_ALPHA_BITS, &component);
  2616             bits += component;
  2617 
  2618             *value = bits;
  2619             return 0;
  2620         }
  2621     case SDL_GL_ACCELERATED_VISUAL:
  2622         {
  2623             /* FIXME: How do we get this information? */
  2624             *value = (_this->gl_config.accelerated != 0);
  2625             return 0;
  2626         }
  2627     case SDL_GL_RETAINED_BACKING:
  2628         {
  2629             *value = _this->gl_config.retained_backing;
  2630             return 0;
  2631         }
  2632     case SDL_GL_CONTEXT_MAJOR_VERSION:
  2633         {
  2634             *value = _this->gl_config.major_version;
  2635             return 0;
  2636         }
  2637     case SDL_GL_CONTEXT_MINOR_VERSION:
  2638         {
  2639             *value = _this->gl_config.minor_version;
  2640             return 0;
  2641         }
  2642     case SDL_GL_CONTEXT_EGL:
  2643         {
  2644             *value = _this->gl_config.use_egl;
  2645             return 0;
  2646         }
  2647     case SDL_GL_CONTEXT_FLAGS:
  2648         {
  2649             *value = _this->gl_config.flags;
  2650             return 0;
  2651         }
  2652     case SDL_GL_CONTEXT_PROFILE_MASK:
  2653         {
  2654             *value = _this->gl_config.profile_mask;
  2655             return 0;
  2656         }
  2657     case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
  2658         {
  2659             *value = _this->gl_config.share_with_current_context;
  2660             return 0;
  2661         }
  2662     default:
  2663         return SDL_SetError("Unknown OpenGL attribute");
  2664     }
  2665 
  2666     glGetIntegervFunc(attrib, (GLint *) value);
  2667     error = glGetErrorFunc();
  2668     if (error != GL_NO_ERROR) {
  2669         if (error == GL_INVALID_ENUM) {
  2670             return SDL_SetError("OpenGL error: GL_INVALID_ENUM");
  2671         } else if (error == GL_INVALID_VALUE) {
  2672             return SDL_SetError("OpenGL error: GL_INVALID_VALUE");
  2673         }
  2674         return SDL_SetError("OpenGL error: %08X", error);
  2675     }
  2676     return 0;
  2677 #else
  2678     return SDL_Unsupported();
  2679 #endif /* SDL_VIDEO_OPENGL */
  2680 }
  2681 
  2682 SDL_GLContext
  2683 SDL_GL_CreateContext(SDL_Window * window)
  2684 {
  2685     SDL_GLContext ctx = NULL;
  2686     CHECK_WINDOW_MAGIC(window, NULL);
  2687 
  2688     if (!(window->flags & SDL_WINDOW_OPENGL)) {
  2689         SDL_SetError("The specified window isn't an OpenGL window");
  2690         return NULL;
  2691     }
  2692 
  2693     ctx = _this->GL_CreateContext(_this, window);
  2694 
  2695     /* Creating a context is assumed to make it current in the SDL driver. */
  2696     _this->current_glwin = window;
  2697     _this->current_glctx = ctx;
  2698 
  2699     return ctx;
  2700 }
  2701 
  2702 int
  2703 SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx)
  2704 {
  2705     int retval;
  2706 
  2707     if (!ctx) {
  2708         window = NULL;
  2709     } else {
  2710         CHECK_WINDOW_MAGIC(window, -1);
  2711 
  2712         if (!(window->flags & SDL_WINDOW_OPENGL)) {
  2713             return SDL_SetError("The specified window isn't an OpenGL window");
  2714         }
  2715     }
  2716 
  2717     if ((window == _this->current_glwin) && (ctx == _this->current_glctx)) {
  2718         retval = 0;  /* we're already current. */
  2719     } else {
  2720         retval = _this->GL_MakeCurrent(_this, window, ctx);
  2721         if (retval == 0) {
  2722             _this->current_glwin = window;
  2723             _this->current_glctx = ctx;
  2724         }
  2725     }
  2726 
  2727     return retval;
  2728 }
  2729 
  2730 int
  2731 SDL_GL_SetSwapInterval(int interval)
  2732 {
  2733     if (!_this) {
  2734         return SDL_UninitializedVideo();
  2735     } else if (_this->current_glctx == NULL) {
  2736         return SDL_SetError("No OpenGL context has been made current");
  2737     } else if (_this->GL_SetSwapInterval) {
  2738         return _this->GL_SetSwapInterval(_this, interval);
  2739     } else {
  2740         return SDL_SetError("Setting the swap interval is not supported");
  2741     }
  2742 }
  2743 
  2744 int
  2745 SDL_GL_GetSwapInterval(void)
  2746 {
  2747     if (!_this) {
  2748         return 0;
  2749     } else if (_this->current_glctx == NULL) {
  2750         return 0;
  2751     } else if (_this->GL_GetSwapInterval) {
  2752         return _this->GL_GetSwapInterval(_this);
  2753     } else {
  2754         return 0;
  2755     }
  2756 }
  2757 
  2758 void
  2759 SDL_GL_SwapWindow(SDL_Window * window)
  2760 {
  2761     CHECK_WINDOW_MAGIC(window, );
  2762 
  2763     if (!(window->flags & SDL_WINDOW_OPENGL)) {
  2764         SDL_SetError("The specified window isn't an OpenGL window");
  2765         return;
  2766     }
  2767     _this->GL_SwapWindow(_this, window);
  2768 }
  2769 
  2770 void
  2771 SDL_GL_DeleteContext(SDL_GLContext context)
  2772 {
  2773     if (!_this || !context) {
  2774         return;
  2775     }
  2776 
  2777     if (_this->current_glctx == context) {
  2778         SDL_GL_MakeCurrent(NULL, NULL);
  2779     }
  2780 
  2781     _this->GL_DeleteContext(_this, context);
  2782 }
  2783 
  2784 #if 0                           // FIXME
  2785 /*
  2786  * Utility function used by SDL_WM_SetIcon(); flags & 1 for color key, flags
  2787  * & 2 for alpha channel.
  2788  */
  2789 static void
  2790 CreateMaskFromColorKeyOrAlpha(SDL_Surface * icon, Uint8 * mask, int flags)
  2791 {
  2792     int x, y;
  2793     Uint32 colorkey;
  2794 #define SET_MASKBIT(icon, x, y, mask) \
  2795 	mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
  2796 
  2797     colorkey = icon->format->colorkey;
  2798     switch (icon->format->BytesPerPixel) {
  2799     case 1:
  2800         {
  2801             Uint8 *pixels;
  2802             for (y = 0; y < icon->h; ++y) {
  2803                 pixels = (Uint8 *) icon->pixels + y * icon->pitch;
  2804                 for (x = 0; x < icon->w; ++x) {
  2805                     if (*pixels++ == colorkey) {
  2806                         SET_MASKBIT(icon, x, y, mask);
  2807                     }
  2808                 }
  2809             }
  2810         }
  2811         break;
  2812 
  2813     case 2:
  2814         {
  2815             Uint16 *pixels;
  2816             for (y = 0; y < icon->h; ++y) {
  2817                 pixels = (Uint16 *) icon->pixels + y * icon->pitch / 2;
  2818                 for (x = 0; x < icon->w; ++x) {
  2819                     if ((flags & 1) && *pixels == colorkey) {
  2820                         SET_MASKBIT(icon, x, y, mask);
  2821                     } else if ((flags & 2)
  2822                                && (*pixels & icon->format->Amask) == 0) {
  2823                         SET_MASKBIT(icon, x, y, mask);
  2824                     }
  2825                     pixels++;
  2826                 }
  2827             }
  2828         }
  2829         break;
  2830 
  2831     case 4:
  2832         {
  2833             Uint32 *pixels;
  2834             for (y = 0; y < icon->h; ++y) {
  2835                 pixels = (Uint32 *) icon->pixels + y * icon->pitch / 4;
  2836                 for (x = 0; x < icon->w; ++x) {
  2837                     if ((flags & 1) && *pixels == colorkey) {
  2838                         SET_MASKBIT(icon, x, y, mask);
  2839                     } else if ((flags & 2)
  2840                                && (*pixels & icon->format->Amask) == 0) {
  2841                         SET_MASKBIT(icon, x, y, mask);
  2842                     }
  2843                     pixels++;
  2844                 }
  2845             }
  2846         }
  2847         break;
  2848     }
  2849 }
  2850 
  2851 /*
  2852  * Sets the window manager icon for the display window.
  2853  */
  2854 void
  2855 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
  2856 {
  2857     if (icon && _this->SetIcon) {
  2858         /* Generate a mask if necessary, and create the icon! */
  2859         if (mask == NULL) {
  2860             int mask_len = icon->h * (icon->w + 7) / 8;
  2861             int flags = 0;
  2862             mask = (Uint8 *) SDL_malloc(mask_len);
  2863             if (mask == NULL) {
  2864                 return;
  2865             }
  2866             SDL_memset(mask, ~0, mask_len);
  2867             if (icon->flags & SDL_SRCCOLORKEY)
  2868                 flags |= 1;
  2869             if (icon->flags & SDL_SRCALPHA)
  2870                 flags |= 2;
  2871             if (flags) {
  2872                 CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
  2873             }
  2874             _this->SetIcon(_this, icon, mask);
  2875             SDL_free(mask);
  2876         } else {
  2877             _this->SetIcon(_this, icon, mask);
  2878         }
  2879     }
  2880 }
  2881 #endif
  2882 
  2883 SDL_bool
  2884 SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info)
  2885 {
  2886     CHECK_WINDOW_MAGIC(window, SDL_FALSE);
  2887 
  2888     if (!info) {
  2889         return SDL_FALSE;
  2890     }
  2891     info->subsystem = SDL_SYSWM_UNKNOWN;
  2892 
  2893     if (!_this->GetWindowWMInfo) {
  2894         return SDL_FALSE;
  2895     }
  2896     return (_this->GetWindowWMInfo(_this, window, info));
  2897 }
  2898 
  2899 void
  2900 SDL_StartTextInput(void)
  2901 {
  2902     SDL_Window *window;
  2903 
  2904     /* First, enable text events */
  2905     SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE);
  2906     SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
  2907 
  2908     /* Then show the on-screen keyboard, if any */
  2909     window = SDL_GetFocusWindow();
  2910     if (window && _this && _this->SDL_ShowScreenKeyboard) {
  2911         _this->SDL_ShowScreenKeyboard(_this, window);
  2912     }
  2913 
  2914     /* Finally start the text input system */
  2915     if (_this && _this->StartTextInput) {
  2916         _this->StartTextInput(_this);
  2917     }
  2918 }
  2919 
  2920 SDL_bool
  2921 SDL_IsTextInputActive(void)
  2922 {
  2923     return (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE);
  2924 }
  2925 
  2926 void
  2927 SDL_StopTextInput(void)
  2928 {
  2929     SDL_Window *window;
  2930 
  2931     /* Stop the text input system */
  2932     if (_this && _this->StopTextInput) {
  2933         _this->StopTextInput(_this);
  2934     }
  2935 
  2936     /* Hide the on-screen keyboard, if any */
  2937     window = SDL_GetFocusWindow();
  2938     if (window && _this && _this->SDL_HideScreenKeyboard) {
  2939         _this->SDL_HideScreenKeyboard(_this, window);
  2940     }
  2941 
  2942     /* Finally disable text events */
  2943     SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
  2944     SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
  2945 }
  2946 
  2947 void
  2948 SDL_SetTextInputRect(SDL_Rect *rect)
  2949 {
  2950     if (_this && _this->SetTextInputRect) {
  2951         _this->SetTextInputRect(_this, rect);
  2952     }
  2953 }
  2954 
  2955 SDL_bool
  2956 SDL_HasScreenKeyboardSupport(void)
  2957 {
  2958     if (_this && _this->SDL_HasScreenKeyboardSupport) {
  2959         return _this->SDL_HasScreenKeyboardSupport(_this);
  2960     }
  2961     return SDL_FALSE;
  2962 }
  2963 
  2964 SDL_bool
  2965 SDL_IsScreenKeyboardShown(SDL_Window *window)
  2966 {
  2967     if (window && _this && _this->SDL_IsScreenKeyboardShown) {
  2968         return _this->SDL_IsScreenKeyboardShown(_this, window);
  2969     }
  2970     return SDL_FALSE;
  2971 }
  2972 
  2973 #if SDL_VIDEO_DRIVER_WINDOWS
  2974 #include "windows/SDL_windowsmessagebox.h"
  2975 #endif
  2976 #if SDL_VIDEO_DRIVER_COCOA
  2977 #include "cocoa/SDL_cocoamessagebox.h"
  2978 #endif
  2979 #if SDL_VIDEO_DRIVER_UIKIT
  2980 #include "uikit/SDL_uikitmessagebox.h"
  2981 #endif
  2982 #if SDL_VIDEO_DRIVER_X11
  2983 #include "x11/SDL_x11messagebox.h"
  2984 #endif
  2985 
  2986 int
  2987 SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
  2988 {
  2989     int dummybutton;
  2990 	int retval = -1;
  2991 	SDL_bool relative_mode = SDL_GetRelativeMouseMode();
  2992 	int show_cursor_prev = SDL_ShowCursor( 1 );
  2993 
  2994 	SDL_SetRelativeMouseMode( SDL_FALSE );
  2995 
  2996     if (!buttonid) {
  2997         buttonid = &dummybutton;
  2998     }
  2999     if (_this && _this->ShowMessageBox) {
  3000         if (_this->ShowMessageBox(_this, messageboxdata, buttonid) == 0) {
  3001 			retval = 0;
  3002         }
  3003     }
  3004 
  3005     /* It's completely fine to call this function before video is initialized */
  3006 #if SDL_VIDEO_DRIVER_WINDOWS
  3007     if ((retval == -1) && (WIN_ShowMessageBox(messageboxdata, buttonid) == 0)) {
  3008         retval = 0;
  3009     }
  3010 #endif
  3011 #if SDL_VIDEO_DRIVER_COCOA
  3012     if ((retval == -1) && (Cocoa_ShowMessageBox(messageboxdata, buttonid) == 0)) {
  3013         retval = 0;
  3014     }
  3015 #endif
  3016 #if SDL_VIDEO_DRIVER_UIKIT
  3017     if ((retval == -1) && (UIKit_ShowMessageBox(messageboxdata, buttonid) == 0)) {
  3018         retval = 0;
  3019     }
  3020 #endif
  3021 #if SDL_VIDEO_DRIVER_X11
  3022     if ((retval == -1) && (X11_ShowMessageBox(messageboxdata, buttonid) == 0)) {
  3023         retval = 0;
  3024     }
  3025 #endif
  3026 
  3027 	SDL_ShowCursor( show_cursor_prev );
  3028 	SDL_SetRelativeMouseMode( relative_mode );
  3029 
  3030 	if(retval == -1) {
  3031 		SDL_SetError("No message system available");
  3032 	}
  3033     return retval;
  3034 }
  3035 
  3036 int
  3037 SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window)
  3038 {
  3039     SDL_MessageBoxData data;
  3040     SDL_MessageBoxButtonData button;
  3041 
  3042     SDL_zero(data);
  3043     data.flags = flags;
  3044     data.title = title;
  3045     data.message = message;
  3046     data.numbuttons = 1;
  3047     data.buttons = &button;
  3048     data.window = window;
  3049 
  3050     SDL_zero(button);
  3051     button.flags |= SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
  3052     button.flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
  3053     button.text = "OK";
  3054 
  3055     return SDL_ShowMessageBox(&data, NULL);
  3056 }
  3057 
  3058 SDL_bool
  3059 SDL_ShouldAllowTopmost()
  3060 {
  3061 	const char *hint = SDL_GetHint(SDL_HINT_ALLOW_TOPMOST);
  3062 	if (hint) {
  3063 		if (*hint == '0') {
  3064 			return SDL_FALSE;
  3065 		} else {
  3066 			return SDL_TRUE;
  3067 		}
  3068 	}
  3069 	return SDL_TRUE;
  3070 }
  3071 
  3072 /* vi: set ts=4 sw=4 expandtab: */