src/video/directfb/SDL_DirectFB_window.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 11 Jun 2017 00:50:26 -0400
changeset 11088 69452f9839d5
parent 10945 1300a3135d61
child 11092 9c9b7b7e46e1
permissions -rw-r--r--
syswm: prevent buffer overflow if SDL and app have different config headers.

This only affects Wayland and DirectFB, as a Unix system generally has X11
support. Other platforms also have different sizes for the C union in
question, but are likely the only target for that platform, etc.

Apps that might run on Wayland or DirectFB will need to be compiled against
new headers from an official 2.0.6 release, or be prepared to force the x11
target, or not use SDL_GetWindowWMInfo().

Fixes Bugzilla #3428.
slouken@2737
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@2737
     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@2737
     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@2737
    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@2737
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@6044
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_DIRECTFB
slouken@2737
    24
slouken@2737
    25
#include "SDL_DirectFB_video.h"
slouken@5199
    26
#include "SDL_DirectFB_modes.h"
slouken@5199
    27
#include "SDL_DirectFB_window.h"
slouken@5199
    28
#include "SDL_DirectFB_shape.h"
slouken@5199
    29
slouken@4636
    30
#if SDL_DIRECTFB_OPENGL
slouken@4636
    31
#include "SDL_DirectFB_opengl.h"
slouken@4636
    32
#endif
slouken@2737
    33
slouken@5199
    34
#include "SDL_syswm.h"
slouken@5199
    35
slouken@5199
    36
#include "../SDL_pixels_c.h"
couriersud@3023
    37
slouken@2737
    38
int
slouken@2737
    39
DirectFB_CreateWindow(_THIS, SDL_Window * window)
slouken@2737
    40
{
slouken@2737
    41
    SDL_DFB_DEVICEDATA(_this);
slouken@5199
    42
    SDL_DFB_DISPLAYDATA(window);
couriersud@3023
    43
    DFB_WindowData *windata = NULL;
slouken@2737
    44
    DFBWindowOptions wopts;
slouken@2737
    45
    DFBWindowDescription desc;
slouken@4636
    46
    int x, y;
slouken@5199
    47
    int bshaped = 0;
slouken@2737
    48
slouken@5199
    49
    SDL_DFB_ALLOC_CLEAR(window->driverdata, sizeof(DFB_WindowData));
slouken@6986
    50
    SDL_memset(&desc, 0, sizeof(DFBWindowDescription));
slouken@2737
    51
    windata = (DFB_WindowData *) window->driverdata;
slouken@2737
    52
couriersud@3023
    53
    windata->is_managed = devdata->has_own_wm;
slouken@5199
    54
#if 1
couriersud@3023
    55
    SDL_DFB_CHECKERR(devdata->dfb->SetCooperativeLevel(devdata->dfb,
couriersud@3023
    56
                                                       DFSCL_NORMAL));
couriersud@3023
    57
    SDL_DFB_CHECKERR(dispdata->layer->SetCooperativeLevel(dispdata->layer,
couriersud@3023
    58
                                                          DLSCL_ADMINISTRATIVE));
slouken@5199
    59
#endif
slouken@7191
    60
    /* FIXME ... ughh, ugly */
slouken@7191
    61
    if (window->x == -1000 && window->y == -1000)
slouken@7191
    62
        bshaped = 1;
slouken@7191
    63
slouken@2737
    64
    /* Fill the window description. */
slouken@5495
    65
    x = window->x;
slouken@5495
    66
    y = window->y;
slouken@2737
    67
slouken@4636
    68
    DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
slouken@2737
    69
couriersud@3023
    70
    /* Create Window */
slouken@7191
    71
    desc.caps = 0;
couriersud@3023
    72
    desc.flags =
slouken@5199
    73
        DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY | DWDESC_SURFACE_CAPS;
slouken@5199
    74
slouken@5199
    75
    if (bshaped) {
slouken@7191
    76
        desc.flags |= DWDESC_CAPS;
slouken@7191
    77
        desc.caps |= DWCAPS_ALPHACHANNEL;
slouken@5199
    78
    }
slouken@5199
    79
    else
slouken@5199
    80
    {
slouken@7191
    81
        desc.flags |= DWDESC_PIXELFORMAT;
slouken@5199
    82
    }
slouken@5199
    83
slouken@5199
    84
    if (!(window->flags & SDL_WINDOW_BORDERLESS))
slouken@7191
    85
        desc.caps |= DWCAPS_NODECORATION;
slouken@5199
    86
slouken@2737
    87
    desc.posx = x;
slouken@2737
    88
    desc.posy = y;
couriersud@3023
    89
    desc.width = windata->size.w;
couriersud@3023
    90
    desc.height = windata->size.h;
slouken@2737
    91
    desc.pixelformat = dispdata->pixelformat;
slouken@2737
    92
    desc.surface_caps = DSCAPS_PREMULTIPLIED;
slouken@9129
    93
#if DIRECTFB_MAJOR_VERSION == 1 && DIRECTFB_MINOR_VERSION >= 6
slouken@6986
    94
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@6986
    95
        desc.surface_caps |= DSCAPS_GL;
slouken@6986
    96
    }
slouken@6986
    97
#endif
slouken@6986
    98
slouken@2737
    99
    /* Create the window. */
couriersud@3023
   100
    SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
slouken@5199
   101
                                                   &windata->dfbwin));
slouken@2737
   102
couriersud@3023
   103
    /* Set Options */
slouken@5199
   104
    SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
slouken@2737
   105
slouken@5199
   106
    /* explicit rescaling of surface */
slouken@5199
   107
    wopts |= DWOP_SCALE;
slouken@5199
   108
    if (window->flags & SDL_WINDOW_RESIZABLE) {
slouken@5199
   109
        wopts &= ~DWOP_KEEP_SIZE;
slouken@5199
   110
    }
slouken@5199
   111
    else {
slouken@2737
   112
        wopts |= DWOP_KEEP_SIZE;
slouken@5199
   113
    }
slouken@2737
   114
couriersud@3023
   115
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@2737
   116
        wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
slouken@5199
   117
        SDL_DFB_CHECK(windata->dfbwin->SetStackingClass(windata->dfbwin, DWSC_UPPER));
couriersud@3023
   118
    }
slouken@7191
   119
slouken@5199
   120
    if (bshaped) {
slouken@5199
   121
        wopts |= DWOP_SHAPED | DWOP_ALPHACHANNEL;
slouken@5199
   122
        wopts &= ~DWOP_OPAQUE_REGION;
slouken@5199
   123
    }
slouken@5199
   124
slouken@5199
   125
    SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
slouken@2737
   126
couriersud@3023
   127
    /* See what we got */
slouken@5199
   128
    SDL_DFB_CHECK(DirectFB_WM_GetClientSize
slouken@3040
   129
                     (_this, window, &window->w, &window->h));
couriersud@3023
   130
slouken@2737
   131
    /* Get the window's surface. */
slouken@5199
   132
    SDL_DFB_CHECKERR(windata->dfbwin->GetSurface(windata->dfbwin,
couriersud@3023
   133
                                                 &windata->window_surface));
slouken@5199
   134
couriersud@3023
   135
    /* And get a subsurface for rendering */
couriersud@3023
   136
    SDL_DFB_CHECKERR(windata->window_surface->
couriersud@3023
   137
                     GetSubSurface(windata->window_surface, &windata->client,
couriersud@3023
   138
                                   &windata->surface));
couriersud@3023
   139
slouken@5199
   140
    SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0xFF));
slouken@2737
   141
couriersud@3023
   142
    /* Create Eventbuffer */
slouken@5199
   143
slouken@5199
   144
    SDL_DFB_CHECKERR(windata->dfbwin->CreateEventBuffer(windata->dfbwin,
slouken@3040
   145
                                                        &windata->
slouken@3040
   146
                                                        eventbuffer));
slouken@5199
   147
    SDL_DFB_CHECKERR(windata->dfbwin->
slouken@5199
   148
                     EnableEvents(windata->dfbwin, DWET_ALL));
couriersud@3023
   149
couriersud@3023
   150
    /* Create a font */
couriersud@3023
   151
    /* FIXME: once during Video_Init */
slouken@4636
   152
    windata->font = NULL;
couriersud@3023
   153
slouken@2737
   154
    /* Make it the top most window. */
slouken@5199
   155
    SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
slouken@2737
   156
slouken@2737
   157
    /* remember parent */
gabomdq@7678
   158
    /* windata->sdlwin = window; */
slouken@2737
   159
slouken@2737
   160
    /* Add to list ... */
slouken@2737
   161
slouken@2737
   162
    windata->next = devdata->firstwin;
slouken@2737
   163
    windata->opacity = 0xFF;
slouken@5199
   164
    devdata->firstwin = window;
slouken@2737
   165
couriersud@3023
   166
    /* Draw Frame */
slouken@4636
   167
    DirectFB_WM_RedrawLayout(_this, window);
couriersud@3023
   168
slouken@2737
   169
    return 0;
slouken@2737
   170
  error:
slouken@7191
   171
    SDL_DFB_RELEASE(windata->surface);
slouken@5199
   172
    SDL_DFB_RELEASE(windata->dfbwin);
slouken@2737
   173
    return -1;
slouken@2737
   174
}
slouken@2737
   175
slouken@2737
   176
int
slouken@2737
   177
DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@2737
   178
{
icculus@7037
   179
    return SDL_Unsupported();
slouken@2737
   180
}
slouken@2737
   181
slouken@2737
   182
void
slouken@2737
   183
DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
slouken@2737
   184
{
couriersud@3023
   185
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   186
couriersud@3023
   187
    if (windata->is_managed) {
couriersud@3023
   188
        windata->wm_needs_redraw = 1;
slouken@4636
   189
        DirectFB_WM_RedrawLayout(_this, window);
icculus@7037
   190
    } else {
couriersud@3023
   191
        SDL_Unsupported();
icculus@7037
   192
    }
couriersud@3023
   193
}
couriersud@3023
   194
couriersud@3023
   195
void
couriersud@3023
   196
DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
couriersud@3023
   197
{
couriersud@3023
   198
    SDL_DFB_DEVICEDATA(_this);
couriersud@3023
   199
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   200
    SDL_Surface *surface = NULL;
couriersud@3023
   201
couriersud@3023
   202
    if (icon) {
couriersud@3023
   203
        SDL_PixelFormat format;
couriersud@3023
   204
        DFBSurfaceDescription dsc;
couriersud@3023
   205
        Uint32 *dest;
couriersud@3023
   206
        Uint32 *p;
couriersud@3023
   207
        int pitch, i;
couriersud@3023
   208
couriersud@3023
   209
        /* Convert the icon to ARGB for modern window managers */
slouken@5288
   210
        SDL_InitFormat(&format, SDL_PIXELFORMAT_ARGB8888);
couriersud@3023
   211
        surface = SDL_ConvertSurface(icon, &format, 0);
couriersud@3023
   212
        if (!surface) {
couriersud@3023
   213
            return;
couriersud@3023
   214
        }
couriersud@3023
   215
        dsc.flags =
couriersud@3023
   216
            DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
couriersud@3023
   217
        dsc.caps = DSCAPS_VIDEOONLY;
couriersud@3023
   218
        dsc.width = surface->w;
couriersud@3023
   219
        dsc.height = surface->h;
couriersud@3023
   220
        dsc.pixelformat = DSPF_ARGB;
couriersud@3023
   221
couriersud@3023
   222
        SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
couriersud@3023
   223
                                                     &windata->icon));
couriersud@3023
   224
couriersud@3023
   225
        SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
couriersud@3023
   226
                                             (void *) &dest, &pitch));
couriersud@3023
   227
couriersud@3023
   228
        p = surface->pixels;
couriersud@3023
   229
        for (i = 0; i < surface->h; i++)
couriersud@3023
   230
            memcpy((char *) dest + i * pitch,
couriersud@3023
   231
                   (char *) p + i * surface->pitch, 4 * surface->w);
couriersud@3023
   232
slouken@4636
   233
        SDL_DFB_CHECK(windata->icon->Unlock(windata->icon));
couriersud@3023
   234
        SDL_FreeSurface(surface);
couriersud@3023
   235
    } else {
couriersud@3023
   236
        SDL_DFB_RELEASE(windata->icon);
couriersud@3023
   237
    }
couriersud@3023
   238
    return;
couriersud@3023
   239
  error:
slouken@7720
   240
    SDL_FreeSurface(surface);
couriersud@3023
   241
    SDL_DFB_RELEASE(windata->icon);
couriersud@3023
   242
    return;
slouken@2737
   243
}
slouken@2737
   244
slouken@2737
   245
void
slouken@2737
   246
DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
slouken@2737
   247
{
slouken@2737
   248
    SDL_DFB_WINDOWDATA(window);
slouken@2737
   249
    int x, y;
slouken@2737
   250
slouken@5478
   251
    x = window->x;
slouken@5478
   252
    y = window->y;
slouken@2737
   253
slouken@4636
   254
    DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
slouken@5199
   255
    SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, x, y));
slouken@2737
   256
}
slouken@2737
   257
slouken@2737
   258
void
slouken@2737
   259
DirectFB_SetWindowSize(_THIS, SDL_Window * window)
slouken@2737
   260
{
couriersud@3023
   261
    SDL_DFB_WINDOWDATA(window);
slouken@2737
   262
slouken@5199
   263
    if(SDL_IsShapedWindow(window))
slouken@5199
   264
        DirectFB_ResizeWindowShape(window);
slouken@5199
   265
slouken@2737
   266
    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@2737
   267
        int cw;
slouken@2737
   268
        int ch;
slouken@2737
   269
slouken@2737
   270
        /* Make sure all events are disabled for this operation ! */
slouken@5199
   271
        SDL_DFB_CHECKERR(windata->dfbwin->DisableEvents(windata->dfbwin,
couriersud@3023
   272
                                                        DWET_ALL));
couriersud@3023
   273
        SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
slouken@2737
   274
couriersud@3023
   275
        if (cw != window->w || ch != window->h) {
couriersud@3023
   276
slouken@7191
   277
            DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
slouken@5199
   278
            SDL_DFB_CHECKERR(windata->dfbwin->Resize(windata->dfbwin,
couriersud@3023
   279
                                                     windata->size.w,
couriersud@3023
   280
                                                     windata->size.h));
couriersud@3023
   281
        }
couriersud@3023
   282
slouken@4636
   283
        SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
slouken@4636
   284
                     (_this, window, &window->w, &window->h));
slouken@5199
   285
        DirectFB_AdjustWindowSurface(window);
slouken@4636
   286
slouken@5199
   287
        SDL_DFB_CHECKERR(windata->dfbwin->EnableEvents(windata->dfbwin,
couriersud@3023
   288
                                                       DWET_ALL));
couriersud@3023
   289
slouken@2737
   290
    }
slouken@2737
   291
    return;
slouken@2737
   292
  error:
slouken@5199
   293
    SDL_DFB_CHECK(windata->dfbwin->EnableEvents(windata->dfbwin, DWET_ALL));
slouken@2737
   294
    return;
slouken@2737
   295
}
slouken@2737
   296
slouken@2737
   297
void
slouken@2737
   298
DirectFB_ShowWindow(_THIS, SDL_Window * window)
slouken@2737
   299
{
slouken@2737
   300
    SDL_DFB_WINDOWDATA(window);
slouken@2737
   301
slouken@5199
   302
    SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, windata->opacity));
slouken@2737
   303
slouken@2737
   304
}
slouken@2737
   305
slouken@2737
   306
void
slouken@2737
   307
DirectFB_HideWindow(_THIS, SDL_Window * window)
slouken@2737
   308
{
slouken@2737
   309
    SDL_DFB_WINDOWDATA(window);
slouken@2737
   310
slouken@5199
   311
    SDL_DFB_CHECK(windata->dfbwin->GetOpacity(windata->dfbwin, &windata->opacity));
slouken@5199
   312
    SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0));
slouken@2737
   313
}
slouken@2737
   314
slouken@2737
   315
void
slouken@2737
   316
DirectFB_RaiseWindow(_THIS, SDL_Window * window)
slouken@2737
   317
{
slouken@2737
   318
    SDL_DFB_WINDOWDATA(window);
slouken@2737
   319
slouken@5199
   320
    SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
slouken@5199
   321
    SDL_DFB_CHECK(windata->dfbwin->RequestFocus(windata->dfbwin));
slouken@2737
   322
}
slouken@2737
   323
slouken@2737
   324
void
slouken@2737
   325
DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
slouken@2737
   326
{
couriersud@3023
   327
    SDL_DFB_WINDOWDATA(window);
slouken@5246
   328
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5199
   329
    DFBWindowOptions wopts;
slouken@2737
   330
slouken@5199
   331
    SDL_DFB_CHECK(windata->dfbwin->GetPosition(windata->dfbwin,
slouken@5199
   332
                                 &windata->restore.x, &windata->restore.y));
slouken@5199
   333
    SDL_DFB_CHECK(windata->dfbwin->GetSize(windata->dfbwin, &windata->restore.w,
slouken@5199
   334
                             &windata->restore.h));
slouken@5199
   335
slouken@5199
   336
    DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
slouken@5199
   337
slouken@5199
   338
    SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, 0, 0));
slouken@5199
   339
    SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin,
slouken@5199
   340
                            display->current_mode.w, display->current_mode.h));
slouken@5199
   341
slouken@5199
   342
    /* Set Options */
slouken@5199
   343
    SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
slouken@5199
   344
    wopts |= DWOP_KEEP_SIZE | DWOP_KEEP_POSITION;
slouken@5199
   345
    SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
slouken@2737
   346
}
slouken@2737
   347
slouken@2737
   348
void
slouken@2737
   349
DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
slouken@2737
   350
{
slouken@2737
   351
    /* FIXME: Size to 32x32 ? */
slouken@2737
   352
slouken@2737
   353
    SDL_Unsupported();
slouken@2737
   354
}
slouken@2737
   355
slouken@2737
   356
void
slouken@2737
   357
DirectFB_RestoreWindow(_THIS, SDL_Window * window)
slouken@2737
   358
{
couriersud@3023
   359
    SDL_DFB_WINDOWDATA(window);
slouken@5199
   360
    DFBWindowOptions wopts;
couriersud@3023
   361
slouken@5199
   362
    /* Set Options */
slouken@5199
   363
    SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
slouken@5199
   364
    wopts &= ~(DWOP_KEEP_SIZE | DWOP_KEEP_POSITION);
slouken@5199
   365
    SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
slouken@5199
   366
slouken@5199
   367
    /* Window layout */
slouken@5199
   368
    DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED),
slouken@7191
   369
        windata->restore.w, windata->restore.h);
slouken@5199
   370
    SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin, windata->restore.w,
slouken@5199
   371
                            windata->restore.h));
slouken@5199
   372
    SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, windata->restore.x,
slouken@5199
   373
                            windata->restore.y));
slouken@5199
   374
slouken@5199
   375
    if (!(window->flags & SDL_WINDOW_RESIZABLE))
slouken@5199
   376
        wopts |= DWOP_KEEP_SIZE;
slouken@5199
   377
slouken@5199
   378
    if (window->flags & SDL_WINDOW_FULLSCREEN)
slouken@5199
   379
        wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_SIZE;
slouken@5199
   380
    SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
slouken@5199
   381
slouken@5199
   382
slouken@2737
   383
}
slouken@2737
   384
slouken@2737
   385
void
slouken@6986
   386
DirectFB_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
slouken@2737
   387
{
slouken@4636
   388
    SDL_DFB_DEVICEDATA(_this);
slouken@2737
   389
    SDL_DFB_WINDOWDATA(window);
slouken@4636
   390
    DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
slouken@2737
   391
couriersud@3023
   392
    if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
slouken@4636
   393
        if (gwindata != NULL)
slouken@4636
   394
        {
slouken@7191
   395
            SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
slouken@7191
   396
            SDL_DFB_CHECK(gwindata->dfbwin->UngrabKeyboard(gwindata->dfbwin));
slouken@4636
   397
        }
slouken@5199
   398
        SDL_DFB_CHECK(windata->dfbwin->GrabPointer(windata->dfbwin));
slouken@5199
   399
        SDL_DFB_CHECK(windata->dfbwin->GrabKeyboard(windata->dfbwin));
slouken@4636
   400
        devdata->grabbed_window = window;
slouken@2737
   401
    } else {
slouken@5199
   402
        SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
slouken@5199
   403
        SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
slouken@4636
   404
        devdata->grabbed_window = NULL;
slouken@2737
   405
    }
slouken@2737
   406
}
slouken@2737
   407
slouken@2737
   408
void
slouken@2737
   409
DirectFB_DestroyWindow(_THIS, SDL_Window * window)
slouken@2737
   410
{
slouken@2737
   411
    SDL_DFB_DEVICEDATA(_this);
slouken@2737
   412
    SDL_DFB_WINDOWDATA(window);
slouken@2737
   413
    DFB_WindowData *p;
slouken@2737
   414
slouken@4636
   415
    /* Some cleanups */
slouken@5199
   416
    SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
slouken@5199
   417
    SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
slouken@2737
   418
slouken@4636
   419
#if SDL_DIRECTFB_OPENGL
slouken@7191
   420
    DirectFB_GL_DestroyWindowContexts(_this, window);
slouken@4636
   421
#endif
couriersud@3023
   422
slouken@7191
   423
    if (window->shaper)
slouken@7191
   424
    {
slouken@7191
   425
        SDL_ShapeData *data = window->shaper->driverdata;
slouken@7191
   426
        SDL_DFB_CHECK(data->surface->ReleaseSource(data->surface));
slouken@7191
   427
        SDL_DFB_RELEASE(data->surface);
slouken@7191
   428
        SDL_DFB_FREE(data);
slouken@7191
   429
        SDL_DFB_FREE(window->shaper);
slouken@7191
   430
    }
slouken@5199
   431
slouken@4636
   432
    SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, NULL));
slouken@4636
   433
    SDL_DFB_CHECK(windata->surface->ReleaseSource(windata->surface));
slouken@4636
   434
    SDL_DFB_CHECK(windata->window_surface->ReleaseSource(windata->window_surface));
slouken@7191
   435
    SDL_DFB_RELEASE(windata->icon);
slouken@4636
   436
    SDL_DFB_RELEASE(windata->font);
slouken@2737
   437
    SDL_DFB_RELEASE(windata->eventbuffer);
slouken@2737
   438
    SDL_DFB_RELEASE(windata->surface);
couriersud@3023
   439
    SDL_DFB_RELEASE(windata->window_surface);
couriersud@3023
   440
slouken@5199
   441
    SDL_DFB_RELEASE(windata->dfbwin);
slouken@2737
   442
slouken@2737
   443
    /* Remove from list ... */
slouken@2737
   444
slouken@5199
   445
    p = devdata->firstwin->driverdata;
slouken@5199
   446
slouken@5199
   447
    while (p && p->next != window)
slouken@5199
   448
        p = (p->next ? p->next->driverdata : NULL);
slouken@2737
   449
    if (p)
slouken@2737
   450
        p->next = windata->next;
slouken@2737
   451
    else
slouken@2737
   452
        devdata->firstwin = windata->next;
slouken@2737
   453
    SDL_free(windata);
slouken@2737
   454
    return;
slouken@2737
   455
}
slouken@2737
   456
slouken@2737
   457
SDL_bool
slouken@2737
   458
DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
slouken@2737
   459
                         struct SDL_SysWMinfo * info)
slouken@2737
   460
{
icculus@11088
   461
    const Uint32 version = ((((Uint32) info->version.major) * 1000000) +
icculus@11088
   462
                            (((Uint32) info->version.minor) * 10000) +
icculus@11088
   463
                            (((Uint32) info->version.patch)));
icculus@11088
   464
slouken@5199
   465
    SDL_DFB_DEVICEDATA(_this);
slouken@5199
   466
    SDL_DFB_WINDOWDATA(window);
slouken@5199
   467
icculus@11088
   468
    /* Before 2.0.6, it was possible to build an SDL with DirectFB support
icculus@11088
   469
       (SDL_SysWMinfo will be large enough to hold DirectFB info), but build
icculus@11088
   470
       your app against SDL headers that didn't have DirectFB support
icculus@11088
   471
       (SDL_SysWMinfo could be smaller than Wayland needs. This would lead
icculus@11088
   472
       to an app properly using SDL_GetWindowWMInfo() but we'd accidentally
icculus@11088
   473
       overflow memory on the stack or heap. To protect against this, we've
icculus@11088
   474
       padded out the struct unconditionally in the headers and DirectFB will
icculus@11088
   475
       just return an error for older apps using this function. Those apps
icculus@11088
   476
       will need to be recompiled against newer headers or not use DirectFB,
icculus@11088
   477
       maybe by forcing SDL_VIDEODRIVER=x11. */
icculus@11088
   478
    if (version < 2000006) {
icculus@11088
   479
        info->subsystem = SDL_SYSWM_UNKNOWN;
icculus@11088
   480
        return SDL_FALSE;
icculus@11088
   481
    }
icculus@11088
   482
slouken@5199
   483
    if (info->version.major == SDL_MAJOR_VERSION &&
slouken@5199
   484
        info->version.minor == SDL_MINOR_VERSION) {
slouken@5199
   485
        info->subsystem = SDL_SYSWM_DIRECTFB;
slouken@5199
   486
        info->info.dfb.dfb = devdata->dfb;
slouken@5199
   487
        info->info.dfb.window = windata->dfbwin;
slouken@5199
   488
        info->info.dfb.surface = windata->surface;
slouken@5199
   489
        return SDL_TRUE;
slouken@5199
   490
    } else {
philipp@10945
   491
        SDL_SetError("Application not compiled with SDL %d.%d",
slouken@5199
   492
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@5199
   493
        return SDL_FALSE;
slouken@5199
   494
    }
slouken@2737
   495
}
couriersud@3023
   496
slouken@5199
   497
void
slouken@5199
   498
DirectFB_AdjustWindowSurface(SDL_Window * window)
couriersud@3023
   499
{
couriersud@3023
   500
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   501
    int adjust = windata->wm_needs_redraw;
couriersud@3023
   502
    int cw, ch;
couriersud@3023
   503
slouken@4636
   504
    DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
couriersud@3023
   505
couriersud@3023
   506
    SDL_DFB_CHECKERR(windata->
couriersud@3023
   507
                     window_surface->GetSize(windata->window_surface, &cw,
couriersud@3023
   508
                                             &ch));
couriersud@3023
   509
    if (cw != windata->size.w || ch != windata->size.h) {
couriersud@3023
   510
        adjust = 1;
couriersud@3023
   511
    }
couriersud@3023
   512
couriersud@3023
   513
    if (adjust) {
slouken@4636
   514
#if SDL_DIRECTFB_OPENGL
slouken@7191
   515
        DirectFB_GL_FreeWindowContexts(SDL_GetVideoDevice(), window);
slouken@4636
   516
#endif
slouken@4636
   517
slouken@5199
   518
#if (DFB_VERSION_ATLEAST(1,2,1))
slouken@5199
   519
        SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
couriersud@3023
   520
                                                        windata->size.w,
couriersud@3023
   521
                                                        windata->size.h));
slouken@3040
   522
        SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
couriersud@3023
   523
                                                          windata->
couriersud@3023
   524
                                                          window_surface,
couriersud@3023
   525
                                                          &windata->client));
couriersud@3037
   526
#else
slouken@3040
   527
        DFBWindowOptions opts;
couriersud@3039
   528
slouken@5199
   529
        SDL_DFB_CHECKERR(windata->dfbwin->GetOptions(windata->dfbwin, &opts));
slouken@3040
   530
        /* recreate subsurface */
slouken@3040
   531
        SDL_DFB_RELEASE(windata->surface);
slouken@3040
   532
slouken@3040
   533
        if (opts & DWOP_SCALE)
slouken@5199
   534
            SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
slouken@3040
   535
                                                            windata->size.w,
slouken@3040
   536
                                                            windata->size.h));
slouken@3040
   537
        SDL_DFB_CHECKERR(windata->window_surface->
slouken@3040
   538
                         GetSubSurface(windata->window_surface,
slouken@3040
   539
                                       &windata->client, &windata->surface));
couriersud@3037
   540
#endif
slouken@5246
   541
        DirectFB_WM_RedrawLayout(SDL_GetVideoDevice(), window);
slouken@7191
   542
slouken@4636
   543
#if SDL_DIRECTFB_OPENGL
slouken@7191
   544
        DirectFB_GL_ReAllocWindowContexts(SDL_GetVideoDevice(), window);
slouken@4636
   545
#endif
slouken@4636
   546
   }
couriersud@3023
   547
  error:
couriersud@3023
   548
    return;
couriersud@3023
   549
}
slouken@6044
   550
icculus@10025
   551
int
icculus@10025
   552
DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
icculus@10025
   553
{
icculus@10025
   554
    const Uint8 alpha = (Uint8) ((unsigned int) (opacity * 255.0f));
icculus@10025
   555
    SDL_DFB_WINDOWDATA(window);
icculus@10025
   556
    SDL_DFB_CHECKERR(windata->dfbwin->SetOpacity(windata->dfbwin, alpha));
icculus@10025
   557
    windata->opacity = alpha;
icculus@10025
   558
    return 0;
icculus@10025
   559
icculus@10025
   560
error:
icculus@10025
   561
    return -1;
icculus@10025
   562
}
icculus@10025
   563
slouken@6044
   564
#endif /* SDL_VIDEO_DRIVER_DIRECTFB */