src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 02 Aug 2017 10:22:48 -0700
changeset 11175 cbc6a8a5b701
parent 11171 6f6e8880cd37
child 11183 2b3b51f36654
permissions -rw-r--r--
Fixed bug 3690 - SDL2 KMS/DRM render context support

Manuel

The attached patch adds support for KMS/DRM context graphics.

It builds with no problem on X86_64 GNU/Linux systems, provided the needed libraries are present, and on ARM GNU/Linux systems that have KMS/DRM support and a GLES2 implementation.
Tested on Raspberry Pi: KMS/DRM is what the Raspberry Pi will use as default in the near future, once the propietary DispmanX API by Broadcom is overtaken by open graphics stack, it's possible to boot current Raspbian system in KMS mode by adding "dtoverlay=vc4-kms-v3d" to config.txt on Raspbian's boot partition.
X86 systems use KMS right away in every current GNU/Linux system.

Simple build instructions:

$./autogen.sh
$./configure --enable-video-kmsdrm
$make
slouken@8582
     1
/*
slouken@8582
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@8582
     4
slouken@8582
     5
  This software is provided 'as-is', without any express or implied
slouken@8582
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@8582
     7
  arising from the use of this software.
slouken@8582
     8
slouken@8582
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@8582
    10
  including commercial applications, and to alter it and redistribute it
slouken@8582
    11
  freely, subject to the following restrictions:
slouken@8582
    12
slouken@8582
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@8582
    14
     claim that you wrote the original software. If you use this software
slouken@8582
    15
     in a product, an acknowledgment in the product documentation would be
slouken@8582
    16
     appreciated but is not required.
slouken@8582
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@8582
    18
     misrepresented as being the original software.
slouken@8582
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@8582
    20
*/
icculus@8093
    21
#include "../SDL_internal.h"
slouken@8582
    22
slouken@8582
    23
/* The high-level video driver subsystem */
slouken@8582
    24
slouken@8582
    25
#include "SDL.h"
slouken@8582
    26
#include "SDL_video.h"
slouken@8582
    27
#include "SDL_sysvideo.h"
slouken@8582
    28
#include "SDL_blit.h"
slouken@8582
    29
#include "SDL_pixels_c.h"
slouken@8582
    30
#include "SDL_rect_c.h"
slouken@8582
    31
#include "../events/SDL_events_c.h"
slouken@8582
    32
#include "../timer/SDL_timer_c.h"
slouken@8582
    33
slouken@8616
    34
#include "SDL_syswm.h"
slouken@8616
    35
slouken@8582
    36
#if SDL_VIDEO_OPENGL
slouken@8582
    37
#include "SDL_opengl.h"
slouken@8582
    38
#endif /* SDL_VIDEO_OPENGL */
slouken@8582
    39
slouken@8582
    40
#if SDL_VIDEO_OPENGL_ES
slouken@8582
    41
#include "SDL_opengles.h"
slouken@8582
    42
#endif /* SDL_VIDEO_OPENGL_ES */
slouken@8582
    43
slouken@8582
    44
/* GL and GLES2 headers conflict on Linux 32 bits */
slouken@8582
    45
#if SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL
slouken@8582
    46
#include "SDL_opengles2.h"
slouken@8582
    47
#endif /* SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL */
slouken@8582
    48
slouken@10609
    49
#if !SDL_VIDEO_OPENGL
icculus@9416
    50
#ifndef GL_CONTEXT_RELEASE_BEHAVIOR_KHR
icculus@9416
    51
#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
icculus@9416
    52
#endif
slouken@10609
    53
#endif
icculus@9416
    54
slouken@8582
    55
/* On Windows, windows.h defines CreateWindow */
slouken@8582
    56
#ifdef CreateWindow
slouken@8582
    57
#undef CreateWindow
slouken@8582
    58
#endif
slouken@8582
    59
icculus@10312
    60
#ifdef __EMSCRIPTEN__
icculus@10312
    61
#include <emscripten.h>
icculus@10312
    62
#endif
icculus@10312
    63
slouken@8582
    64
/* Available video drivers */
slouken@8582
    65
static VideoBootStrap *bootstrap[] = {
slouken@8582
    66
#if SDL_VIDEO_DRIVER_COCOA
slouken@8582
    67
    &COCOA_bootstrap,
slouken@8582
    68
#endif
slouken@8582
    69
#if SDL_VIDEO_DRIVER_X11
slouken@8582
    70
    &X11_bootstrap,
slouken@8582
    71
#endif
icculus@8153
    72
#if SDL_VIDEO_DRIVER_MIR
icculus@8153
    73
    &MIR_bootstrap,
icculus@8153
    74
#endif
slouken@9164
    75
#if SDL_VIDEO_DRIVER_WAYLAND
slouken@9164
    76
    &Wayland_bootstrap,
slouken@9164
    77
#endif
slouken@9164
    78
#if SDL_VIDEO_DRIVER_VIVANTE
slouken@9164
    79
    &VIVANTE_bootstrap,
slouken@9164
    80
#endif
slouken@8582
    81
#if SDL_VIDEO_DRIVER_DIRECTFB
slouken@8582
    82
    &DirectFB_bootstrap,
slouken@8582
    83
#endif
slouken@8582
    84
#if SDL_VIDEO_DRIVER_WINDOWS
slouken@8582
    85
    &WINDOWS_bootstrap,
slouken@8582
    86
#endif
slouken@8582
    87
#if SDL_VIDEO_DRIVER_WINRT
slouken@8582
    88
    &WINRT_bootstrap,
slouken@8582
    89
#endif
slouken@8582
    90
#if SDL_VIDEO_DRIVER_HAIKU
slouken@8582
    91
    &HAIKU_bootstrap,
slouken@8582
    92
#endif
slouken@8582
    93
#if SDL_VIDEO_DRIVER_PANDORA
slouken@8582
    94
    &PND_bootstrap,
slouken@8582
    95
#endif
slouken@8582
    96
#if SDL_VIDEO_DRIVER_UIKIT
slouken@8582
    97
    &UIKIT_bootstrap,
slouken@8582
    98
#endif
slouken@8582
    99
#if SDL_VIDEO_DRIVER_ANDROID
slouken@8582
   100
    &Android_bootstrap,
slouken@8582
   101
#endif
slouken@8582
   102
#if SDL_VIDEO_DRIVER_PSP
slouken@8582
   103
    &PSP_bootstrap,
slouken@8582
   104
#endif
slouken@8582
   105
#if SDL_VIDEO_DRIVER_RPI
slouken@8582
   106
    &RPI_bootstrap,
slouken@8582
   107
#endif 
slouken@11175
   108
#if SDL_VIDEO_DRIVER_KMSDRM
slouken@11175
   109
    &KMSDRM_bootstrap,
slouken@11175
   110
#endif
gabomdq@8833
   111
#if SDL_VIDEO_DRIVER_NACL
gabomdq@8833
   112
    &NACL_bootstrap,
gabomdq@8833
   113
#endif
icculus@9278
   114
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
icculus@9278
   115
    &Emscripten_bootstrap,
icculus@9278
   116
#endif
icculus@11119
   117
#if SDL_VIDEO_DRIVER_QNX
icculus@11119
   118
    &QNX_bootstrap,
icculus@11119
   119
#endif
slouken@8582
   120
#if SDL_VIDEO_DRIVER_DUMMY
slouken@8582
   121
    &DUMMY_bootstrap,
slouken@8582
   122
#endif
slouken@8582
   123
    NULL
slouken@8582
   124
};
slouken@8582
   125
slouken@8582
   126
static SDL_VideoDevice *_this = NULL;
slouken@8582
   127
slouken@8582
   128
#define CHECK_WINDOW_MAGIC(window, retval) \
slouken@8582
   129
    if (!_this) { \
slouken@8582
   130
        SDL_UninitializedVideo(); \
slouken@8582
   131
        return retval; \
slouken@8582
   132
    } \
slouken@8582
   133
    if (!window || window->magic != &_this->window_magic) { \
slouken@8582
   134
        SDL_SetError("Invalid window"); \
slouken@8582
   135
        return retval; \
slouken@8582
   136
    }
slouken@8582
   137
slouken@8582
   138
#define CHECK_DISPLAY_INDEX(displayIndex, retval) \
slouken@8582
   139
    if (!_this) { \
slouken@8582
   140
        SDL_UninitializedVideo(); \
slouken@8582
   141
        return retval; \
slouken@8582
   142
    } \
icculus@8651
   143
    SDL_assert(_this->displays != NULL); \
slouken@8582
   144
    if (displayIndex < 0 || displayIndex >= _this->num_displays) { \
slouken@8582
   145
        SDL_SetError("displayIndex must be in the range 0 - %d", \
slouken@8582
   146
                     _this->num_displays - 1); \
slouken@8582
   147
        return retval; \
slouken@8582
   148
    }
slouken@8582
   149
slouken@8818
   150
#define FULLSCREEN_MASK (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN)
slouken@8582
   151
slouken@8582
   152
#ifdef __MACOSX__
slouken@8582
   153
/* Support for Mac OS X fullscreen spaces */
slouken@8582
   154
extern SDL_bool Cocoa_IsWindowInFullscreenSpace(SDL_Window * window);
slouken@8582
   155
extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state);
slouken@8582
   156
#endif
slouken@8582
   157
slouken@8582
   158
slouken@8582
   159
/* Support for framebuffer emulation using an accelerated renderer */
slouken@8582
   160
slouken@8582
   161
#define SDL_WINDOWTEXTUREDATA   "_SDL_WindowTextureData"
slouken@8582
   162
slouken@8582
   163
typedef struct {
slouken@8582
   164
    SDL_Renderer *renderer;
slouken@8582
   165
    SDL_Texture *texture;
slouken@8582
   166
    void *pixels;
slouken@8582
   167
    int pitch;
slouken@8582
   168
    int bytes_per_pixel;
slouken@8582
   169
} SDL_WindowTextureData;
slouken@8582
   170
slouken@8582
   171
static SDL_bool
slouken@8582
   172
ShouldUseTextureFramebuffer()
slouken@8582
   173
{
slouken@8582
   174
    const char *hint;
slouken@8582
   175
slouken@8582
   176
    /* If there's no native framebuffer support then there's no option */
slouken@8582
   177
    if (!_this->CreateWindowFramebuffer) {
slouken@8582
   178
        return SDL_TRUE;
slouken@8582
   179
    }
slouken@8582
   180
slouken@10699
   181
    /* If this is the dummy driver there is no texture support */
slouken@10699
   182
    if (_this->is_dummy) {
slouken@10699
   183
        return SDL_FALSE;
slouken@10699
   184
    }
slouken@10699
   185
slouken@8582
   186
    /* If the user has specified a software renderer we can't use a
slouken@8582
   187
       texture framebuffer, or renderer creation will go recursive.
slouken@8582
   188
     */
slouken@8582
   189
    hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
slouken@8582
   190
    if (hint && SDL_strcasecmp(hint, "software") == 0) {
slouken@8582
   191
        return SDL_FALSE;
slouken@8582
   192
    }
slouken@8582
   193
slouken@8582
   194
    /* See if the user or application wants a specific behavior */
slouken@8582
   195
    hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
slouken@8582
   196
    if (hint) {
slouken@10499
   197
        if (*hint == '0' || SDL_strcasecmp(hint, "false") == 0) {
slouken@8582
   198
            return SDL_FALSE;
slouken@8582
   199
        } else {
slouken@8582
   200
            return SDL_TRUE;
slouken@8582
   201
        }
slouken@8582
   202
    }
slouken@8582
   203
slouken@8582
   204
    /* Each platform has different performance characteristics */
slouken@8582
   205
#if defined(__WIN32__)
slouken@8582
   206
    /* GDI BitBlt() is way faster than Direct3D dynamic textures right now.
slouken@8582
   207
     */
slouken@8582
   208
    return SDL_FALSE;
slouken@8582
   209
slouken@8582
   210
#elif defined(__MACOSX__)
icculus@10781
   211
    /* Mac OS X uses OpenGL as the native fast path (for cocoa and X11) */
slouken@8582
   212
    return SDL_TRUE;
slouken@8582
   213
slouken@8582
   214
#elif defined(__LINUX__)
slouken@8582
   215
    /* Properly configured OpenGL drivers are faster than MIT-SHM */
slouken@8582
   216
#if SDL_VIDEO_OPENGL
slouken@8582
   217
    /* Ugh, find a way to cache this value! */
slouken@8582
   218
    {
slouken@8582
   219
        SDL_Window *window;
slouken@8582
   220
        SDL_GLContext context;
slouken@8582
   221
        SDL_bool hasAcceleratedOpenGL = SDL_FALSE;
slouken@8582
   222
slouken@8582
   223
        window = SDL_CreateWindow("OpenGL test", -32, -32, 32, 32, SDL_WINDOW_OPENGL|SDL_WINDOW_HIDDEN);
slouken@8582
   224
        if (window) {
slouken@8582
   225
            context = SDL_GL_CreateContext(window);
slouken@8582
   226
            if (context) {
slouken@8582
   227
                const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
slouken@8582
   228
                const char *vendor = NULL;
slouken@8582
   229
slouken@8582
   230
                glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
slouken@8582
   231
                if (glGetStringFunc) {
slouken@8582
   232
                    vendor = (const char *) glGetStringFunc(GL_VENDOR);
slouken@8582
   233
                }
brandon@10924
   234
                /* Add more vendors here at will... */
slouken@8582
   235
                if (vendor &&
slouken@8582
   236
                    (SDL_strstr(vendor, "ATI Technologies") ||
slouken@8582
   237
                     SDL_strstr(vendor, "NVIDIA"))) {
slouken@8582
   238
                    hasAcceleratedOpenGL = SDL_TRUE;
slouken@8582
   239
                }
slouken@8582
   240
                SDL_GL_DeleteContext(context);
slouken@8582
   241
            }
slouken@8582
   242
            SDL_DestroyWindow(window);
slouken@8582
   243
        }
brandon@10924
   244
        return hasAcceleratedOpenGL;
slouken@8582
   245
    }
slouken@8582
   246
#elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@8582
   247
    /* Let's be optimistic about this! */
slouken@8582
   248
    return SDL_TRUE;
slouken@8582
   249
#else
slouken@8582
   250
    return SDL_FALSE;
slouken@8582
   251
#endif
slouken@8582
   252
slouken@8582
   253
#else
slouken@8582
   254
    /* Play it safe, assume that if there is a framebuffer driver that it's
slouken@8582
   255
       optimized for the current platform.
slouken@8582
   256
    */
slouken@8582
   257
    return SDL_FALSE;
slouken@8582
   258
#endif
slouken@8582
   259
}
slouken@8582
   260
slouken@8582
   261
static int
slouken@8922
   262
SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
slouken@8582
   263
{
slouken@8582
   264
    SDL_WindowTextureData *data;
slouken@8582
   265
slouken@8582
   266
    data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
slouken@8582
   267
    if (!data) {
slouken@8582
   268
        SDL_Renderer *renderer = NULL;
slouken@8582
   269
        int i;
slouken@8582
   270
        const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
slouken@8582
   271
slouken@8582
   272
        /* Check to see if there's a specific driver requested */
slouken@8582
   273
        if (hint && *hint != '0' && *hint != '1' &&
slouken@10499
   274
            SDL_strcasecmp(hint, "true") != 0 &&
slouken@10499
   275
            SDL_strcasecmp(hint, "false") != 0 &&
slouken@8582
   276
            SDL_strcasecmp(hint, "software") != 0) {
slouken@8582
   277
            for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
slouken@8922
   278
                SDL_RendererInfo info;
slouken@8582
   279
                SDL_GetRenderDriverInfo(i, &info);
slouken@8582
   280
                if (SDL_strcasecmp(info.name, hint) == 0) {
slouken@8582
   281
                    renderer = SDL_CreateRenderer(window, i, 0);
slouken@8582
   282
                    break;
slouken@8582
   283
                }
slouken@8582
   284
            }
slouken@8582
   285
        }
gabomdq@8833
   286
        
slouken@8582
   287
        if (!renderer) {
slouken@8582
   288
            for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
slouken@8922
   289
                SDL_RendererInfo info;
slouken@8582
   290
                SDL_GetRenderDriverInfo(i, &info);
slouken@8582
   291
                if (SDL_strcmp(info.name, "software") != 0) {
slouken@8582
   292
                    renderer = SDL_CreateRenderer(window, i, 0);
slouken@8582
   293
                    if (renderer) {
slouken@8582
   294
                        break;
slouken@8582
   295
                    }
slouken@8582
   296
                }
slouken@8582
   297
            }
slouken@8582
   298
        }
slouken@8582
   299
        if (!renderer) {
slouken@8582
   300
            return SDL_SetError("No hardware accelerated renderers available");
slouken@8582
   301
        }
slouken@8582
   302
slouken@8582
   303
        /* Create the data after we successfully create the renderer (bug #1116) */
slouken@8582
   304
        data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
slouken@8582
   305
        if (!data) {
slouken@8582
   306
            SDL_DestroyRenderer(renderer);
slouken@8582
   307
            return SDL_OutOfMemory();
slouken@8582
   308
        }
slouken@8582
   309
        SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
slouken@8582
   310
slouken@8582
   311
        data->renderer = renderer;
slouken@8582
   312
    }
slouken@8582
   313
slouken@8582
   314
    /* Free any old texture and pixel data */
slouken@8582
   315
    if (data->texture) {
slouken@8582
   316
        SDL_DestroyTexture(data->texture);
slouken@8582
   317
        data->texture = NULL;
slouken@8582
   318
    }
slouken@8582
   319
    SDL_free(data->pixels);
slouken@8582
   320
    data->pixels = NULL;
slouken@8582
   321
slouken@8922
   322
    {
slouken@8922
   323
        SDL_RendererInfo info;
slouken@8922
   324
        Uint32 i;
slouken@8922
   325
slouken@8922
   326
        if (SDL_GetRendererInfo(data->renderer, &info) < 0) {
slouken@8922
   327
            return -1;
slouken@8922
   328
        }
slouken@8922
   329
slouken@8922
   330
        /* Find the first format without an alpha channel */
slouken@8922
   331
        *format = info.texture_formats[0];
slouken@8922
   332
slouken@8922
   333
        for (i = 0; i < info.num_texture_formats; ++i) {
slouken@8922
   334
            if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
slouken@8922
   335
                    !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
slouken@8922
   336
                *format = info.texture_formats[i];
slouken@8922
   337
                break;
slouken@8922
   338
            }
slouken@8582
   339
        }
slouken@8582
   340
    }
slouken@8582
   341
slouken@8582
   342
    data->texture = SDL_CreateTexture(data->renderer, *format,
slouken@8582
   343
                                      SDL_TEXTUREACCESS_STREAMING,
slouken@8582
   344
                                      window->w, window->h);
slouken@8582
   345
    if (!data->texture) {
slouken@8582
   346
        return -1;
slouken@8582
   347
    }
slouken@8582
   348
slouken@8582
   349
    /* Create framebuffer data */
slouken@8582
   350
    data->bytes_per_pixel = SDL_BYTESPERPIXEL(*format);
slouken@8582
   351
    data->pitch = (((window->w * data->bytes_per_pixel) + 3) & ~3);
icculus@10650
   352
icculus@10650
   353
    {
icculus@10650
   354
        /* Make static analysis happy about potential malloc(0) calls. */
icculus@10650
   355
        const size_t allocsize = window->h * data->pitch;
icculus@10650
   356
        data->pixels = SDL_malloc((allocsize > 0) ? allocsize : 1);
icculus@10650
   357
        if (!data->pixels) {
icculus@10650
   358
            return SDL_OutOfMemory();
icculus@10650
   359
        }
slouken@8582
   360
    }
slouken@8582
   361
slouken@8582
   362
    *pixels = data->pixels;
slouken@8582
   363
    *pitch = data->pitch;
slouken@8582
   364
slouken@8582
   365
    /* Make sure we're not double-scaling the viewport */
slouken@8582
   366
    SDL_RenderSetViewport(data->renderer, NULL);
slouken@8582
   367
slouken@8582
   368
    return 0;
slouken@8582
   369
}
slouken@8582
   370
slouken@8582
   371
static int
slouken@8922
   372
SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, const SDL_Rect * rects, int numrects)
slouken@8582
   373
{
slouken@8582
   374
    SDL_WindowTextureData *data;
slouken@8582
   375
    SDL_Rect rect;
slouken@8582
   376
    void *src;
slouken@8582
   377
slouken@8582
   378
    data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
slouken@8582
   379
    if (!data || !data->texture) {
slouken@8582
   380
        return SDL_SetError("No window texture data");
slouken@8582
   381
    }
slouken@8582
   382
slouken@8582
   383
    /* Update a single rect that contains subrects for best DMA performance */
slouken@8582
   384
    if (SDL_GetSpanEnclosingRect(window->w, window->h, numrects, rects, &rect)) {
slouken@8582
   385
        src = (void *)((Uint8 *)data->pixels +
slouken@8582
   386
                        rect.y * data->pitch +
slouken@8582
   387
                        rect.x * data->bytes_per_pixel);
slouken@8582
   388
        if (SDL_UpdateTexture(data->texture, &rect, src, data->pitch) < 0) {
slouken@8582
   389
            return -1;
slouken@8582
   390
        }
slouken@8582
   391
slouken@8582
   392
        if (SDL_RenderCopy(data->renderer, data->texture, NULL, NULL) < 0) {
slouken@8582
   393
            return -1;
slouken@8582
   394
        }
slouken@8582
   395
slouken@8582
   396
        SDL_RenderPresent(data->renderer);
slouken@8582
   397
    }
slouken@8582
   398
    return 0;
slouken@8582
   399
}
slouken@8582
   400
slouken@8582
   401
static void
slouken@8922
   402
SDL_DestroyWindowTexture(SDL_VideoDevice *unused, SDL_Window * window)
slouken@8582
   403
{
slouken@8582
   404
    SDL_WindowTextureData *data;
slouken@8582
   405
slouken@8582
   406
    data = SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, NULL);
slouken@8582
   407
    if (!data) {
slouken@8582
   408
        return;
slouken@8582
   409
    }
slouken@8582
   410
    if (data->texture) {
slouken@8582
   411
        SDL_DestroyTexture(data->texture);
slouken@8582
   412
    }
slouken@8582
   413
    if (data->renderer) {
slouken@8582
   414
        SDL_DestroyRenderer(data->renderer);
slouken@8582
   415
    }
slouken@8582
   416
    SDL_free(data->pixels);
slouken@8582
   417
    SDL_free(data);
slouken@8582
   418
}
slouken@8582
   419
slouken@8582
   420
slouken@8582
   421
static int
slouken@8582
   422
cmpmodes(const void *A, const void *B)
slouken@8582
   423
{
slouken@8582
   424
    const SDL_DisplayMode *a = (const SDL_DisplayMode *) A;
slouken@8582
   425
    const SDL_DisplayMode *b = (const SDL_DisplayMode *) B;
slouken@8582
   426
    if (a == b) {
slouken@8582
   427
        return 0;
slouken@8582
   428
    } else if (a->w != b->w) {
slouken@8582
   429
        return b->w - a->w;
slouken@8582
   430
    } else if (a->h != b->h) {
slouken@8582
   431
        return b->h - a->h;
slouken@8582
   432
    } else if (SDL_BITSPERPIXEL(a->format) != SDL_BITSPERPIXEL(b->format)) {
slouken@8582
   433
        return SDL_BITSPERPIXEL(b->format) - SDL_BITSPERPIXEL(a->format);
slouken@8582
   434
    } else if (SDL_PIXELLAYOUT(a->format) != SDL_PIXELLAYOUT(b->format)) {
slouken@8582
   435
        return SDL_PIXELLAYOUT(b->format) - SDL_PIXELLAYOUT(a->format);
slouken@8582
   436
    } else if (a->refresh_rate != b->refresh_rate) {
slouken@8582
   437
        return b->refresh_rate - a->refresh_rate;
slouken@8582
   438
    }
slouken@8582
   439
    return 0;
slouken@8582
   440
}
slouken@8582
   441
slouken@8582
   442
static int
slouken@8582
   443
SDL_UninitializedVideo()
slouken@8582
   444
{
slouken@8582
   445
    return SDL_SetError("Video subsystem has not been initialized");
slouken@8582
   446
}
slouken@8582
   447
slouken@8582
   448
int
slouken@8582
   449
SDL_GetNumVideoDrivers(void)
slouken@8582
   450
{
slouken@8582
   451
    return SDL_arraysize(bootstrap) - 1;
slouken@8582
   452
}
slouken@8582
   453
slouken@8582
   454
const char *
slouken@8582
   455
SDL_GetVideoDriver(int index)
slouken@8582
   456
{
slouken@8582
   457
    if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
slouken@8582
   458
        return bootstrap[index]->name;
slouken@8582
   459
    }
slouken@8582
   460
    return NULL;
slouken@8582
   461
}
slouken@8582
   462
slouken@8582
   463
/*
slouken@8582
   464
 * Initialize the video and event subsystems -- determine native pixel format
slouken@8582
   465
 */
slouken@8582
   466
int
slouken@8582
   467
SDL_VideoInit(const char *driver_name)
slouken@8582
   468
{
slouken@8582
   469
    SDL_VideoDevice *video;
slouken@8582
   470
    int index;
slouken@8582
   471
    int i;
slouken@8582
   472
slouken@8582
   473
    /* Check to make sure we don't overwrite '_this' */
slouken@8582
   474
    if (_this != NULL) {
slouken@8582
   475
        SDL_VideoQuit();
slouken@8582
   476
    }
slouken@8582
   477
slouken@8582
   478
#if !SDL_TIMERS_DISABLED
slouken@8268
   479
    SDL_TicksInit();
slouken@8582
   480
#endif
slouken@8582
   481
slouken@8582
   482
    /* Start the event loop */
slouken@8582
   483
    if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0 ||
slouken@8582
   484
        SDL_KeyboardInit() < 0 ||
slouken@8582
   485
        SDL_MouseInit() < 0 ||
slouken@8582
   486
        SDL_TouchInit() < 0) {
slouken@8582
   487
        return -1;
slouken@8582
   488
    }
slouken@8582
   489
slouken@8582
   490
    /* Select the proper video driver */
slouken@8582
   491
    index = 0;
slouken@8582
   492
    video = NULL;
slouken@8582
   493
    if (driver_name == NULL) {
slouken@8582
   494
        driver_name = SDL_getenv("SDL_VIDEODRIVER");
slouken@8582
   495
    }
slouken@8582
   496
    if (driver_name != NULL) {
slouken@8582
   497
        for (i = 0; bootstrap[i]; ++i) {
slouken@8582
   498
            if (SDL_strncasecmp(bootstrap[i]->name, driver_name, SDL_strlen(driver_name)) == 0) {
gabomdq@8117
   499
                if (bootstrap[i]->available()) {
gabomdq@8117
   500
                    video = bootstrap[i]->create(index);
gabomdq@8117
   501
                    break;
gabomdq@8117
   502
                }
slouken@8582
   503
            }
slouken@8582
   504
        }
slouken@8582
   505
    } else {
slouken@8582
   506
        for (i = 0; bootstrap[i]; ++i) {
slouken@8582
   507
            if (bootstrap[i]->available()) {
slouken@8582
   508
                video = bootstrap[i]->create(index);
slouken@8582
   509
                if (video != NULL) {
slouken@8582
   510
                    break;
slouken@8582
   511
                }
slouken@8582
   512
            }
slouken@8582
   513
        }
slouken@8582
   514
    }
slouken@8582
   515
    if (video == NULL) {
slouken@8582
   516
        if (driver_name) {
slouken@8582
   517
            return SDL_SetError("%s not available", driver_name);
slouken@8582
   518
        }
slouken@8582
   519
        return SDL_SetError("No available video device");
slouken@8582
   520
    }
slouken@8582
   521
    _this = video;
slouken@8582
   522
    _this->name = bootstrap[i]->name;
slouken@8582
   523
    _this->next_object_id = 1;
slouken@8582
   524
slouken@8582
   525
slouken@8582
   526
    /* Set some very sane GL defaults */
slouken@8582
   527
    _this->gl_config.driver_loaded = 0;
slouken@8582
   528
    _this->gl_config.dll_handle = NULL;
jorgen@8145
   529
    SDL_GL_ResetAttributes();
slouken@8582
   530
slouken@8582
   531
    _this->current_glwin_tls = SDL_TLSCreate();
slouken@8582
   532
    _this->current_glctx_tls = SDL_TLSCreate();
slouken@8582
   533
slouken@8582
   534
    /* Initialize the video subsystem */
slouken@8582
   535
    if (_this->VideoInit(_this) < 0) {
slouken@8582
   536
        SDL_VideoQuit();
slouken@8582
   537
        return -1;
slouken@8582
   538
    }
slouken@8582
   539
slouken@8582
   540
    /* Make sure some displays were added */
slouken@8582
   541
    if (_this->num_displays == 0) {
slouken@8582
   542
        SDL_VideoQuit();
slouken@8582
   543
        return SDL_SetError("The video driver did not add any displays");
slouken@8582
   544
    }
slouken@8582
   545
slouken@8582
   546
    /* Add the renderer framebuffer emulation if desired */
slouken@8582
   547
    if (ShouldUseTextureFramebuffer()) {
slouken@8582
   548
        _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
slouken@8582
   549
        _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
slouken@8582
   550
        _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
slouken@8582
   551
    }
slouken@8582
   552
icculus@8265
   553
    /* Disable the screen saver by default. This is a change from <= 2.0.1,
icculus@8265
   554
       but most things using SDL are games or media players; you wouldn't
icculus@8265
   555
       want a screensaver to trigger if you're playing exclusively with a
icculus@8265
   556
       joystick, or passively watching a movie. Things that use SDL but
icculus@8265
   557
       function more like a normal desktop app should explicitly reenable the
icculus@8265
   558
       screensaver. */
slouken@10499
   559
    if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, SDL_FALSE)) {
slouken@8266
   560
        SDL_DisableScreenSaver();
slouken@8266
   561
    }
icculus@8265
   562
slouken@8582
   563
    /* If we don't use a screen keyboard, turn on text input by default,
slouken@8582
   564
       otherwise programs that expect to get text events without enabling
slouken@8582
   565
       UNICODE input won't get any events.
slouken@8582
   566
slouken@8582
   567
       Actually, come to think of it, you needed to call SDL_EnableUNICODE(1)
slouken@8582
   568
       in SDL 1.2 before you got text input events.  Hmm...
slouken@8582
   569
     */
slouken@8582
   570
    if (!SDL_HasScreenKeyboardSupport()) {
slouken@8582
   571
        SDL_StartTextInput();
slouken@8582
   572
    }
slouken@8582
   573
slouken@8582
   574
    /* We're ready to go! */
slouken@8582
   575
    return 0;
slouken@8582
   576
}
slouken@8582
   577
slouken@8582
   578
const char *
slouken@8582
   579
SDL_GetCurrentVideoDriver()
slouken@8582
   580
{
slouken@8582
   581
    if (!_this) {
slouken@8582
   582
        SDL_UninitializedVideo();
slouken@8582
   583
        return NULL;
slouken@8582
   584
    }
slouken@8582
   585
    return _this->name;
slouken@8582
   586
}
slouken@8582
   587
slouken@8582
   588
SDL_VideoDevice *
slouken@8582
   589
SDL_GetVideoDevice(void)
slouken@8582
   590
{
slouken@8582
   591
    return _this;
slouken@8582
   592
}
slouken@8582
   593
slouken@8582
   594
int
slouken@8582
   595
SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
slouken@8582
   596
{
slouken@8582
   597
    SDL_VideoDisplay display;
slouken@8582
   598
slouken@8582
   599
    SDL_zero(display);
slouken@8582
   600
    if (desktop_mode) {
slouken@8582
   601
        display.desktop_mode = *desktop_mode;
slouken@8582
   602
    }
slouken@8582
   603
    display.current_mode = display.desktop_mode;
slouken@8582
   604
slouken@8582
   605
    return SDL_AddVideoDisplay(&display);
slouken@8582
   606
}
slouken@8582
   607
slouken@8582
   608
int
slouken@8582
   609
SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
slouken@8582
   610
{
slouken@8582
   611
    SDL_VideoDisplay *displays;
slouken@8582
   612
    int index = -1;
slouken@8582
   613
slouken@8582
   614
    displays =
slouken@8582
   615
        SDL_realloc(_this->displays,
slouken@8582
   616
                    (_this->num_displays + 1) * sizeof(*displays));
slouken@8582
   617
    if (displays) {
slouken@8582
   618
        index = _this->num_displays++;
slouken@8582
   619
        displays[index] = *display;
slouken@8582
   620
        displays[index].device = _this;
slouken@8582
   621
        _this->displays = displays;
slouken@8582
   622
slouken@8582
   623
        if (display->name) {
slouken@8582
   624
            displays[index].name = SDL_strdup(display->name);
slouken@8582
   625
        } else {
slouken@8582
   626
            char name[32];
slouken@8582
   627
slouken@8582
   628
            SDL_itoa(index, name, 10);
slouken@8582
   629
            displays[index].name = SDL_strdup(name);
slouken@8582
   630
        }
slouken@8582
   631
    } else {
slouken@8582
   632
        SDL_OutOfMemory();
slouken@8582
   633
    }
slouken@8582
   634
    return index;
slouken@8582
   635
}
slouken@8582
   636
slouken@8582
   637
int
slouken@8582
   638
SDL_GetNumVideoDisplays(void)
slouken@8582
   639
{
slouken@8582
   640
    if (!_this) {
slouken@8582
   641
        SDL_UninitializedVideo();
slouken@8582
   642
        return 0;
slouken@8582
   643
    }
slouken@8582
   644
    return _this->num_displays;
slouken@8582
   645
}
slouken@8582
   646
slouken@8582
   647
static int
slouken@8582
   648
SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
slouken@8582
   649
{
slouken@8582
   650
    int displayIndex;
slouken@8582
   651
slouken@8582
   652
    for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
slouken@8582
   653
        if (display == &_this->displays[displayIndex]) {
slouken@8582
   654
            return displayIndex;
slouken@8582
   655
        }
slouken@8582
   656
    }
slouken@8582
   657
slouken@8582
   658
    /* Couldn't find the display, just use index 0 */
slouken@8582
   659
    return 0;
slouken@8582
   660
}
slouken@8582
   661
slouken@8582
   662
void *
slouken@8818
   663
SDL_GetDisplayDriverData(int displayIndex)
slouken@8582
   664
{
slouken@8818
   665
    CHECK_DISPLAY_INDEX(displayIndex, NULL);
slouken@8582
   666
slouken@8582
   667
    return _this->displays[displayIndex].driverdata;
slouken@8582
   668
}
slouken@8582
   669
slouken@8582
   670
const char *
slouken@8582
   671
SDL_GetDisplayName(int displayIndex)
slouken@8582
   672
{
slouken@8582
   673
    CHECK_DISPLAY_INDEX(displayIndex, NULL);
slouken@8582
   674
slouken@8582
   675
    return _this->displays[displayIndex].name;
slouken@8582
   676
}
slouken@8582
   677
slouken@8582
   678
int
slouken@8582
   679
SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
slouken@8582
   680
{
slouken@8582
   681
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@8582
   682
slouken@8582
   683
    if (rect) {
slouken@8582
   684
        SDL_VideoDisplay *display = &_this->displays[displayIndex];
slouken@8582
   685
slouken@8582
   686
        if (_this->GetDisplayBounds) {
slouken@8582
   687
            if (_this->GetDisplayBounds(_this, display, rect) == 0) {
slouken@8582
   688
                return 0;
slouken@8582
   689
            }
slouken@8582
   690
        }
slouken@8582
   691
slouken@8582
   692
        /* Assume that the displays are left to right */
slouken@8582
   693
        if (displayIndex == 0) {
slouken@8582
   694
            rect->x = 0;
slouken@8582
   695
            rect->y = 0;
slouken@8582
   696
        } else {
slouken@8582
   697
            SDL_GetDisplayBounds(displayIndex-1, rect);
slouken@8582
   698
            rect->x += rect->w;
slouken@8582
   699
        }
slouken@8582
   700
        rect->w = display->current_mode.w;
slouken@8582
   701
        rect->h = display->current_mode.h;
slouken@8582
   702
    }
icculus@10019
   703
    return 0;  /* !!! FIXME: should this be an error if (rect==NULL) ? */
icculus@10019
   704
}
icculus@10019
   705
icculus@10019
   706
int SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect)
icculus@10019
   707
{
icculus@10019
   708
    CHECK_DISPLAY_INDEX(displayIndex, -1);
icculus@10019
   709
icculus@10019
   710
    if (rect) {
icculus@10019
   711
        SDL_VideoDisplay *display = &_this->displays[displayIndex];
icculus@10019
   712
icculus@10019
   713
        if (_this->GetDisplayUsableBounds) {
icculus@10019
   714
            if (_this->GetDisplayUsableBounds(_this, display, rect) == 0) {
icculus@10019
   715
                return 0;
icculus@10019
   716
            }
icculus@10019
   717
        }
icculus@10019
   718
icculus@10019
   719
        /* Oh well, just give the entire display bounds. */
icculus@10019
   720
        return SDL_GetDisplayBounds(displayIndex, rect);
icculus@10019
   721
    }
icculus@10019
   722
    return 0;  /* !!! FIXME: should this be an error if (rect==NULL) ? */
slouken@8582
   723
}
slouken@8582
   724
alfred@9813
   725
int
alfred@9813
   726
SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi)
alfred@9813
   727
{
alfred@9813
   728
	SDL_VideoDisplay *display;
alfred@9813
   729
alfred@9813
   730
    CHECK_DISPLAY_INDEX(displayIndex, -1);
alfred@9813
   731
alfred@9813
   732
    display = &_this->displays[displayIndex];
alfred@9813
   733
alfred@9813
   734
	if (_this->GetDisplayDPI) {
alfred@9813
   735
		if (_this->GetDisplayDPI(_this, display, ddpi, hdpi, vdpi) == 0) {
alfred@9813
   736
			return 0;
alfred@9813
   737
		}
philipp@10166
   738
    } else {
philipp@10166
   739
        return SDL_Unsupported();
philipp@10166
   740
    }
alfred@9813
   741
alfred@9813
   742
	return -1;
alfred@9813
   743
}
alfred@9813
   744
slouken@8582
   745
SDL_bool
slouken@8582
   746
SDL_AddDisplayMode(SDL_VideoDisplay * display,  const SDL_DisplayMode * mode)
slouken@8582
   747
{
slouken@8582
   748
    SDL_DisplayMode *modes;
slouken@8582
   749
    int i, nmodes;
slouken@8582
   750
slouken@8582
   751
    /* Make sure we don't already have the mode in the list */
slouken@8582
   752
    modes = display->display_modes;
slouken@8582
   753
    nmodes = display->num_display_modes;
slouken@8582
   754
    for (i = 0; i < nmodes; ++i) {
slouken@8582
   755
        if (cmpmodes(mode, &modes[i]) == 0) {
slouken@8582
   756
            return SDL_FALSE;
slouken@8582
   757
        }
slouken@8582
   758
    }
slouken@8582
   759
slouken@8582
   760
    /* Go ahead and add the new mode */
slouken@8582
   761
    if (nmodes == display->max_display_modes) {
slouken@8582
   762
        modes =
slouken@8582
   763
            SDL_realloc(modes,
slouken@8582
   764
                        (display->max_display_modes + 32) * sizeof(*modes));
slouken@8582
   765
        if (!modes) {
slouken@8582
   766
            return SDL_FALSE;
slouken@8582
   767
        }
slouken@8582
   768
        display->display_modes = modes;
slouken@8582
   769
        display->max_display_modes += 32;
slouken@8582
   770
    }
slouken@8582
   771
    modes[nmodes] = *mode;
slouken@8582
   772
    display->num_display_modes++;
slouken@8582
   773
slouken@8582
   774
    /* Re-sort video modes */
slouken@8582
   775
    SDL_qsort(display->display_modes, display->num_display_modes,
slouken@8582
   776
              sizeof(SDL_DisplayMode), cmpmodes);
slouken@8582
   777
slouken@8582
   778
    return SDL_TRUE;
slouken@8582
   779
}
slouken@8582
   780
slouken@8582
   781
static int
slouken@8582
   782
SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
slouken@8582
   783
{
slouken@8582
   784
    if (!display->num_display_modes && _this->GetDisplayModes) {
slouken@8582
   785
        _this->GetDisplayModes(_this, display);
slouken@8582
   786
        SDL_qsort(display->display_modes, display->num_display_modes,
slouken@8582
   787
                  sizeof(SDL_DisplayMode), cmpmodes);
slouken@8582
   788
    }
slouken@8582
   789
    return display->num_display_modes;
slouken@8582
   790
}
slouken@8582
   791
slouken@8582
   792
int
slouken@8582
   793
SDL_GetNumDisplayModes(int displayIndex)
slouken@8582
   794
{
slouken@8582
   795
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@8582
   796
slouken@8582
   797
    return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
slouken@8582
   798
}
slouken@8582
   799
slouken@8582
   800
int
slouken@8582
   801
SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
slouken@8582
   802
{
slouken@8582
   803
    SDL_VideoDisplay *display;
slouken@8582
   804
slouken@8582
   805
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@8582
   806
slouken@8582
   807
    display = &_this->displays[displayIndex];
slouken@8582
   808
    if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
slouken@8582
   809
        return SDL_SetError("index must be in the range of 0 - %d",
slouken@8582
   810
                            SDL_GetNumDisplayModesForDisplay(display) - 1);
slouken@8582
   811
    }
slouken@8582
   812
    if (mode) {
slouken@8582
   813
        *mode = display->display_modes[index];
slouken@8582
   814
    }
slouken@8582
   815
    return 0;
slouken@8582
   816
}
slouken@8582
   817
slouken@8582
   818
int
slouken@8582
   819
SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
slouken@8582
   820
{
slouken@8582
   821
    SDL_VideoDisplay *display;
slouken@8582
   822
slouken@8582
   823
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@8582
   824
slouken@8582
   825
    display = &_this->displays[displayIndex];
slouken@8582
   826
    if (mode) {
slouken@8582
   827
        *mode = display->desktop_mode;
slouken@8582
   828
    }
slouken@8582
   829
    return 0;
slouken@8582
   830
}
slouken@8582
   831
slouken@8582
   832
int
slouken@8582
   833
SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
slouken@8582
   834
{
slouken@8582
   835
    SDL_VideoDisplay *display;
slouken@8582
   836
slouken@8582
   837
    CHECK_DISPLAY_INDEX(displayIndex, -1);
slouken@8582
   838
slouken@8582
   839
    display = &_this->displays[displayIndex];
slouken@8582
   840
    if (mode) {
slouken@8582
   841
        *mode = display->current_mode;
slouken@8582
   842
    }
slouken@8582
   843
    return 0;
slouken@8582
   844
}
slouken@8582
   845
slouken@8582
   846
static SDL_DisplayMode *
slouken@8582
   847
SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
slouken@8582
   848
                                    const SDL_DisplayMode * mode,
slouken@8582
   849
                                    SDL_DisplayMode * closest)
slouken@8582
   850
{
slouken@8582
   851
    Uint32 target_format;
slouken@8582
   852
    int target_refresh_rate;
slouken@8582
   853
    int i;
slouken@8582
   854
    SDL_DisplayMode *current, *match;
slouken@8582
   855
slouken@8582
   856
    if (!mode || !closest) {
slouken@8582
   857
        SDL_SetError("Missing desired mode or closest mode parameter");
slouken@8582
   858
        return NULL;
slouken@8582
   859
    }
slouken@8582
   860
slouken@8582
   861
    /* Default to the desktop format */
slouken@8582
   862
    if (mode->format) {
slouken@8582
   863
        target_format = mode->format;
slouken@8582
   864
    } else {
slouken@8582
   865
        target_format = display->desktop_mode.format;
slouken@8582
   866
    }
slouken@8582
   867
slouken@8582
   868
    /* Default to the desktop refresh rate */
slouken@8582
   869
    if (mode->refresh_rate) {
slouken@8582
   870
        target_refresh_rate = mode->refresh_rate;
slouken@8582
   871
    } else {
slouken@8582
   872
        target_refresh_rate = display->desktop_mode.refresh_rate;
slouken@8582
   873
    }
slouken@8582
   874
slouken@8582
   875
    match = NULL;
slouken@8582
   876
    for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
slouken@8582
   877
        current = &display->display_modes[i];
slouken@8582
   878
slouken@8582
   879
        if (current->w && (current->w < mode->w)) {
slouken@8582
   880
            /* Out of sorted modes large enough here */
slouken@8582
   881
            break;
slouken@8582
   882
        }
slouken@8582
   883
        if (current->h && (current->h < mode->h)) {
slouken@8582
   884
            if (current->w && (current->w == mode->w)) {
slouken@8582
   885
                /* Out of sorted modes large enough here */
slouken@8582
   886
                break;
slouken@8582
   887
            }
slouken@8582
   888
            /* Wider, but not tall enough, due to a different
slouken@8582
   889
               aspect ratio. This mode must be skipped, but closer
slouken@8582
   890
               modes may still follow. */
slouken@8582
   891
            continue;
slouken@8582
   892
        }
slouken@8582
   893
        if (!match || current->w < match->w || current->h < match->h) {
slouken@8582
   894
            match = current;
slouken@8582
   895
            continue;
slouken@8582
   896
        }
slouken@8582
   897
        if (current->format != match->format) {
slouken@8582
   898
            /* Sorted highest depth to lowest */
slouken@8582
   899
            if (current->format == target_format ||
slouken@8582
   900
                (SDL_BITSPERPIXEL(current->format) >=
slouken@8582
   901
                 SDL_BITSPERPIXEL(target_format)
slouken@8582
   902
                 && SDL_PIXELTYPE(current->format) ==
slouken@8582
   903
                 SDL_PIXELTYPE(target_format))) {
slouken@8582
   904
                match = current;
slouken@8582
   905
            }
slouken@8582
   906
            continue;
slouken@8582
   907
        }
slouken@8582
   908
        if (current->refresh_rate != match->refresh_rate) {
slouken@8582
   909
            /* Sorted highest refresh to lowest */
slouken@8582
   910
            if (current->refresh_rate >= target_refresh_rate) {
slouken@8582
   911
                match = current;
slouken@8582
   912
            }
slouken@8582
   913
        }
slouken@8582
   914
    }
slouken@8582
   915
    if (match) {
slouken@8582
   916
        if (match->format) {
slouken@8582
   917
            closest->format = match->format;
slouken@8582
   918
        } else {
slouken@8582
   919
            closest->format = mode->format;
slouken@8582
   920
        }
slouken@8582
   921
        if (match->w && match->h) {
slouken@8582
   922
            closest->w = match->w;
slouken@8582
   923
            closest->h = match->h;
slouken@8582
   924
        } else {
slouken@8582
   925
            closest->w = mode->w;
slouken@8582
   926
            closest->h = mode->h;
slouken@8582
   927
        }
slouken@8582
   928
        if (match->refresh_rate) {
slouken@8582
   929
            closest->refresh_rate = match->refresh_rate;
slouken@8582
   930
        } else {
slouken@8582
   931
            closest->refresh_rate = mode->refresh_rate;
slouken@8582
   932
        }
slouken@8582
   933
        closest->driverdata = match->driverdata;
slouken@8582
   934
slouken@8582
   935
        /*
slouken@8582
   936
         * Pick some reasonable defaults if the app and driver don't
slouken@8582
   937
         * care
slouken@8582
   938
         */
slouken@8582
   939
        if (!closest->format) {
slouken@8582
   940
            closest->format = SDL_PIXELFORMAT_RGB888;
slouken@8582
   941
        }
slouken@8582
   942
        if (!closest->w) {
slouken@8582
   943
            closest->w = 640;
slouken@8582
   944
        }
slouken@8582
   945
        if (!closest->h) {
slouken@8582
   946
            closest->h = 480;
slouken@8582
   947
        }
slouken@8582
   948
        return closest;
slouken@8582
   949
    }
slouken@8582
   950
    return NULL;
slouken@8582
   951
}
slouken@8582
   952
slouken@8582
   953
SDL_DisplayMode *
slouken@8582
   954
SDL_GetClosestDisplayMode(int displayIndex,
slouken@8582
   955
                          const SDL_DisplayMode * mode,
slouken@8582
   956
                          SDL_DisplayMode * closest)
slouken@8582
   957
{
slouken@8582
   958
    SDL_VideoDisplay *display;
slouken@8582
   959
slouken@8582
   960
    CHECK_DISPLAY_INDEX(displayIndex, NULL);
slouken@8582
   961
slouken@8582
   962
    display = &_this->displays[displayIndex];
slouken@8582
   963
    return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
slouken@8582
   964
}
slouken@8582
   965
slouken@8582
   966
static int
slouken@8582
   967
SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
slouken@8582
   968
{
slouken@8582
   969
    SDL_DisplayMode display_mode;
slouken@8582
   970
    SDL_DisplayMode current_mode;
slouken@8582
   971
slouken@8582
   972
    if (mode) {
slouken@8582
   973
        display_mode = *mode;
slouken@8582
   974
slouken@8582
   975
        /* Default to the current mode */
slouken@8582
   976
        if (!display_mode.format) {
slouken@8582
   977
            display_mode.format = display->current_mode.format;
slouken@8582
   978
        }
slouken@8582
   979
        if (!display_mode.w) {
slouken@8582
   980
            display_mode.w = display->current_mode.w;
slouken@8582
   981
        }
slouken@8582
   982
        if (!display_mode.h) {
slouken@8582
   983
            display_mode.h = display->current_mode.h;
slouken@8582
   984
        }
slouken@8582
   985
        if (!display_mode.refresh_rate) {
slouken@8582
   986
            display_mode.refresh_rate = display->current_mode.refresh_rate;
slouken@8582
   987
        }
slouken@8582
   988
slouken@8582
   989
        /* Get a good video mode, the closest one possible */
slouken@8582
   990
        if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
slouken@8582
   991
            return SDL_SetError("No video mode large enough for %dx%d",
slouken@8582
   992
                                display_mode.w, display_mode.h);
slouken@8582
   993
        }
slouken@8582
   994
    } else {
slouken@8582
   995
        display_mode = display->desktop_mode;
slouken@8582
   996
    }
slouken@8582
   997
slouken@8582
   998
    /* See if there's anything left to do */
slouken@8582
   999
    current_mode = display->current_mode;
slouken@8582
  1000
    if (SDL_memcmp(&display_mode, &current_mode, sizeof(display_mode)) == 0) {
slouken@8582
  1001
        return 0;
slouken@8582
  1002
    }
slouken@8582
  1003
slouken@8582
  1004
    /* Actually change the display mode */
slouken@8582
  1005
    if (!_this->SetDisplayMode) {
slouken@8582
  1006
        return SDL_SetError("Video driver doesn't support changing display mode");
slouken@8582
  1007
    }
slouken@8582
  1008
    if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
slouken@8582
  1009
        return -1;
slouken@8582
  1010
    }
slouken@8582
  1011
    display->current_mode = display_mode;
slouken@8582
  1012
    return 0;
slouken@8582
  1013
}
slouken@8582
  1014
slouken@8582
  1015
int
slouken@8582
  1016
SDL_GetWindowDisplayIndex(SDL_Window * window)
slouken@8582
  1017
{
slouken@8582
  1018
    int displayIndex;
slouken@8582
  1019
    int i, dist;
slouken@8582
  1020
    int closest = -1;
slouken@8582
  1021
    int closest_dist = 0x7FFFFFFF;
slouken@8582
  1022
    SDL_Point center;
slouken@8582
  1023
    SDL_Point delta;
slouken@8582
  1024
    SDL_Rect rect;
slouken@8582
  1025
slouken@8582
  1026
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8582
  1027
slouken@8582
  1028
    if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
slouken@8582
  1029
        SDL_WINDOWPOS_ISCENTERED(window->x)) {
slouken@8582
  1030
        displayIndex = (window->x & 0xFFFF);
slouken@8582
  1031
        if (displayIndex >= _this->num_displays) {
slouken@8582
  1032
            displayIndex = 0;
slouken@8582
  1033
        }
slouken@8582
  1034
        return displayIndex;
slouken@8582
  1035
    }
slouken@8582
  1036
    if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
slouken@8582
  1037
        SDL_WINDOWPOS_ISCENTERED(window->y)) {
slouken@8582
  1038
        displayIndex = (window->y & 0xFFFF);
slouken@8582
  1039
        if (displayIndex >= _this->num_displays) {
slouken@8582
  1040
            displayIndex = 0;
slouken@8582
  1041
        }
slouken@8582
  1042
        return displayIndex;
slouken@8582
  1043
    }
slouken@8582
  1044
slouken@8582
  1045
    /* Find the display containing the window */
slouken@8582
  1046
    for (i = 0; i < _this->num_displays; ++i) {
slouken@8582
  1047
        SDL_VideoDisplay *display = &_this->displays[i];
slouken@8582
  1048
slouken@8582
  1049
        if (display->fullscreen_window == window) {
slouken@8582
  1050
            return i;
slouken@8582
  1051
        }
slouken@8582
  1052
    }
slouken@8582
  1053
    center.x = window->x + window->w / 2;
slouken@8582
  1054
    center.y = window->y + window->h / 2;
slouken@8582
  1055
    for (i = 0; i < _this->num_displays; ++i) {
slouken@8582
  1056
        SDL_GetDisplayBounds(i, &rect);
slouken@8582
  1057
        if (SDL_EnclosePoints(&center, 1, &rect, NULL)) {
slouken@8582
  1058
            return i;
slouken@8582
  1059
        }
slouken@8582
  1060
slouken@8582
  1061
        delta.x = center.x - (rect.x + rect.w / 2);
slouken@8582
  1062
        delta.y = center.y - (rect.y + rect.h / 2);
slouken@8582
  1063
        dist = (delta.x*delta.x + delta.y*delta.y);
slouken@8582
  1064
        if (dist < closest_dist) {
slouken@8582
  1065
            closest = i;
slouken@8582
  1066
            closest_dist = dist;
slouken@8582
  1067
        }
slouken@8582
  1068
    }
slouken@8582
  1069
    if (closest < 0) {
slouken@8582
  1070
        SDL_SetError("Couldn't find any displays");
slouken@8582
  1071
    }
slouken@8582
  1072
    return closest;
slouken@8582
  1073
}
slouken@8582
  1074
slouken@8582
  1075
SDL_VideoDisplay *
slouken@8582
  1076
SDL_GetDisplayForWindow(SDL_Window *window)
slouken@8582
  1077
{
slouken@8582
  1078
    int displayIndex = SDL_GetWindowDisplayIndex(window);
slouken@8582
  1079
    if (displayIndex >= 0) {
slouken@8582
  1080
        return &_this->displays[displayIndex];
slouken@8582
  1081
    } else {
slouken@8582
  1082
        return NULL;
slouken@8582
  1083
    }
slouken@8582
  1084
}
slouken@8582
  1085
slouken@8582
  1086
int
slouken@8582
  1087
SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
slouken@8582
  1088
{
slouken@8582
  1089
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8582
  1090
slouken@8582
  1091
    if (mode) {
slouken@8582
  1092
        window->fullscreen_mode = *mode;
slouken@8582
  1093
    } else {
slouken@8582
  1094
        SDL_zero(window->fullscreen_mode);
slouken@8582
  1095
    }
slouken@8818
  1096
slouken@8818
  1097
    if (FULLSCREEN_VISIBLE(window) && (window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
slouken@8818
  1098
        SDL_DisplayMode fullscreen_mode;
slouken@8818
  1099
        if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) {
slouken@8818
  1100
            SDL_SetDisplayModeForDisplay(SDL_GetDisplayForWindow(window), &fullscreen_mode);
slouken@8818
  1101
        }
slouken@8818
  1102
    }
slouken@8582
  1103
    return 0;
slouken@8582
  1104
}
slouken@8582
  1105
slouken@8582
  1106
int
slouken@8582
  1107
SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
slouken@8582
  1108
{
slouken@8582
  1109
    SDL_DisplayMode fullscreen_mode;
slouken@8582
  1110
    SDL_VideoDisplay *display;
slouken@8582
  1111
slouken@8818
  1112
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8818
  1113
slouken@8582
  1114
    if (!mode) {
slouken@8818
  1115
        return SDL_InvalidParamError("mode");
slouken@8582
  1116
    }
slouken@8582
  1117
slouken@8582
  1118
    fullscreen_mode = window->fullscreen_mode;
slouken@8582
  1119
    if (!fullscreen_mode.w) {
slouken@8823
  1120
        fullscreen_mode.w = window->windowed.w;
slouken@8582
  1121
    }
slouken@8582
  1122
    if (!fullscreen_mode.h) {
slouken@8823
  1123
        fullscreen_mode.h = window->windowed.h;
slouken@8582
  1124
    }
slouken@8582
  1125
slouken@8582
  1126
    display = SDL_GetDisplayForWindow(window);
slouken@8582
  1127
slouken@8582
  1128
    /* if in desktop size mode, just return the size of the desktop */
slouken@8818
  1129
    if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
slouken@8582
  1130
        fullscreen_mode = display->desktop_mode;
slouken@8818
  1131
    } else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
slouken@8582
  1132
                                             &fullscreen_mode,
slouken@8582
  1133
                                             &fullscreen_mode)) {
slouken@8582
  1134
        return SDL_SetError("Couldn't find display mode match");
slouken@8582
  1135
    }
slouken@8582
  1136
slouken@8582
  1137
    if (mode) {
slouken@8582
  1138
        *mode = fullscreen_mode;
slouken@8582
  1139
    }
slouken@8582
  1140
    return 0;
slouken@8582
  1141
}
slouken@8582
  1142
slouken@8582
  1143
Uint32
slouken@8582
  1144
SDL_GetWindowPixelFormat(SDL_Window * window)
slouken@8582
  1145
{
slouken@8582
  1146
    SDL_VideoDisplay *display;
slouken@8582
  1147
slouken@8582
  1148
    CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
slouken@8582
  1149
slouken@8582
  1150
    display = SDL_GetDisplayForWindow(window);
slouken@8582
  1151
    return display->current_mode.format;
slouken@8582
  1152
}
slouken@8582
  1153
slouken@8582
  1154
static void
slouken@8582
  1155
SDL_RestoreMousePosition(SDL_Window *window)
slouken@8582
  1156
{
slouken@8582
  1157
    int x, y;
slouken@8582
  1158
slouken@8582
  1159
    if (window == SDL_GetMouseFocus()) {
slouken@8582
  1160
        SDL_GetMouseState(&x, &y);
slouken@8582
  1161
        SDL_WarpMouseInWindow(window, x, y);
slouken@8582
  1162
    }
slouken@8582
  1163
}
slouken@8582
  1164
dludwig@9924
  1165
#if __WINRT__
dludwig@9924
  1166
extern Uint32 WINRT_DetectWindowFlags(SDL_Window * window);
dludwig@9924
  1167
#endif
dludwig@9924
  1168
slime73@9532
  1169
static int
slouken@8582
  1170
SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
slouken@8582
  1171
{
slouken@8582
  1172
    SDL_VideoDisplay *display;
slouken@8582
  1173
    SDL_Window *other;
slouken@8582
  1174
slime73@9532
  1175
    CHECK_WINDOW_MAGIC(window,-1);
icculus@8783
  1176
alfred@9037
  1177
    /* if we are in the process of hiding don't go back to fullscreen */
slouken@10698
  1178
    if (window->is_hiding && fullscreen) {
slime73@9532
  1179
        return 0;
slouken@10698
  1180
    }
icculus@9887
  1181
slouken@8582
  1182
#ifdef __MACOSX__
slouken@9906
  1183
    /* if the window is going away and no resolution change is necessary,
slouken@10698
  1184
       do nothing, or else we may trigger an ugly double-transition
slouken@9906
  1185
     */
icculus@10781
  1186
    if (SDL_strcmp(_this->name, "cocoa") == 0) {  /* don't do this for X11, etc */
icculus@10781
  1187
        if (window->is_destroying && (window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP)
icculus@10781
  1188
            return 0;
slouken@9906
  1189
    
icculus@10781
  1190
        if (!_this->is_dummy) {
icculus@10781
  1191
            /* If we're switching between a fullscreen Space and "normal" fullscreen, we need to get back to normal first. */
icculus@10781
  1192
            if (fullscreen && ((window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP) && ((window->flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN)) {
icculus@10781
  1193
                if (!Cocoa_SetWindowFullscreenSpace(window, SDL_FALSE)) {
icculus@10781
  1194
                    return -1;
icculus@10781
  1195
                }
icculus@10781
  1196
            } else if (fullscreen && ((window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN) && ((window->flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP)) {
icculus@10781
  1197
                display = SDL_GetDisplayForWindow(window);
icculus@10781
  1198
                SDL_SetDisplayModeForDisplay(display, NULL);
icculus@10781
  1199
                if (_this->SetWindowFullscreen) {
icculus@10781
  1200
                    _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
icculus@10781
  1201
                }
slouken@10698
  1202
            }
icculus@10781
  1203
icculus@10781
  1204
            if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
icculus@10781
  1205
                if (Cocoa_IsWindowInFullscreenSpace(window) != fullscreen) {
icculus@10781
  1206
                    return -1;
icculus@10781
  1207
                }
icculus@10781
  1208
                window->last_fullscreen_flags = window->flags;
icculus@10781
  1209
                return 0;
slouken@10698
  1210
            }
slouken@9904
  1211
        }
icculus@9887
  1212
    }
dludwig@9931
  1213
#elif __WINRT__ && (NTDDI_VERSION < NTDDI_WIN10)
dludwig@9924
  1214
    /* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
dludwig@9924
  1215
       or not.  The user can choose this, via OS-provided UI, but this can't
dludwig@9924
  1216
       be set programmatically.
dludwig@9924
  1217
dludwig@9924
  1218
       Just look at what SDL's WinRT video backend code detected with regards
dludwig@9924
  1219
       to fullscreen (being active, or not), and figure out a return/error code
dludwig@9924
  1220
       from that.
dludwig@9924
  1221
    */
dludwig@9924
  1222
    if (fullscreen == !(WINRT_DetectWindowFlags(window) & FULLSCREEN_MASK)) {
dludwig@9924
  1223
        /* Uh oh, either:
dludwig@9924
  1224
            1. fullscreen was requested, and we're already windowed
dludwig@9924
  1225
            2. windowed-mode was requested, and we're already fullscreen
dludwig@9924
  1226
dludwig@9924
  1227
            WinRT 8.x can't resolve either programmatically, so we're
dludwig@9924
  1228
            giving up.
dludwig@9924
  1229
        */
dludwig@9924
  1230
        return -1;
dludwig@9924
  1231
    } else {
dludwig@9924
  1232
        /* Whatever was requested, fullscreen or windowed mode, is already
dludwig@9924
  1233
            in-place.
dludwig@9924
  1234
        */
dludwig@9924
  1235
        return 0;
dludwig@9924
  1236
    }
slouken@8582
  1237
#endif
slouken@8582
  1238
slouken@8582
  1239
    display = SDL_GetDisplayForWindow(window);
slouken@8582
  1240
slouken@8582
  1241
    if (fullscreen) {
slouken@8582
  1242
        /* Hide any other fullscreen windows */
slouken@8582
  1243
        if (display->fullscreen_window &&
slouken@8582
  1244
            display->fullscreen_window != window) {
slouken@8582
  1245
            SDL_MinimizeWindow(display->fullscreen_window);
slouken@8582
  1246
        }
slouken@8582
  1247
    }
slouken@8582
  1248
slouken@8582
  1249
    /* See if anything needs to be done now */
slouken@8582
  1250
    if ((display->fullscreen_window == window) == fullscreen) {
jorgen@8110
  1251
        if ((window->last_fullscreen_flags & FULLSCREEN_MASK) == (window->flags & FULLSCREEN_MASK)) {
slime73@9532
  1252
            return 0;
jorgen@8110
  1253
        }
slouken@8582
  1254
    }
slouken@8582
  1255
slouken@8582
  1256
    /* See if there are any fullscreen windows */
slouken@8582
  1257
    for (other = _this->windows; other; other = other->next) {
slouken@8582
  1258
        SDL_bool setDisplayMode = SDL_FALSE;
slouken@8582
  1259
slouken@8582
  1260
        if (other == window) {
slouken@8582
  1261
            setDisplayMode = fullscreen;
slouken@8582
  1262
        } else if (FULLSCREEN_VISIBLE(other) &&
slouken@8582
  1263
                   SDL_GetDisplayForWindow(other) == display) {
slouken@8582
  1264
            setDisplayMode = SDL_TRUE;
slouken@8582
  1265
        }
slouken@8582
  1266
slouken@8582
  1267
        if (setDisplayMode) {
slouken@8582
  1268
            SDL_DisplayMode fullscreen_mode;
slouken@8582
  1269
icculus@8656
  1270
            SDL_zero(fullscreen_mode);
icculus@8656
  1271
slouken@8582
  1272
            if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
slouken@8582
  1273
                SDL_bool resized = SDL_TRUE;
slouken@8582
  1274
slouken@8582
  1275
                if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
slouken@8582
  1276
                    resized = SDL_FALSE;
slouken@8582
  1277
                }
slouken@8582
  1278
slouken@8582
  1279
                /* only do the mode change if we want exclusive fullscreen */
slouken@8582
  1280
                if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
slime73@9532
  1281
                    if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
slime73@9532
  1282
                        return -1;
slime73@9532
  1283
                    }
slouken@8582
  1284
                } else {
slime73@9532
  1285
                    if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
slime73@9532
  1286
                        return -1;
slime73@9532
  1287
                    }
slouken@8582
  1288
                }
slouken@8582
  1289
slouken@8582
  1290
                if (_this->SetWindowFullscreen) {
slouken@8582
  1291
                    _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
slouken@8582
  1292
                }
slouken@8582
  1293
                display->fullscreen_window = other;
slouken@8582
  1294
slouken@8582
  1295
                /* Generate a mode change event here */
slouken@8582
  1296
                if (resized) {
slouken@8582
  1297
                    SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
slouken@8582
  1298
                                        fullscreen_mode.w, fullscreen_mode.h);
slouken@8582
  1299
                } else {
slouken@8582
  1300
                    SDL_OnWindowResized(other);
slouken@8582
  1301
                }
slouken@8582
  1302
slouken@8582
  1303
                SDL_RestoreMousePosition(other);
jorgen@8110
  1304
jorgen@8110
  1305
                window->last_fullscreen_flags = window->flags;
slime73@9532
  1306
                return 0;
slouken@8582
  1307
            }
slouken@8582
  1308
        }
slouken@8582
  1309
    }
slouken@8582
  1310
slouken@8582
  1311
    /* Nope, restore the desktop mode */
slouken@8582
  1312
    SDL_SetDisplayModeForDisplay(display, NULL);
slouken@8582
  1313
slouken@8582
  1314
    if (_this->SetWindowFullscreen) {
slouken@8582
  1315
        _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
slouken@8582
  1316
    }
slouken@8582
  1317
    display->fullscreen_window = NULL;
slouken@8582
  1318
slouken@8582
  1319
    /* Generate a mode change event here */
slouken@8582
  1320
    SDL_OnWindowResized(window);
slouken@8582
  1321
slouken@8582
  1322
    /* Restore the cursor position */
slouken@8582
  1323
    SDL_RestoreMousePosition(window);
jorgen@8110
  1324
jorgen@8110
  1325
    window->last_fullscreen_flags = window->flags;
slime73@9532
  1326
    return 0;
slouken@8582
  1327
}
slouken@8582
  1328
slouken@8582
  1329
#define CREATE_FLAGS \
slouken@11006
  1330
    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN )
slouken@8582
  1331
slouken@8582
  1332
static void
slouken@8582
  1333
SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
slouken@8582
  1334
{
slouken@8582
  1335
    if (flags & SDL_WINDOW_MAXIMIZED) {
slouken@8582
  1336
        SDL_MaximizeWindow(window);
slouken@8582
  1337
    }
slouken@8582
  1338
    if (flags & SDL_WINDOW_MINIMIZED) {
slouken@8582
  1339
        SDL_MinimizeWindow(window);
slouken@8582
  1340
    }
slouken@8582
  1341
    if (flags & SDL_WINDOW_FULLSCREEN) {
slouken@8582
  1342
        SDL_SetWindowFullscreen(window, flags);
slouken@8582
  1343
    }
slouken@8582
  1344
    if (flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@8582
  1345
        SDL_SetWindowGrab(window, SDL_TRUE);
slouken@8582
  1346
    }
slouken@8582
  1347
    if (!(flags & SDL_WINDOW_HIDDEN)) {
slouken@8582
  1348
        SDL_ShowWindow(window);
slouken@8582
  1349
    }
slouken@8582
  1350
}
slouken@8582
  1351
slouken@8582
  1352
SDL_Window *
slouken@8582
  1353
SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
slouken@8582
  1354
{
slouken@8582
  1355
    SDL_Window *window;
slouken@8582
  1356
slouken@8582
  1357
    if (!_this) {
slouken@8582
  1358
        /* Initialize the video system if needed */
slouken@8582
  1359
        if (SDL_VideoInit(NULL) < 0) {
slouken@8582
  1360
            return NULL;
slouken@8582
  1361
        }
slouken@8582
  1362
    }
slouken@8582
  1363
slouken@10698
  1364
    if ((((flags & SDL_WINDOW_UTILITY) != 0) + ((flags & SDL_WINDOW_TOOLTIP) != 0) + ((flags & SDL_WINDOW_POPUP_MENU) != 0)) > 1) {
icculus@10021
  1365
        SDL_SetError("Conflicting window flags specified");
icculus@10021
  1366
        return NULL;
icculus@10021
  1367
    }
icculus@10021
  1368
slouken@8582
  1369
    /* Some platforms can't create zero-sized windows */
slouken@8582
  1370
    if (w < 1) {
slouken@8582
  1371
        w = 1;
slouken@8582
  1372
    }
slouken@8582
  1373
    if (h < 1) {
slouken@8582
  1374
        h = 1;
slouken@8582
  1375
    }
slouken@8582
  1376
icculus@9461
  1377
    /* Some platforms blow up if the windows are too large. Raise it later? */
icculus@9461
  1378
    if ((w > 16384) || (h > 16384)) {
icculus@9461
  1379
        SDL_SetError("Window is too large.");
icculus@9461
  1380
        return NULL;
icculus@9461
  1381
    }
icculus@9461
  1382
slouken@8582
  1383
    /* Some platforms have OpenGL enabled by default */
gabomdq@8833
  1384
#if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__
slouken@10699
  1385
    if (!_this->is_dummy) {
slouken@10491
  1386
        flags |= SDL_WINDOW_OPENGL;
slouken@10491
  1387
    }
slouken@8582
  1388
#endif
slouken@8582
  1389
    if (flags & SDL_WINDOW_OPENGL) {
slouken@8582
  1390
        if (!_this->GL_CreateContext) {
slouken@8582
  1391
            SDL_SetError("No OpenGL support in video driver");
slouken@8582
  1392
            return NULL;
slouken@8582
  1393
        }
slouken@8582
  1394
        if (SDL_GL_LoadLibrary(NULL) < 0) {
slouken@8582
  1395
            return NULL;
slouken@8582
  1396
        }
slouken@8582
  1397
    }
slouken@8582
  1398
slouken@8582
  1399
    /* Unless the user has specified the high-DPI disabling hint, respect the
slouken@8582
  1400
     * SDL_WINDOW_ALLOW_HIGHDPI flag.
slouken@8582
  1401
     */
slouken@8582
  1402
    if (flags & SDL_WINDOW_ALLOW_HIGHDPI) {
slouken@10499
  1403
        if (SDL_GetHintBoolean(SDL_HINT_VIDEO_HIGHDPI_DISABLED, SDL_FALSE)) {
slouken@8582
  1404
            flags &= ~SDL_WINDOW_ALLOW_HIGHDPI;
slouken@8582
  1405
        }
slouken@8582
  1406
    }
slouken@8582
  1407
slouken@8582
  1408
    window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
slouken@8582
  1409
    if (!window) {
slouken@8582
  1410
        SDL_OutOfMemory();
slouken@8582
  1411
        return NULL;
slouken@8582
  1412
    }
slouken@8582
  1413
    window->magic = &_this->window_magic;
slouken@8582
  1414
    window->id = _this->next_object_id++;
slouken@8582
  1415
    window->x = x;
slouken@8582
  1416
    window->y = y;
slouken@8582
  1417
    window->w = w;
slouken@8582
  1418
    window->h = h;
slouken@8582
  1419
    if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
slouken@8582
  1420
        SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@8582
  1421
        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@8582
  1422
        int displayIndex;
slouken@8582
  1423
        SDL_Rect bounds;
slouken@8582
  1424
slouken@8582
  1425
        displayIndex = SDL_GetIndexOfDisplay(display);
slouken@8582
  1426
        SDL_GetDisplayBounds(displayIndex, &bounds);
slouken@8582
  1427
        if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
slouken@8582
  1428
            window->x = bounds.x + (bounds.w - w) / 2;
slouken@8582
  1429
        }
slouken@8582
  1430
        if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@8582
  1431
            window->y = bounds.y + (bounds.h - h) / 2;
slouken@8582
  1432
        }
slouken@8582
  1433
    }
slouken@10056
  1434
    window->windowed.x = window->x;
slouken@10056
  1435
    window->windowed.y = window->y;
slouken@10056
  1436
    window->windowed.w = window->w;
slouken@10056
  1437
    window->windowed.h = window->h;
slouken@10056
  1438
slouken@10056
  1439
    if (flags & SDL_WINDOW_FULLSCREEN) {
slouken@10056
  1440
        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@10056
  1441
        int displayIndex;
slouken@10056
  1442
        SDL_Rect bounds;
slouken@10056
  1443
slouken@10056
  1444
        displayIndex = SDL_GetIndexOfDisplay(display);
slouken@10056
  1445
        SDL_GetDisplayBounds(displayIndex, &bounds);
slouken@10056
  1446
slouken@10056
  1447
        window->x = bounds.x;
slouken@10056
  1448
        window->y = bounds.y;
slouken@10056
  1449
        window->w = bounds.w;
slouken@10056
  1450
        window->h = bounds.h;
slouken@10056
  1451
    }
slouken@10056
  1452
slouken@8582
  1453
    window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
jorgen@8110
  1454
    window->last_fullscreen_flags = window->flags;
icculus@10025
  1455
    window->opacity = 1.0f;
slouken@8582
  1456
    window->brightness = 1.0f;
slouken@8582
  1457
    window->next = _this->windows;
jorgen@8112
  1458
    window->is_destroying = SDL_FALSE;
slouken@8582
  1459
slouken@8582
  1460
    if (_this->windows) {
slouken@8582
  1461
        _this->windows->prev = window;
slouken@8582
  1462
    }
slouken@8582
  1463
    _this->windows = window;
slouken@8582
  1464
slouken@8582
  1465
    if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
slouken@8582
  1466
        SDL_DestroyWindow(window);
slouken@8582
  1467
        return NULL;
slouken@8582
  1468
    }
slouken@8582
  1469
dludwig@9931
  1470
#if __WINRT__ && (NTDDI_VERSION < NTDDI_WIN10)
dludwig@9924
  1471
    /* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
dludwig@9924
  1472
       or not.  The user can choose this, via OS-provided UI, but this can't
dludwig@9924
  1473
       be set programmatically.
dludwig@9924
  1474
dludwig@9924
  1475
       Just look at what SDL's WinRT video backend code detected with regards
dludwig@9924
  1476
       to fullscreen (being active, or not), and figure out a return/error code
dludwig@9924
  1477
       from that.
dludwig@9924
  1478
    */
dludwig@9924
  1479
    flags = window->flags;
dludwig@9924
  1480
#endif
dludwig@9924
  1481
slouken@8582
  1482
    if (title) {
slouken@8582
  1483
        SDL_SetWindowTitle(window, title);
slouken@8582
  1484
    }
slouken@8582
  1485
    SDL_FinishWindowCreation(window, flags);
slouken@8582
  1486
slouken@8582
  1487
    /* If the window was created fullscreen, make sure the mode code matches */
slouken@8582
  1488
    SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
slouken@8582
  1489
slouken@8582
  1490
    return window;
slouken@8582
  1491
}
slouken@8582
  1492
slouken@8582
  1493
SDL_Window *
slouken@8582
  1494
SDL_CreateWindowFrom(const void *data)
slouken@8582
  1495
{
slouken@8582
  1496
    SDL_Window *window;
slouken@8582
  1497
slouken@8582
  1498
    if (!_this) {
slouken@8582
  1499
        SDL_UninitializedVideo();
slouken@8582
  1500
        return NULL;
slouken@8582
  1501
    }
slouken@9163
  1502
    if (!_this->CreateWindowFrom) {
slouken@9163
  1503
        SDL_Unsupported();
slouken@9163
  1504
        return NULL;
slouken@9163
  1505
    }
slouken@8582
  1506
    window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
slouken@8582
  1507
    if (!window) {
slouken@8582
  1508
        SDL_OutOfMemory();
slouken@8582
  1509
        return NULL;
slouken@8582
  1510
    }
slouken@8582
  1511
    window->magic = &_this->window_magic;
slouken@8582
  1512
    window->id = _this->next_object_id++;
slouken@8582
  1513
    window->flags = SDL_WINDOW_FOREIGN;
jorgen@8110
  1514
    window->last_fullscreen_flags = window->flags;
jorgen@8112
  1515
    window->is_destroying = SDL_FALSE;
icculus@10025
  1516
    window->opacity = 1.0f;
slouken@8582
  1517
    window->brightness = 1.0f;
slouken@8582
  1518
    window->next = _this->windows;
slouken@8582
  1519
    if (_this->windows) {
slouken@8582
  1520
        _this->windows->prev = window;
slouken@8582
  1521
    }
slouken@8582
  1522
    _this->windows = window;
slouken@8582
  1523
slouken@9163
  1524
    if (_this->CreateWindowFrom(_this, window, data) < 0) {
slouken@8582
  1525
        SDL_DestroyWindow(window);
slouken@8582
  1526
        return NULL;
slouken@8582
  1527
    }
slouken@8582
  1528
    return window;
slouken@8582
  1529
}
slouken@8582
  1530
slouken@8582
  1531
int
slouken@8582
  1532
SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
slouken@8582
  1533
{
slouken@8906
  1534
    SDL_bool loaded_opengl = SDL_FALSE;
slouken@8582
  1535
slouken@8582
  1536
    if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
slouken@8582
  1537
        return SDL_SetError("No OpenGL support in video driver");
slouken@8582
  1538
    }
slouken@8582
  1539
slouken@8582
  1540
    if (window->flags & SDL_WINDOW_FOREIGN) {
slouken@8582
  1541
        /* Can't destroy and re-create foreign windows, hrm */
slouken@8582
  1542
        flags |= SDL_WINDOW_FOREIGN;
slouken@8582
  1543
    } else {
slouken@8582
  1544
        flags &= ~SDL_WINDOW_FOREIGN;
slouken@8582
  1545
    }
slouken@8582
  1546
slouken@8582
  1547
    /* Restore video mode, etc. */
slouken@8582
  1548
    SDL_HideWindow(window);
slouken@8582
  1549
slouken@8582
  1550
    /* Tear down the old native window */
slouken@8582
  1551
    if (window->surface) {
slouken@8582
  1552
        window->surface->flags &= ~SDL_DONTFREE;
slouken@8582
  1553
        SDL_FreeSurface(window->surface);
philipp@9988
  1554
        window->surface = NULL;
slouken@8582
  1555
    }
slouken@8582
  1556
    if (_this->DestroyWindowFramebuffer) {
slouken@8582
  1557
        _this->DestroyWindowFramebuffer(_this, window);
slouken@8582
  1558
    }
slouken@8582
  1559
    if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
slouken@8582
  1560
        _this->DestroyWindow(_this, window);
slouken@8582
  1561
    }
slouken@8582
  1562
slouken@8582
  1563
    if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
slouken@8582
  1564
        if (flags & SDL_WINDOW_OPENGL) {
slouken@8582
  1565
            if (SDL_GL_LoadLibrary(NULL) < 0) {
slouken@8582
  1566
                return -1;
slouken@8582
  1567
            }
slouken@8906
  1568
            loaded_opengl = SDL_TRUE;
slouken@8582
  1569
        } else {
slouken@8582
  1570
            SDL_GL_UnloadLibrary();
slouken@8582
  1571
        }
slouken@8582
  1572
    }
slouken@8582
  1573
slouken@8582
  1574
    window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
jorgen@8110
  1575
    window->last_fullscreen_flags = window->flags;
jorgen@8112
  1576
    window->is_destroying = SDL_FALSE;
slouken@8582
  1577
slouken@8582
  1578
    if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
slouken@8582
  1579
        if (_this->CreateWindow(_this, window) < 0) {
slouken@8906
  1580
            if (loaded_opengl) {
slouken@8582
  1581
                SDL_GL_UnloadLibrary();
slouken@8906
  1582
                window->flags &= ~SDL_WINDOW_OPENGL;
slouken@8582
  1583
            }
slouken@8582
  1584
            return -1;
slouken@8582
  1585
        }
slouken@8582
  1586
    }
slouken@9776
  1587
slouken@8708
  1588
    if (flags & SDL_WINDOW_FOREIGN) {
slouken@8708
  1589
        window->flags |= SDL_WINDOW_FOREIGN;
slouken@8708
  1590
    }
slouken@8582
  1591
slouken@9776
  1592
    if (_this->SetWindowTitle && window->title) {
slouken@9776
  1593
        _this->SetWindowTitle(_this, window);
slouken@8582
  1594
    }
slouken@9776
  1595
slouken@9776
  1596
    if (_this->SetWindowIcon && window->icon) {
slouken@9776
  1597
        _this->SetWindowIcon(_this, window, window->icon);
slouken@8582
  1598
    }
icculus@8931
  1599
icculus@8953
  1600
    if (window->hit_test) {
icculus@8935
  1601
        _this->SetWindowHitTest(window, SDL_TRUE);
icculus@8931
  1602
    }
icculus@8931
  1603
slouken@8582
  1604
    SDL_FinishWindowCreation(window, flags);
slouken@8582
  1605
slouken@8582
  1606
    return 0;
slouken@8582
  1607
}
slouken@8582
  1608
slouken@8582
  1609
Uint32
slouken@8582
  1610
SDL_GetWindowID(SDL_Window * window)
slouken@8582
  1611
{
slouken@8582
  1612
    CHECK_WINDOW_MAGIC(window, 0);
slouken@8582
  1613
slouken@8582
  1614
    return window->id;
slouken@8582
  1615
}
slouken@8582
  1616
slouken@8582
  1617
SDL_Window *
slouken@8582
  1618
SDL_GetWindowFromID(Uint32 id)
slouken@8582
  1619
{
slouken@8582
  1620
    SDL_Window *window;
slouken@8582
  1621
slouken@8582
  1622
    if (!_this) {
slouken@8582
  1623
        return NULL;
slouken@8582
  1624
    }
slouken@8582
  1625
    for (window = _this->windows; window; window = window->next) {
slouken@8582
  1626
        if (window->id == id) {
slouken@8582
  1627
            return window;
slouken@8582
  1628
        }
slouken@8582
  1629
    }
slouken@8582
  1630
    return NULL;
slouken@8582
  1631
}
slouken@8582
  1632
slouken@8582
  1633
Uint32
slouken@8582
  1634
SDL_GetWindowFlags(SDL_Window * window)
slouken@8582
  1635
{
slouken@8582
  1636
    CHECK_WINDOW_MAGIC(window, 0);
slouken@8582
  1637
slouken@8582
  1638
    return window->flags;
slouken@8582
  1639
}
slouken@8582
  1640
slouken@8582
  1641
void
slouken@8582
  1642
SDL_SetWindowTitle(SDL_Window * window, const char *title)
slouken@8582
  1643
{
slouken@8818
  1644
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  1645
slouken@8582
  1646
    if (title == window->title) {
slouken@8582
  1647
        return;
slouken@8582
  1648
    }
slouken@8582
  1649
    SDL_free(window->title);
icculus@9474
  1650
icculus@9474
  1651
    window->title = SDL_strdup(title ? title : "");
slouken@8582
  1652
slouken@8582
  1653
    if (_this->SetWindowTitle) {
slouken@8582
  1654
        _this->SetWindowTitle(_this, window);
slouken@8582
  1655
    }
slouken@8582
  1656
}
slouken@8582
  1657
slouken@8582
  1658
const char *
slouken@8582
  1659
SDL_GetWindowTitle(SDL_Window * window)
slouken@8582
  1660
{
slouken@8582
  1661
    CHECK_WINDOW_MAGIC(window, "");
slouken@8582
  1662
slouken@8582
  1663
    return window->title ? window->title : "";
slouken@8582
  1664
}
slouken@8582
  1665
slouken@8582
  1666
void
slouken@8582
  1667
SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
slouken@8582
  1668
{
slouken@8818
  1669
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  1670
slouken@8582
  1671
    if (!icon) {
slouken@8582
  1672
        return;
slouken@8582
  1673
    }
slouken@8582
  1674
slouken@8582
  1675
    SDL_FreeSurface(window->icon);
slouken@8582
  1676
slouken@8582
  1677
    /* Convert the icon into ARGB8888 */
slouken@8582
  1678
    window->icon = SDL_ConvertSurfaceFormat(icon, SDL_PIXELFORMAT_ARGB8888, 0);
slouken@8582
  1679
    if (!window->icon) {
slouken@8582
  1680
        return;
slouken@8582
  1681
    }
slouken@8582
  1682
slouken@8582
  1683
    if (_this->SetWindowIcon) {
slouken@8582
  1684
        _this->SetWindowIcon(_this, window, window->icon);
slouken@8582
  1685
    }
slouken@8582
  1686
}
slouken@8582
  1687
slouken@8582
  1688
void*
slouken@8582
  1689
SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
slouken@8582
  1690
{
slouken@8582
  1691
    SDL_WindowUserData *prev, *data;
slouken@8582
  1692
slouken@8582
  1693
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@8582
  1694
slouken@8582
  1695
    /* Input validation */
slouken@8582
  1696
    if (name == NULL || name[0] == '\0') {
slouken@8582
  1697
      SDL_InvalidParamError("name");
slouken@8582
  1698
      return NULL;
slouken@8582
  1699
    }
slouken@8582
  1700
slouken@8582
  1701
    /* See if the named data already exists */
slouken@8582
  1702
    prev = NULL;
slouken@8582
  1703
    for (data = window->data; data; prev = data, data = data->next) {
slouken@8582
  1704
        if (data->name && SDL_strcmp(data->name, name) == 0) {
slouken@8582
  1705
            void *last_value = data->data;
slouken@8582
  1706
slouken@8582
  1707
            if (userdata) {
slouken@8582
  1708
                /* Set the new value */
slouken@8582
  1709
                data->data = userdata;
slouken@8582
  1710
            } else {
slouken@8582
  1711
                /* Delete this value */
slouken@8582
  1712
                if (prev) {
slouken@8582
  1713
                    prev->next = data->next;
slouken@8582
  1714
                } else {
slouken@8582
  1715
                    window->data = data->next;
slouken@8582
  1716
                }
slouken@8582
  1717
                SDL_free(data->name);
slouken@8582
  1718
                SDL_free(data);
slouken@8582
  1719
            }
slouken@8582
  1720
            return last_value;
slouken@8582
  1721
        }
slouken@8582
  1722
    }
slouken@8582
  1723
slouken@8582
  1724
    /* Add new data to the window */
slouken@8582
  1725
    if (userdata) {
slouken@8582
  1726
        data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
slouken@8582
  1727
        data->name = SDL_strdup(name);
slouken@8582
  1728
        data->data = userdata;
slouken@8582
  1729
        data->next = window->data;
slouken@8582
  1730
        window->data = data;
slouken@8582
  1731
    }
slouken@8582
  1732
    return NULL;
slouken@8582
  1733
}
slouken@8582
  1734
slouken@8582
  1735
void *
slouken@8582
  1736
SDL_GetWindowData(SDL_Window * window, const char *name)
slouken@8582
  1737
{
slouken@8582
  1738
    SDL_WindowUserData *data;
slouken@8582
  1739
slouken@8582
  1740
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@8582
  1741
slouken@8582
  1742
    /* Input validation */
slouken@8582
  1743
    if (name == NULL || name[0] == '\0') {
slouken@8582
  1744
      SDL_InvalidParamError("name");
slouken@8582
  1745
      return NULL;
slouken@8582
  1746
    }
slouken@8582
  1747
slouken@8582
  1748
    for (data = window->data; data; data = data->next) {
slouken@8582
  1749
        if (data->name && SDL_strcmp(data->name, name) == 0) {
slouken@8582
  1750
            return data->data;
slouken@8582
  1751
        }
slouken@8582
  1752
    }
slouken@8582
  1753
    return NULL;
slouken@8582
  1754
}
slouken@8582
  1755
slouken@8582
  1756
void
slouken@8582
  1757
SDL_SetWindowPosition(SDL_Window * window, int x, int y)
slouken@8582
  1758
{
slouken@8818
  1759
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  1760
slouken@8582
  1761
    if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
urkle@9363
  1762
        int displayIndex = (x & 0xFFFF);
slouken@8582
  1763
        SDL_Rect bounds;
slouken@10732
  1764
        if (displayIndex >= _this->num_displays) {
urkle@9363
  1765
            displayIndex = 0;
urkle@9363
  1766
        }
slouken@8582
  1767
icculus@8655
  1768
        SDL_zero(bounds);
icculus@8655
  1769
slouken@8582
  1770
        SDL_GetDisplayBounds(displayIndex, &bounds);
slouken@8582
  1771
        if (SDL_WINDOWPOS_ISCENTERED(x)) {
slouken@8582
  1772
            x = bounds.x + (bounds.w - window->w) / 2;
slouken@8582
  1773
        }
slouken@8582
  1774
        if (SDL_WINDOWPOS_ISCENTERED(y)) {
slouken@8582
  1775
            y = bounds.y + (bounds.h - window->h) / 2;
slouken@8582
  1776
        }
slouken@8582
  1777
    }
slouken@8582
  1778
slouken@8582
  1779
    if ((window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@8582
  1780
        if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
slouken@8582
  1781
            window->windowed.x = x;
slouken@8582
  1782
        }
slouken@8582
  1783
        if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
slouken@8582
  1784
            window->windowed.y = y;
slouken@8582
  1785
        }
slouken@8582
  1786
    } else {
slouken@8582
  1787
        if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
slouken@8582
  1788
            window->x = x;
slouken@8582
  1789
        }
slouken@8582
  1790
        if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
slouken@8582
  1791
            window->y = y;
slouken@8582
  1792
        }
slouken@8582
  1793
slouken@8582
  1794
        if (_this->SetWindowPosition) {
slouken@8582
  1795
            _this->SetWindowPosition(_this, window);
slouken@8582
  1796
        }
slouken@8582
  1797
        SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@8582
  1798
    }
slouken@8582
  1799
}
slouken@8582
  1800
slouken@8582
  1801
void
slouken@8582
  1802
SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
slouken@8582
  1803
{
slouken@8818
  1804
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  1805
slouken@8582
  1806
    /* Fullscreen windows are always at their display's origin */
slouken@8582
  1807
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
alfred@9818
  1808
        int displayIndex;
alfred@9818
  1809
        
slouken@8582
  1810
        if (x) {
slouken@8582
  1811
            *x = 0;
slouken@8582
  1812
        }
slouken@8582
  1813
        if (y) {
slouken@8582
  1814
            *y = 0;
slouken@8582
  1815
        }
alfred@9818
  1816
alfred@9818
  1817
        /* Find the window's monitor and update to the
alfred@9818
  1818
           monitor offset. */
alfred@9818
  1819
        displayIndex = SDL_GetWindowDisplayIndex(window);
alfred@9818
  1820
        if (displayIndex >= 0) {
alfred@9818
  1821
            SDL_Rect bounds;
alfred@9818
  1822
alfred@9818
  1823
            SDL_zero(bounds);
alfred@9818
  1824
alfred@9818
  1825
            SDL_GetDisplayBounds(displayIndex, &bounds);
alfred@9818
  1826
            if (x) {
alfred@9818
  1827
                *x = bounds.x;
alfred@9818
  1828
            }
alfred@9818
  1829
            if (y) {
alfred@9818
  1830
                *y = bounds.y;
alfred@9818
  1831
            }
alfred@9818
  1832
        }
slouken@8582
  1833
    } else {
slouken@8582
  1834
        if (x) {
slouken@8582
  1835
            *x = window->x;
slouken@8582
  1836
        }
slouken@8582
  1837
        if (y) {
slouken@8582
  1838
            *y = window->y;
slouken@8582
  1839
        }
slouken@8582
  1840
    }
slouken@8582
  1841
}
slouken@8582
  1842
slouken@8582
  1843
void
slouken@8582
  1844
SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered)
slouken@8582
  1845
{
slouken@8818
  1846
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  1847
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@8582
  1848
        const int want = (bordered != SDL_FALSE);  /* normalize the flag. */
slouken@8582
  1849
        const int have = ((window->flags & SDL_WINDOW_BORDERLESS) == 0);
slouken@8582
  1850
        if ((want != have) && (_this->SetWindowBordered)) {
slouken@8582
  1851
            if (want) {
slouken@8582
  1852
                window->flags &= ~SDL_WINDOW_BORDERLESS;
slouken@8582
  1853
            } else {
slouken@8582
  1854
                window->flags |= SDL_WINDOW_BORDERLESS;
slouken@8582
  1855
            }
slouken@8582
  1856
            _this->SetWindowBordered(_this, window, (SDL_bool) want);
slouken@8582
  1857
        }
slouken@8582
  1858
    }
slouken@8582
  1859
}
slouken@8582
  1860
slouken@8582
  1861
void
icculus@10385
  1862
SDL_SetWindowResizable(SDL_Window * window, SDL_bool resizable)
icculus@10385
  1863
{
icculus@10385
  1864
    CHECK_WINDOW_MAGIC(window,);
icculus@10385
  1865
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
icculus@10385
  1866
        const int want = (resizable != SDL_FALSE);  /* normalize the flag. */
icculus@10385
  1867
        const int have = ((window->flags & SDL_WINDOW_RESIZABLE) != 0);
icculus@10385
  1868
        if ((want != have) && (_this->SetWindowResizable)) {
icculus@10385
  1869
            if (want) {
icculus@10385
  1870
                window->flags |= SDL_WINDOW_RESIZABLE;
icculus@10385
  1871
            } else {
icculus@10385
  1872
                window->flags &= ~SDL_WINDOW_RESIZABLE;
icculus@10385
  1873
            }
icculus@10385
  1874
            _this->SetWindowResizable(_this, window, (SDL_bool) want);
icculus@10385
  1875
        }
icculus@10385
  1876
    }
icculus@10385
  1877
}
icculus@10385
  1878
icculus@10385
  1879
void
slouken@8582
  1880
SDL_SetWindowSize(SDL_Window * window, int w, int h)
slouken@8582
  1881
{
slouken@8818
  1882
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  1883
    if (w <= 0) {
slouken@8582
  1884
        SDL_InvalidParamError("w");
slouken@8582
  1885
        return;
slouken@8582
  1886
    }
slouken@8582
  1887
    if (h <= 0) {
slouken@8582
  1888
        SDL_InvalidParamError("h");
slouken@8582
  1889
        return;
slouken@8582
  1890
    }
slouken@8582
  1891
slouken@8582
  1892
    /* Make sure we don't exceed any window size limits */
slouken@8582
  1893
    if (window->min_w && w < window->min_w)
slouken@8582
  1894
    {
slouken@8582
  1895
        w = window->min_w;
slouken@8582
  1896
    }
slouken@8582
  1897
    if (window->max_w && w > window->max_w)
slouken@8582
  1898
    {
slouken@8582
  1899
        w = window->max_w;
slouken@8582
  1900
    }
slouken@8582
  1901
    if (window->min_h && h < window->min_h)
slouken@8582
  1902
    {
slouken@8582
  1903
        h = window->min_h;
slouken@8582
  1904
    }
slouken@8582
  1905
    if (window->max_h && h > window->max_h)
slouken@8582
  1906
    {
slouken@8582
  1907
        h = window->max_h;
slouken@8582
  1908
    }
slouken@8582
  1909
slouken@8823
  1910
    window->windowed.w = w;
slouken@8823
  1911
    window->windowed.h = h;
slouken@8823
  1912
slouken@8582
  1913
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@8818
  1914
        if (FULLSCREEN_VISIBLE(window) && (window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
slouken@8823
  1915
            window->last_fullscreen_flags = 0;
slouken@8823
  1916
            SDL_UpdateFullscreenMode(window, SDL_TRUE);
slouken@8818
  1917
        }
slouken@8582
  1918
    } else {
slouken@8582
  1919
        window->w = w;
slouken@8582
  1920
        window->h = h;
slouken@8582
  1921
        if (_this->SetWindowSize) {
slouken@8582
  1922
            _this->SetWindowSize(_this, window);
slouken@8582
  1923
        }
slouken@8582
  1924
        if (window->w == w && window->h == h) {
slouken@8582
  1925
            /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
slouken@8582
  1926
            SDL_OnWindowResized(window);
slouken@8582
  1927
        }
slouken@8582
  1928
    }
slouken@8582
  1929
}
slouken@8582
  1930
slouken@8582
  1931
void
slouken@8582
  1932
SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
slouken@8582
  1933
{
slouken@8818
  1934
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  1935
    if (w) {
slouken@8582
  1936
        *w = window->w;
slouken@8582
  1937
    }
slouken@8582
  1938
    if (h) {
slouken@8582
  1939
        *h = window->h;
slouken@8582
  1940
    }
slouken@8582
  1941
}
slouken@8582
  1942
slouken@10860
  1943
int
slouken@10860
  1944
SDL_GetWindowBordersSize(SDL_Window * window, int *top, int *left, int *bottom, int *right)
slouken@10860
  1945
{
slouken@10860
  1946
    int dummy = 0;
slouken@10860
  1947
slouken@10860
  1948
    if (!top) { top = &dummy; }
slouken@10860
  1949
    if (!left) { left = &dummy; }
slouken@10860
  1950
    if (!right) { right = &dummy; }
slouken@10860
  1951
    if (!bottom) { bottom = &dummy; }
slouken@10860
  1952
slouken@10860
  1953
    /* Always initialize, so applications don't have to care */
slouken@10860
  1954
    *top = *left = *bottom = *right = 0;
slouken@10860
  1955
slouken@10860
  1956
    CHECK_WINDOW_MAGIC(window, -1);
slouken@10860
  1957
slouken@10860
  1958
    if (!_this->GetWindowBordersSize) {
slouken@10860
  1959
        return SDL_Unsupported();
slouken@10860
  1960
    }
slouken@10860
  1961
slouken@10860
  1962
    return _this->GetWindowBordersSize(_this, window, top, left, bottom, right);
slouken@10860
  1963
}
slouken@10860
  1964
slouken@8582
  1965
void
slouken@8582
  1966
SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h)
slouken@8582
  1967
{
slouken@8818
  1968
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  1969
    if (min_w <= 0) {
slouken@8582
  1970
        SDL_InvalidParamError("min_w");
slouken@8582
  1971
        return;
slouken@8582
  1972
    }
slouken@8582
  1973
    if (min_h <= 0) {
slouken@8582
  1974
        SDL_InvalidParamError("min_h");
slouken@8582
  1975
        return;
slouken@8582
  1976
    }
slouken@8582
  1977
slouken@10871
  1978
    if ((window->max_w && min_w >= window->max_w) ||
slouken@10871
  1979
        (window->max_h && min_h >= window->max_h)) {
slouken@10860
  1980
        SDL_SetError("SDL_SetWindowMinimumSize(): Tried to set minimum size larger than maximum size");
slouken@10860
  1981
        return;
slouken@10860
  1982
    }
slouken@10860
  1983
slouken@10860
  1984
    window->min_w = min_w;
slouken@10860
  1985
    window->min_h = min_h;
slouken@10860
  1986
slouken@8582
  1987
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@8582
  1988
        if (_this->SetWindowMinimumSize) {
slouken@8582
  1989
            _this->SetWindowMinimumSize(_this, window);
slouken@8582
  1990
        }
slouken@8582
  1991
        /* Ensure that window is not smaller than minimal size */
slouken@8582
  1992
        SDL_SetWindowSize(window, SDL_max(window->w, window->min_w), SDL_max(window->h, window->min_h));
slouken@8582
  1993
    }
slouken@8582
  1994
}
slouken@8582
  1995
slouken@8582
  1996
void
slouken@8582
  1997
SDL_GetWindowMinimumSize(SDL_Window * window, int *min_w, int *min_h)
slouken@8582
  1998
{
slouken@8818
  1999
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2000
    if (min_w) {
slouken@8582
  2001
        *min_w = window->min_w;
slouken@8582
  2002
    }
slouken@8582
  2003
    if (min_h) {
slouken@8582
  2004
        *min_h = window->min_h;
slouken@8582
  2005
    }
slouken@8582
  2006
}
slouken@8582
  2007
slouken@8582
  2008
void
slouken@8582
  2009
SDL_SetWindowMaximumSize(SDL_Window * window, int max_w, int max_h)
slouken@8582
  2010
{
slouken@8818
  2011
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2012
    if (max_w <= 0) {
slouken@8582
  2013
        SDL_InvalidParamError("max_w");
slouken@8582
  2014
        return;
slouken@8582
  2015
    }
slouken@8582
  2016
    if (max_h <= 0) {
slouken@8582
  2017
        SDL_InvalidParamError("max_h");
slouken@8582
  2018
        return;
slouken@8582
  2019
    }
slouken@8582
  2020
slouken@10860
  2021
    if (max_w <= window->min_w || max_h <= window->min_h) {
slouken@10860
  2022
        SDL_SetError("SDL_SetWindowMaximumSize(): Tried to set maximum size smaller than minimum size");
slouken@10860
  2023
        return;
slouken@10860
  2024
    }
slouken@10860
  2025
slouken@10860
  2026
    window->max_w = max_w;
slouken@10860
  2027
    window->max_h = max_h;
slouken@10860
  2028
slouken@8582
  2029
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@8582
  2030
        if (_this->SetWindowMaximumSize) {
slouken@8582
  2031
            _this->SetWindowMaximumSize(_this, window);
slouken@8582
  2032
        }
slouken@8582
  2033
        /* Ensure that window is not larger than maximal size */
slouken@8582
  2034
        SDL_SetWindowSize(window, SDL_min(window->w, window->max_w), SDL_min(window->h, window->max_h));
slouken@8582
  2035
    }
slouken@8582
  2036
}
slouken@8582
  2037
slouken@8582
  2038
void
slouken@8582
  2039
SDL_GetWindowMaximumSize(SDL_Window * window, int *max_w, int *max_h)
slouken@8582
  2040
{
slouken@8818
  2041
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2042
    if (max_w) {
slouken@8582
  2043
        *max_w = window->max_w;
slouken@8582
  2044
    }
slouken@8582
  2045
    if (max_h) {
slouken@8582
  2046
        *max_h = window->max_h;
slouken@8582
  2047
    }
slouken@8582
  2048
}
slouken@8582
  2049
slouken@8582
  2050
void
slouken@8582
  2051
SDL_ShowWindow(SDL_Window * window)
slouken@8582
  2052
{
slouken@8818
  2053
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2054
slouken@8582
  2055
    if (window->flags & SDL_WINDOW_SHOWN) {
slouken@8582
  2056
        return;
slouken@8582
  2057
    }
slouken@8582
  2058
slouken@8582
  2059
    if (_this->ShowWindow) {
slouken@8582
  2060
        _this->ShowWindow(_this, window);
slouken@8582
  2061
    }
slouken@8582
  2062
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@8582
  2063
}
slouken@8582
  2064
slouken@8582
  2065
void
slouken@8582
  2066
SDL_HideWindow(SDL_Window * window)
slouken@8582
  2067
{
slouken@8818
  2068
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2069
slouken@8582
  2070
    if (!(window->flags & SDL_WINDOW_SHOWN)) {
slouken@8582
  2071
        return;
slouken@8582
  2072
    }
slouken@8582
  2073
alfred@9037
  2074
	window->is_hiding = SDL_TRUE;
slouken@8582
  2075
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@8582
  2076
slouken@8582
  2077
    if (_this->HideWindow) {
slouken@8582
  2078
        _this->HideWindow(_this, window);
slouken@8582
  2079
    }
alfred@9037
  2080
	window->is_hiding = SDL_FALSE;
slouken@8582
  2081
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@8582
  2082
}
slouken@8582
  2083
slouken@8582
  2084
void
slouken@8582
  2085
SDL_RaiseWindow(SDL_Window * window)
slouken@8582
  2086
{
slouken@8818
  2087
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2088
slouken@8582
  2089
    if (!(window->flags & SDL_WINDOW_SHOWN)) {
slouken@8582
  2090
        return;
slouken@8582
  2091
    }
slouken@8582
  2092
    if (_this->RaiseWindow) {
slouken@8582
  2093
        _this->RaiseWindow(_this, window);
slouken@8582
  2094
    }
slouken@8582
  2095
}
slouken@8582
  2096
slouken@8582
  2097
void
slouken@8582
  2098
SDL_MaximizeWindow(SDL_Window * window)
slouken@8582
  2099
{
slouken@8818
  2100
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2101
slouken@8582
  2102
    if (window->flags & SDL_WINDOW_MAXIMIZED) {
slouken@8582
  2103
        return;
slouken@8582
  2104
    }
slouken@8582
  2105
slouken@8582
  2106
    /* !!! FIXME: should this check if the window is resizable? */
slouken@8582
  2107
slouken@8582
  2108
    if (_this->MaximizeWindow) {
slouken@8582
  2109
        _this->MaximizeWindow(_this, window);
slouken@8582
  2110
    }
slouken@8582
  2111
}
slouken@8582
  2112
slouken@8582
  2113
void
slouken@8582
  2114
SDL_MinimizeWindow(SDL_Window * window)
slouken@8582
  2115
{
slouken@8818
  2116
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2117
slouken@8582
  2118
    if (window->flags & SDL_WINDOW_MINIMIZED) {
slouken@8582
  2119
        return;
slouken@8582
  2120
    }
slouken@8582
  2121
slouken@8582
  2122
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@8582
  2123
slouken@8582
  2124
    if (_this->MinimizeWindow) {
slouken@8582
  2125
        _this->MinimizeWindow(_this, window);
slouken@8582
  2126
    }
slouken@8582
  2127
}
slouken@8582
  2128
slouken@8582
  2129
void
slouken@8582
  2130
SDL_RestoreWindow(SDL_Window * window)
slouken@8582
  2131
{
slouken@8818
  2132
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2133
slouken@8582
  2134
    if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
slouken@8582
  2135
        return;
slouken@8582
  2136
    }
slouken@8582
  2137
slouken@8582
  2138
    if (_this->RestoreWindow) {
slouken@8582
  2139
        _this->RestoreWindow(_this, window);
slouken@8582
  2140
    }
slouken@8582
  2141
}
slouken@8582
  2142
slouken@8582
  2143
int
slouken@8582
  2144
SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
slouken@8582
  2145
{
slouken@9905
  2146
    Uint32 oldflags;
slouken@8582
  2147
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8582
  2148
slouken@8582
  2149
    flags &= FULLSCREEN_MASK;
slouken@8582
  2150
slouken@8818
  2151
    if (flags == (window->flags & FULLSCREEN_MASK)) {
slouken@8582
  2152
        return 0;
slouken@8582
  2153
    }
slouken@8582
  2154
slouken@8582
  2155
    /* clear the previous flags and OR in the new ones */
slouken@9905
  2156
    oldflags = window->flags & FULLSCREEN_MASK;
slouken@8582
  2157
    window->flags &= ~FULLSCREEN_MASK;
slouken@8582
  2158
    window->flags |= flags;
slouken@8582
  2159
slouken@9905
  2160
    if (SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window)) == 0) {
slouken@9905
  2161
        return 0;
slouken@9905
  2162
    }
slouken@9905
  2163
    
slouken@9905
  2164
    window->flags &= ~FULLSCREEN_MASK;
slouken@9905
  2165
    window->flags |= oldflags;
slouken@9905
  2166
    return -1;
slouken@8582
  2167
}
slouken@8582
  2168
slouken@8582
  2169
static SDL_Surface *
slouken@8582
  2170
SDL_CreateWindowFramebuffer(SDL_Window * window)
slouken@8582
  2171
{
slouken@8582
  2172
    Uint32 format;
slouken@8582
  2173
    void *pixels;
slouken@8582
  2174
    int pitch;
slouken@8582
  2175
    int bpp;
slouken@8582
  2176
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@8582
  2177
slouken@8582
  2178
    if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
slouken@8582
  2179
        return NULL;
slouken@8582
  2180
    }
slouken@8582
  2181
slouken@8582
  2182
    if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
slouken@8582
  2183
        return NULL;
slouken@8582
  2184
    }
slouken@8582
  2185
slouken@8582
  2186
    if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@8582
  2187
        return NULL;
slouken@8582
  2188
    }
slouken@8582
  2189
slouken@8582
  2190
    return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
slouken@8582
  2191
}
slouken@8582
  2192
slouken@8582
  2193
SDL_Surface *
slouken@8582
  2194
SDL_GetWindowSurface(SDL_Window * window)
slouken@8582
  2195
{
slouken@8582
  2196
    CHECK_WINDOW_MAGIC(window, NULL);
slouken@8582
  2197
slouken@8582
  2198
    if (!window->surface_valid) {
slouken@8582
  2199
        if (window->surface) {
slouken@8582
  2200
            window->surface->flags &= ~SDL_DONTFREE;
slouken@8582
  2201
            SDL_FreeSurface(window->surface);
slouken@8582
  2202
        }
slouken@8582
  2203
        window->surface = SDL_CreateWindowFramebuffer(window);
slouken@8582
  2204
        if (window->surface) {
slouken@8582
  2205
            window->surface_valid = SDL_TRUE;
slouken@8582
  2206
            window->surface->flags |= SDL_DONTFREE;
slouken@8582
  2207
        }
slouken@8582
  2208
    }
slouken@8582
  2209
    return window->surface;
slouken@8582
  2210
}
slouken@8582
  2211
slouken@8582
  2212
int
slouken@8582
  2213
SDL_UpdateWindowSurface(SDL_Window * window)
slouken@8582
  2214
{
slouken@8582
  2215
    SDL_Rect full_rect;
slouken@8582
  2216
slouken@8582
  2217
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8582
  2218
slouken@8582
  2219
    full_rect.x = 0;
slouken@8582
  2220
    full_rect.y = 0;
slouken@8582
  2221
    full_rect.w = window->w;
slouken@8582
  2222
    full_rect.h = window->h;
slouken@8582
  2223
    return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
slouken@8582
  2224
}
slouken@8582
  2225
slouken@8582
  2226
int
slouken@8582
  2227
SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
slouken@8582
  2228
                             int numrects)
slouken@8582
  2229
{
slouken@8582
  2230
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8582
  2231
slouken@8582
  2232
    if (!window->surface_valid) {
slouken@8582
  2233
        return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
slouken@8582
  2234
    }
slouken@8582
  2235
slouken@8582
  2236
    return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
slouken@8582
  2237
}
slouken@8582
  2238
slouken@8582
  2239
int
slouken@8582
  2240
SDL_SetWindowBrightness(SDL_Window * window, float brightness)
slouken@8582
  2241
{
slouken@8582
  2242
    Uint16 ramp[256];
slouken@8582
  2243
    int status;
slouken@8582
  2244
slouken@8582
  2245
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8582
  2246
slouken@8582
  2247
    SDL_CalculateGammaRamp(brightness, ramp);
slouken@8582
  2248
    status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
slouken@8582
  2249
    if (status == 0) {
slouken@8582
  2250
        window->brightness = brightness;
slouken@8582
  2251
    }
slouken@8582
  2252
    return status;
slouken@8582
  2253
}
slouken@8582
  2254
slouken@8582
  2255
float
slouken@8582
  2256
SDL_GetWindowBrightness(SDL_Window * window)
slouken@8582
  2257
{
slouken@8582
  2258
    CHECK_WINDOW_MAGIC(window, 1.0f);
slouken@8582
  2259
slouken@8582
  2260
    return window->brightness;
slouken@8582
  2261
}
slouken@8582
  2262
slouken@8582
  2263
int
icculus@10025
  2264
SDL_SetWindowOpacity(SDL_Window * window, float opacity)
icculus@10025
  2265
{
icculus@10025
  2266
    int retval;
icculus@10025
  2267
    CHECK_WINDOW_MAGIC(window, -1);
icculus@10025
  2268
icculus@10025
  2269
    if (!_this->SetWindowOpacity) {
icculus@10025
  2270
        return SDL_Unsupported();
icculus@10025
  2271
    }
icculus@10025
  2272
icculus@10025
  2273
    if (opacity < 0.0f) {
icculus@10025
  2274
        opacity = 0.0f;
icculus@10025
  2275
    } else if (opacity > 1.0f) {
icculus@10025
  2276
        opacity = 1.0f;
icculus@10025
  2277
    }
icculus@10025
  2278
icculus@10025
  2279
    retval = _this->SetWindowOpacity(_this, window, opacity);
icculus@10025
  2280
    if (retval == 0) {
icculus@10025
  2281
        window->opacity = opacity;
icculus@10025
  2282
    }
icculus@10025
  2283
icculus@10025
  2284
    return retval;
icculus@10025
  2285
}
icculus@10025
  2286
icculus@10025
  2287
int
icculus@10025
  2288
SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity)
icculus@10025
  2289
{
icculus@10025
  2290
    CHECK_WINDOW_MAGIC(window, -1);
icculus@10025
  2291
icculus@10025
  2292
    if (out_opacity) {
icculus@10025
  2293
        *out_opacity = window->opacity;
icculus@10025
  2294
    }
icculus@10025
  2295
icculus@10025
  2296
    return 0;
icculus@10025
  2297
}
icculus@10025
  2298
icculus@10027
  2299
int
icculus@10027
  2300
SDL_SetWindowModalFor(SDL_Window * modal_window, SDL_Window * parent_window)
icculus@10027
  2301
{
icculus@10027
  2302
    CHECK_WINDOW_MAGIC(modal_window, -1);
icculus@10027
  2303
    CHECK_WINDOW_MAGIC(parent_window, -1);
icculus@10027
  2304
icculus@10027
  2305
    if (!_this->SetWindowModalFor) {
icculus@10027
  2306
        return SDL_Unsupported();
icculus@10027
  2307
    }
icculus@10027
  2308
    
icculus@10027
  2309
    return _this->SetWindowModalFor(_this, modal_window, parent_window);
icculus@10027
  2310
}
icculus@10027
  2311
icculus@10026
  2312
int 
icculus@10026
  2313
SDL_SetWindowInputFocus(SDL_Window * window)
icculus@10026
  2314
{
icculus@10026
  2315
    CHECK_WINDOW_MAGIC(window, -1);
icculus@10026
  2316
icculus@10026
  2317
    if (!_this->SetWindowInputFocus) {
icculus@10026
  2318
        return SDL_Unsupported();
icculus@10026
  2319
    }
icculus@10026
  2320
    
icculus@10026
  2321
    return _this->SetWindowInputFocus(_this, window);
icculus@10026
  2322
}
icculus@10026
  2323
icculus@10026
  2324
icculus@10025
  2325
int
slouken@8582
  2326
SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
slouken@8582
  2327
                                            const Uint16 * green,
slouken@8582
  2328
                                            const Uint16 * blue)
slouken@8582
  2329
{
slouken@8582
  2330
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8582
  2331
slouken@8582
  2332
    if (!_this->SetWindowGammaRamp) {
slouken@8582
  2333
        return SDL_Unsupported();
slouken@8582
  2334
    }
slouken@8582
  2335
slouken@8582
  2336
    if (!window->gamma) {
slouken@8582
  2337
        if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
slouken@8582
  2338
            return -1;
slouken@8582
  2339
        }
icculus@9546
  2340
        SDL_assert(window->gamma != NULL);
slouken@8582
  2341
    }
slouken@8582
  2342
slouken@8582
  2343
    if (red) {
slouken@8582
  2344
        SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
slouken@8582
  2345
    }
slouken@8582
  2346
    if (green) {
slouken@8582
  2347
        SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
slouken@8582
  2348
    }
slouken@8582
  2349
    if (blue) {
slouken@8582
  2350
        SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
slouken@8582
  2351
    }
slouken@8582
  2352
    if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
slouken@8582
  2353
        return _this->SetWindowGammaRamp(_this, window, window->gamma);
slouken@8582
  2354
    } else {
slouken@8582
  2355
        return 0;
slouken@8582
  2356
    }
slouken@8582
  2357
}
slouken@8582
  2358
slouken@8582
  2359
int
slouken@8582
  2360
SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
slouken@8582
  2361
                                            Uint16 * green,
slouken@8582
  2362
                                            Uint16 * blue)
slouken@8582
  2363
{
slouken@8582
  2364
    CHECK_WINDOW_MAGIC(window, -1);
slouken@8582
  2365
slouken@8582
  2366
    if (!window->gamma) {
slouken@8582
  2367
        int i;
slouken@8582
  2368
slouken@8582
  2369
        window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
slouken@8582
  2370
        if (!window->gamma) {
slouken@8582
  2371
            return SDL_OutOfMemory();
slouken@8582
  2372
        }
slouken@8582
  2373
        window->saved_gamma = window->gamma + 3*256;
slouken@8582
  2374
slouken@8582
  2375
        if (_this->GetWindowGammaRamp) {
slouken@8582
  2376
            if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
slouken@8582
  2377
                return -1;
slouken@8582
  2378
            }
slouken@8582
  2379
        } else {
slouken@8582
  2380
            /* Create an identity gamma ramp */
slouken@8582
  2381
            for (i = 0; i < 256; ++i) {
slouken@8582
  2382
                Uint16 value = (Uint16)((i << 8) | i);
slouken@8582
  2383
slouken@8582
  2384
                window->gamma[0*256+i] = value;
slouken@8582
  2385
                window->gamma[1*256+i] = value;
slouken@8582
  2386
                window->gamma[2*256+i] = value;
slouken@8582
  2387
            }
slouken@8582
  2388
        }
slouken@8582
  2389
        SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
slouken@8582
  2390
    }
slouken@8582
  2391
slouken@8582
  2392
    if (red) {
slouken@8582
  2393
        SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
slouken@8582
  2394
    }
slouken@8582
  2395
    if (green) {
slouken@8582
  2396
        SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
slouken@8582
  2397
    }
slouken@8582
  2398
    if (blue) {
slouken@8582
  2399
        SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
slouken@8582
  2400
    }
slouken@8582
  2401
    return 0;
slouken@8582
  2402
}
slouken@8582
  2403
slouken@8582
  2404
void
slouken@8582
  2405
SDL_UpdateWindowGrab(SDL_Window * window)
slouken@8582
  2406
{
slouken@9745
  2407
    SDL_Window *grabbed_window;
slouken@9745
  2408
    SDL_bool grabbed;
slouken@9745
  2409
    if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
slouken@9745
  2410
         (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@9745
  2411
        grabbed = SDL_TRUE;
slouken@9745
  2412
    } else {
slouken@9745
  2413
        grabbed = SDL_FALSE;
slouken@9745
  2414
    }
slouken@9745
  2415
slouken@9745
  2416
    grabbed_window = _this->grabbed_window;
slouken@9745
  2417
    if (grabbed) {
slouken@9745
  2418
        if (grabbed_window && (grabbed_window != window)) {
slouken@9745
  2419
            /* stealing a grab from another window! */
slouken@9745
  2420
            grabbed_window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
slouken@9745
  2421
            if (_this->SetWindowGrab) {
icculus@9447
  2422
                _this->SetWindowGrab(_this, grabbed_window, SDL_FALSE);
icculus@9447
  2423
            }
icculus@9447
  2424
        }
slouken@9745
  2425
        _this->grabbed_window = window;
slouken@9745
  2426
    } else if (grabbed_window == window) {
slouken@9745
  2427
        _this->grabbed_window = NULL;  /* ungrabbing. */
slouken@9745
  2428
    }
slouken@9745
  2429
slouken@9745
  2430
    if (_this->SetWindowGrab) {
slouken@8582
  2431
        _this->SetWindowGrab(_this, window, grabbed);
slouken@8582
  2432
    }
slouken@8582
  2433
}
slouken@8582
  2434
slouken@8582
  2435
void
slouken@8582
  2436
SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
slouken@8582
  2437
{
slouken@8818
  2438
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2439
slouken@8582
  2440
    if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
slouken@8582
  2441
        return;
slouken@8582
  2442
    }
slouken@8582
  2443
    if (grabbed) {
slouken@8582
  2444
        window->flags |= SDL_WINDOW_INPUT_GRABBED;
slouken@8582
  2445
    } else {
slouken@8582
  2446
        window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
slouken@8582
  2447
    }
slouken@8582
  2448
    SDL_UpdateWindowGrab(window);
slouken@8582
  2449
}
slouken@8582
  2450
slouken@8582
  2451
SDL_bool
slouken@8582
  2452
SDL_GetWindowGrab(SDL_Window * window)
slouken@8582
  2453
{
slouken@8582
  2454
    CHECK_WINDOW_MAGIC(window, SDL_FALSE);
icculus@9447
  2455
    SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
icculus@9447
  2456
    return window == _this->grabbed_window;
icculus@9447
  2457
}
icculus@9447
  2458
icculus@9447
  2459
SDL_Window *
icculus@9447
  2460
SDL_GetGrabbedWindow(void)
icculus@9447
  2461
{
icculus@9447
  2462
    SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
icculus@9447
  2463
    return _this->grabbed_window;
slouken@8582
  2464
}
slouken@8582
  2465
slouken@8582
  2466
void
slouken@8582
  2467
SDL_OnWindowShown(SDL_Window * window)
slouken@8582
  2468
{
slouken@8582
  2469
    SDL_OnWindowRestored(window);
slouken@8582
  2470
}
slouken@8582
  2471
slouken@8582
  2472
void
slouken@8582
  2473
SDL_OnWindowHidden(SDL_Window * window)
slouken@8582
  2474
{
slouken@8582
  2475
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@8582
  2476
}
slouken@8582
  2477
slouken@8582
  2478
void
slouken@8582
  2479
SDL_OnWindowResized(SDL_Window * window)
slouken@8582
  2480
{
slouken@8582
  2481
    window->surface_valid = SDL_FALSE;
slouken@8582
  2482
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
slouken@8582
  2483
}
slouken@8582
  2484
slouken@8582
  2485
void
slouken@8582
  2486
SDL_OnWindowMinimized(SDL_Window * window)
slouken@8582
  2487
{
slouken@8582
  2488
    SDL_UpdateFullscreenMode(window, SDL_FALSE);
slouken@8582
  2489
}
slouken@8582
  2490
slouken@8582
  2491
void
slouken@8582
  2492
SDL_OnWindowRestored(SDL_Window * window)
slouken@8582
  2493
{
pgriffais@8683
  2494
    /*
pgriffais@8683
  2495
     * FIXME: Is this fine to just remove this, or should it be preserved just
pgriffais@8683
  2496
     * for the fullscreen case? In principle it seems like just hiding/showing
pgriffais@8683
  2497
     * windows shouldn't affect the stacking order; maybe the right fix is to
pgriffais@8683
  2498
     * re-decouple OnWindowShown and OnWindowRestored.
pgriffais@8683
  2499
     */
icculus@8684
  2500
    /*SDL_RaiseWindow(window);*/
slouken@8582
  2501
slouken@8582
  2502
    if (FULLSCREEN_VISIBLE(window)) {
slouken@8582
  2503
        SDL_UpdateFullscreenMode(window, SDL_TRUE);
slouken@8582
  2504
    }
slouken@8582
  2505
}
slouken@8582
  2506
slouken@8582
  2507
void
slouken@8582
  2508
SDL_OnWindowEnter(SDL_Window * window)
slouken@8582
  2509
{
slouken@8582
  2510
    if (_this->OnWindowEnter) {
slouken@8582
  2511
        _this->OnWindowEnter(_this, window);
slouken@8582
  2512
    }
slouken@8582
  2513
}
slouken@8582
  2514
slouken@8582
  2515
void
slouken@8582
  2516
SDL_OnWindowLeave(SDL_Window * window)
slouken@8582
  2517
{
slouken@8582
  2518
}
slouken@8582
  2519
slouken@8582
  2520
void
slouken@8582
  2521
SDL_OnWindowFocusGained(SDL_Window * window)
slouken@8582
  2522
{
slouken@8582
  2523
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@8582
  2524
slouken@8582
  2525
    if (window->gamma && _this->SetWindowGammaRamp) {
slouken@8582
  2526
        _this->SetWindowGammaRamp(_this, window, window->gamma);
slouken@8582
  2527
    }
slouken@8582
  2528
slouken@8582
  2529
    if (mouse && mouse->relative_mode) {
slouken@8582
  2530
        SDL_SetMouseFocus(window);
slouken@8582
  2531
        SDL_WarpMouseInWindow(window, window->w/2, window->h/2);
slouken@8582
  2532
    }
slouken@8582
  2533
slouken@8582
  2534
    SDL_UpdateWindowGrab(window);
slouken@8582
  2535
}
slouken@8582
  2536
slouken@8582
  2537
static SDL_bool
slouken@8582
  2538
ShouldMinimizeOnFocusLoss(SDL_Window * window)
slouken@8582
  2539
{
jorgen@8112
  2540
    if (!(window->flags & SDL_WINDOW_FULLSCREEN) || window->is_destroying) {
slouken@8582
  2541
        return SDL_FALSE;
slouken@8582
  2542
    }
slouken@8582
  2543
slouken@8582
  2544
#ifdef __MACOSX__
icculus@10781
  2545
    if (SDL_strcmp(_this->name, "cocoa") == 0) {  /* don't do this for X11, etc */
icculus@10781
  2546
        if (Cocoa_IsWindowInFullscreenSpace(window)) {
icculus@10781
  2547
            return SDL_FALSE;
icculus@10781
  2548
        }
slouken@8582
  2549
    }
slouken@8582
  2550
#endif
slouken@8582
  2551
slouken@10499
  2552
    return SDL_GetHintBoolean(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, SDL_TRUE);
slouken@8582
  2553
}
slouken@8582
  2554
slouken@8582
  2555
void
slouken@8582
  2556
SDL_OnWindowFocusLost(SDL_Window * window)
slouken@8582
  2557
{
slouken@8582
  2558
    if (window->gamma && _this->SetWindowGammaRamp) {
slouken@8582
  2559
        _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
slouken@8582
  2560
    }
slouken@8582
  2561
slouken@8582
  2562
    SDL_UpdateWindowGrab(window);
slouken@8582
  2563
slouken@8582
  2564
    if (ShouldMinimizeOnFocusLoss(window)) {
slouken@8582
  2565
        SDL_MinimizeWindow(window);
slouken@8582
  2566
    }
slouken@8582
  2567
}
slouken@8582
  2568
icculus@8783
  2569
/* !!! FIXME: is this different than SDL_GetKeyboardFocus()?
icculus@8783
  2570
   !!! FIXME:  Also, SDL_GetKeyboardFocus() is O(1), this isn't. */
slouken@8582
  2571
SDL_Window *
slouken@8582
  2572
SDL_GetFocusWindow(void)
slouken@8582
  2573
{
slouken@8582
  2574
    SDL_Window *window;
slouken@8582
  2575
slouken@8582
  2576
    if (!_this) {
slouken@8582
  2577
        return NULL;
slouken@8582
  2578
    }
slouken@8582
  2579
    for (window = _this->windows; window; window = window->next) {
slouken@8582
  2580
        if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
slouken@8582
  2581
            return window;
slouken@8582
  2582
        }
slouken@8582
  2583
    }
slouken@8582
  2584
    return NULL;
slouken@8582
  2585
}
slouken@8582
  2586
slouken@8582
  2587
void
slouken@8582
  2588
SDL_DestroyWindow(SDL_Window * window)
slouken@8582
  2589
{
slouken@8582
  2590
    SDL_VideoDisplay *display;
slouken@8582
  2591
slouken@8818
  2592
    CHECK_WINDOW_MAGIC(window,);
slouken@8582
  2593
jorgen@8112
  2594
    window->is_destroying = SDL_TRUE;
jorgen@8112
  2595
slouken@8582
  2596
    /* Restore video mode, etc. */
slouken@8582
  2597
    SDL_HideWindow(window);
slouken@8582
  2598
slouken@8582
  2599
    /* Make sure this window no longer has focus */
slouken@8582
  2600
    if (SDL_GetKeyboardFocus() == window) {
slouken@8582
  2601
        SDL_SetKeyboardFocus(NULL);
slouken@8582
  2602
    }
slouken@8582
  2603
    if (SDL_GetMouseFocus() == window) {
slouken@8582
  2604
        SDL_SetMouseFocus(NULL);
slouken@8582
  2605
    }
slouken@8582
  2606
slouken@8582
  2607
    /* make no context current if this is the current context window. */
slouken@8582
  2608
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@8582
  2609
        if (_this->current_glwin == window) {
slouken@8582
  2610
            SDL_GL_MakeCurrent(window, NULL);
slouken@8582
  2611
        }
slouken@8582
  2612
    }
slouken@8582
  2613
slouken@8582
  2614
    if (window->surface) {
slouken@8582
  2615
        window->surface->flags &= ~SDL_DONTFREE;
slouken@8582
  2616
        SDL_FreeSurface(window->surface);
slouken@8582
  2617
    }
slouken@8582
  2618
    if (_this->DestroyWindowFramebuffer) {
slouken@8582
  2619
        _this->DestroyWindowFramebuffer(_this, window);
slouken@8582
  2620
    }
slouken@8582
  2621
    if (_this->DestroyWindow) {
slouken@8582
  2622
        _this->DestroyWindow(_this, window);
slouken@8582
  2623
    }
slouken@8582
  2624
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@8582
  2625
        SDL_GL_UnloadLibrary();
slouken@8582
  2626
    }
slouken@8582
  2627
slouken@8582
  2628
    display = SDL_GetDisplayForWindow(window);
slouken@8582
  2629
    if (display->fullscreen_window == window) {
slouken@8582
  2630
        display->fullscreen_window = NULL;
slouken@8582
  2631
    }
slouken@8582
  2632
slouken@8582
  2633
    /* Now invalidate magic */
slouken@8582
  2634
    window->magic = NULL;
slouken@8582
  2635
slouken@8582
  2636
    /* Free memory associated with the window */
slouken@8582
  2637
    SDL_free(window->title);
slouken@8582
  2638
    SDL_FreeSurface(window->icon);
slouken@8582
  2639
    SDL_free(window->gamma);
slouken@8582
  2640
    while (window->data) {
slouken@8582
  2641
        SDL_WindowUserData *data = window->data;
slouken@8582
  2642
slouken@8582
  2643
        window->data = data->next;
slouken@8582
  2644
        SDL_free(data->name);
slouken@8582
  2645
        SDL_free(data);
slouken@8582
  2646
    }
slouken@8582
  2647
slouken@8582
  2648
    /* Unlink the window from the list */
slouken@8582
  2649
    if (window->next) {
slouken@8582
  2650
        window->next->prev = window->prev;
slouken@8582
  2651
    }
slouken@8582
  2652
    if (window->prev) {
slouken@8582
  2653
        window->prev->next = window->next;
slouken@8582
  2654
    } else {
slouken@8582
  2655
        _this->windows = window->next;
slouken@8582
  2656
    }
slouken@8582
  2657
slouken@8582
  2658
    SDL_free(window);
slouken@8582
  2659
}
slouken@8582
  2660
slouken@8582
  2661
SDL_bool
slouken@8582
  2662
SDL_IsScreenSaverEnabled()
slouken@8582
  2663
{
slouken@8582
  2664
    if (!_this) {
slouken@8582
  2665
        return SDL_TRUE;
slouken@8582
  2666
    }
slouken@8582
  2667
    return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
slouken@8582
  2668
}
slouken@8582
  2669
slouken@8582
  2670
void
slouken@8582
  2671
SDL_EnableScreenSaver()
slouken@8582
  2672
{
slouken@8582
  2673
    if (!_this) {
slouken@8582
  2674
        return;
slouken@8582
  2675
    }
slouken@8582
  2676
    if (!_this->suspend_screensaver) {
slouken@8582
  2677
        return;
slouken@8582
  2678
    }
slouken@8582
  2679
    _this->suspend_screensaver = SDL_FALSE;
slouken@8582
  2680
    if (_this->SuspendScreenSaver) {
slouken@8582
  2681
        _this->SuspendScreenSaver(_this);
slouken@8582
  2682
    }
slouken@8582
  2683
}
slouken@8582
  2684
slouken@8582
  2685
void
slouken@8582
  2686
SDL_DisableScreenSaver()
slouken@8582
  2687
{
slouken@8582
  2688
    if (!_this) {
slouken@8582
  2689
        return;
slouken@8582
  2690
    }
slouken@8582
  2691
    if (_this->suspend_screensaver) {
slouken@8582
  2692
        return;
slouken@8582
  2693
    }
slouken@8582
  2694
    _this->suspend_screensaver = SDL_TRUE;
slouken@8582
  2695
    if (_this->SuspendScreenSaver) {
slouken@8582
  2696
        _this->SuspendScreenSaver(_this);
slouken@8582
  2697
    }
slouken@8582
  2698
}
slouken@8582
  2699
slouken@8582
  2700
void
slouken@8582
  2701
SDL_VideoQuit(void)
slouken@8582
  2702
{
slouken@8582
  2703
    int i, j;
slouken@8582
  2704
slouken@8582
  2705
    if (!_this) {
slouken@8582
  2706
        return;
slouken@8582
  2707
    }
slouken@8582
  2708
slouken@8582
  2709
    /* Halt event processing before doing anything else */
slouken@8582
  2710
    SDL_TouchQuit();
slouken@8582
  2711
    SDL_MouseQuit();
slouken@8582
  2712
    SDL_KeyboardQuit();
slouken@8582
  2713
    SDL_QuitSubSystem(SDL_INIT_EVENTS);
slouken@8582
  2714
slouken@8582
  2715
    SDL_EnableScreenSaver();
slouken@8582
  2716
slouken@8582
  2717
    /* Clean up the system video */
slouken@8582
  2718
    while (_this->windows) {
slouken@8582
  2719
        SDL_DestroyWindow(_this->windows);
slouken@8582
  2720
    }
slouken@8582
  2721
    _this->VideoQuit(_this);
slouken@8582
  2722
slouken@8582
  2723
    for (i = 0; i < _this->num_displays; ++i) {
slouken@8582
  2724
        SDL_VideoDisplay *display = &_this->displays[i];
slouken@8582
  2725
        for (j = display->num_display_modes; j--;) {
slouken@8582
  2726
            SDL_free(display->display_modes[j].driverdata);
slouken@8582
  2727
            display->display_modes[j].driverdata = NULL;
slouken@8582
  2728
        }
slouken@8582
  2729
        SDL_free(display->display_modes);
slouken@8582
  2730
        display->display_modes = NULL;
slouken@8582
  2731
        SDL_free(display->desktop_mode.driverdata);
slouken@8582
  2732
        display->desktop_mode.driverdata = NULL;
slouken@8582
  2733
        SDL_free(display->driverdata);
slouken@8582
  2734
        display->driverdata = NULL;
slouken@8582
  2735
    }
slouken@8582
  2736
    if (_this->displays) {
slouken@8582
  2737
        for (i = 0; i < _this->num_displays; ++i) {
slouken@8582
  2738
            SDL_free(_this->displays[i].name);
slouken@8582
  2739
        }
slouken@8582
  2740
        SDL_free(_this->displays);
slouken@8582
  2741
        _this->displays = NULL;
slouken@8582
  2742
        _this->num_displays = 0;
slouken@8582
  2743
    }
slouken@8582
  2744
    SDL_free(_this->clipboard_text);
slouken@8582
  2745
    _this->clipboard_text = NULL;
slouken@8582
  2746
    _this->free(_this);
slouken@8582
  2747
    _this = NULL;