src/video/SDL_video.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 23 Dec 2013 17:37:22 -0800
changeset 8071 1ac2db4abe11
parent 8062 4fc5f66d63cc
child 8072 9d8865351afd
permissions -rw-r--r--
Added a relative mouse mode that uses mouse warping instead of raw input.
To enable this, set the environment variable SDL_MOUSE_RELATIVE_MODE_WARP to "1"

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