src/video/directfb/SDL_DirectFB_window.c
author Gabriel Jacobo
Wed, 21 Aug 2013 09:47:10 -0300
changeset 7678 286c42d7c5ed
parent 7191 75360622e65f
child 7720 f9a649383362
permissions -rw-r--r--
OCD fixes: Adds a space after /* (glory to regular expressions!)
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_DIRECTFB
    24 
    25 #include "SDL_DirectFB_video.h"
    26 #include "SDL_DirectFB_modes.h"
    27 #include "SDL_DirectFB_window.h"
    28 #include "SDL_DirectFB_shape.h"
    29 
    30 #if SDL_DIRECTFB_OPENGL
    31 #include "SDL_DirectFB_opengl.h"
    32 #endif
    33 
    34 #include "SDL_syswm.h"
    35 
    36 #include "../SDL_pixels_c.h"
    37 
    38 int
    39 DirectFB_CreateWindow(_THIS, SDL_Window * window)
    40 {
    41     SDL_DFB_DEVICEDATA(_this);
    42     SDL_DFB_DISPLAYDATA(window);
    43     DFB_WindowData *windata = NULL;
    44     DFBWindowOptions wopts;
    45     DFBWindowDescription desc;
    46     int x, y;
    47     int bshaped = 0;
    48 
    49     SDL_DFB_ALLOC_CLEAR(window->driverdata, sizeof(DFB_WindowData));
    50     SDL_memset(&desc, 0, sizeof(DFBWindowDescription));
    51     windata = (DFB_WindowData *) window->driverdata;
    52 
    53     windata->is_managed = devdata->has_own_wm;
    54 #if 1
    55     SDL_DFB_CHECKERR(devdata->dfb->SetCooperativeLevel(devdata->dfb,
    56                                                        DFSCL_NORMAL));
    57     SDL_DFB_CHECKERR(dispdata->layer->SetCooperativeLevel(dispdata->layer,
    58                                                           DLSCL_ADMINISTRATIVE));
    59 #endif
    60     /* FIXME ... ughh, ugly */
    61     if (window->x == -1000 && window->y == -1000)
    62         bshaped = 1;
    63 
    64     /* Fill the window description. */
    65     x = window->x;
    66     y = window->y;
    67 
    68     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
    69 
    70     /* Create Window */
    71     desc.caps = 0;
    72     desc.flags =
    73         DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY | DWDESC_SURFACE_CAPS;
    74 
    75     if (bshaped) {
    76         desc.flags |= DWDESC_CAPS;
    77         desc.caps |= DWCAPS_ALPHACHANNEL;
    78     }
    79     else
    80     {
    81         desc.flags |= DWDESC_PIXELFORMAT;
    82     }
    83 
    84     if (!(window->flags & SDL_WINDOW_BORDERLESS))
    85         desc.caps |= DWCAPS_NODECORATION;
    86 
    87     desc.posx = x;
    88     desc.posy = y;
    89     desc.width = windata->size.w;
    90     desc.height = windata->size.h;
    91     desc.pixelformat = dispdata->pixelformat;
    92     desc.surface_caps = DSCAPS_PREMULTIPLIED;
    93 #if DIRECTFB_MAJOR_VERSION == 1 && DIRECTFB_MINOR_VERSION >= 4
    94     if (window->flags & SDL_WINDOW_OPENGL) {
    95         desc.surface_caps |= DSCAPS_GL;
    96     }
    97 #endif
    98 
    99     /* Create the window. */
   100     SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
   101                                                    &windata->dfbwin));
   102 
   103     /* Set Options */
   104     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   105 
   106     /* explicit rescaling of surface */
   107     wopts |= DWOP_SCALE;
   108     if (window->flags & SDL_WINDOW_RESIZABLE) {
   109         wopts &= ~DWOP_KEEP_SIZE;
   110     }
   111     else {
   112         wopts |= DWOP_KEEP_SIZE;
   113     }
   114 
   115     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   116         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
   117         SDL_DFB_CHECK(windata->dfbwin->SetStackingClass(windata->dfbwin, DWSC_UPPER));
   118     }
   119 
   120     if (bshaped) {
   121         wopts |= DWOP_SHAPED | DWOP_ALPHACHANNEL;
   122         wopts &= ~DWOP_OPAQUE_REGION;
   123     }
   124 
   125     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   126 
   127     /* See what we got */
   128     SDL_DFB_CHECK(DirectFB_WM_GetClientSize
   129                      (_this, window, &window->w, &window->h));
   130 
   131     /* Get the window's surface. */
   132     SDL_DFB_CHECKERR(windata->dfbwin->GetSurface(windata->dfbwin,
   133                                                  &windata->window_surface));
   134 
   135     /* And get a subsurface for rendering */
   136     SDL_DFB_CHECKERR(windata->window_surface->
   137                      GetSubSurface(windata->window_surface, &windata->client,
   138                                    &windata->surface));
   139 
   140     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0xFF));
   141 
   142     /* Create Eventbuffer */
   143 
   144     SDL_DFB_CHECKERR(windata->dfbwin->CreateEventBuffer(windata->dfbwin,
   145                                                         &windata->
   146                                                         eventbuffer));
   147     SDL_DFB_CHECKERR(windata->dfbwin->
   148                      EnableEvents(windata->dfbwin, DWET_ALL));
   149 
   150     /* Create a font */
   151     /* FIXME: once during Video_Init */
   152     windata->font = NULL;
   153 
   154     /* Make it the top most window. */
   155     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   156 
   157     /* remember parent */
   158     /* windata->sdlwin = window; */
   159 
   160     /* Add to list ... */
   161 
   162     windata->next = devdata->firstwin;
   163     windata->opacity = 0xFF;
   164     devdata->firstwin = window;
   165 
   166     /* Draw Frame */
   167     DirectFB_WM_RedrawLayout(_this, window);
   168 
   169     return 0;
   170   error:
   171     SDL_DFB_RELEASE(windata->surface);
   172     SDL_DFB_RELEASE(windata->dfbwin);
   173     return -1;
   174 }
   175 
   176 int
   177 DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   178 {
   179     return SDL_Unsupported();
   180 }
   181 
   182 void
   183 DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
   184 {
   185     SDL_DFB_WINDOWDATA(window);
   186 
   187     if (windata->is_managed) {
   188         windata->wm_needs_redraw = 1;
   189         DirectFB_WM_RedrawLayout(_this, window);
   190     } else {
   191         SDL_Unsupported();
   192     }
   193 }
   194 
   195 void
   196 DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   197 {
   198     SDL_DFB_DEVICEDATA(_this);
   199     SDL_DFB_WINDOWDATA(window);
   200     SDL_Surface *surface = NULL;
   201 
   202     if (icon) {
   203         SDL_PixelFormat format;
   204         DFBSurfaceDescription dsc;
   205         Uint32 *dest;
   206         Uint32 *p;
   207         int pitch, i;
   208 
   209         /* Convert the icon to ARGB for modern window managers */
   210         SDL_InitFormat(&format, SDL_PIXELFORMAT_ARGB8888);
   211         surface = SDL_ConvertSurface(icon, &format, 0);
   212         if (!surface) {
   213             return;
   214         }
   215         dsc.flags =
   216             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   217         dsc.caps = DSCAPS_VIDEOONLY;
   218         dsc.width = surface->w;
   219         dsc.height = surface->h;
   220         dsc.pixelformat = DSPF_ARGB;
   221 
   222         SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   223                                                      &windata->icon));
   224 
   225         SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
   226                                              (void *) &dest, &pitch));
   227 
   228         p = surface->pixels;
   229         for (i = 0; i < surface->h; i++)
   230             memcpy((char *) dest + i * pitch,
   231                    (char *) p + i * surface->pitch, 4 * surface->w);
   232 
   233         SDL_DFB_CHECK(windata->icon->Unlock(windata->icon));
   234         SDL_FreeSurface(surface);
   235     } else {
   236         SDL_DFB_RELEASE(windata->icon);
   237     }
   238     return;
   239   error:
   240     if (surface)
   241         SDL_FreeSurface(surface);
   242     SDL_DFB_RELEASE(windata->icon);
   243     return;
   244 }
   245 
   246 void
   247 DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
   248 {
   249     SDL_DFB_WINDOWDATA(window);
   250     int x, y;
   251 
   252     x = window->x;
   253     y = window->y;
   254 
   255     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   256     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, x, y));
   257 }
   258 
   259 void
   260 DirectFB_SetWindowSize(_THIS, SDL_Window * window)
   261 {
   262     SDL_DFB_WINDOWDATA(window);
   263 
   264     if(SDL_IsShapedWindow(window))
   265         DirectFB_ResizeWindowShape(window);
   266 
   267     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   268         int cw;
   269         int ch;
   270 
   271         /* Make sure all events are disabled for this operation ! */
   272         SDL_DFB_CHECKERR(windata->dfbwin->DisableEvents(windata->dfbwin,
   273                                                         DWET_ALL));
   274         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
   275 
   276         if (cw != window->w || ch != window->h) {
   277 
   278             DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   279             SDL_DFB_CHECKERR(windata->dfbwin->Resize(windata->dfbwin,
   280                                                      windata->size.w,
   281                                                      windata->size.h));
   282         }
   283 
   284         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   285                      (_this, window, &window->w, &window->h));
   286         DirectFB_AdjustWindowSurface(window);
   287 
   288         SDL_DFB_CHECKERR(windata->dfbwin->EnableEvents(windata->dfbwin,
   289                                                        DWET_ALL));
   290 
   291     }
   292     return;
   293   error:
   294     SDL_DFB_CHECK(windata->dfbwin->EnableEvents(windata->dfbwin, DWET_ALL));
   295     return;
   296 }
   297 
   298 void
   299 DirectFB_ShowWindow(_THIS, SDL_Window * window)
   300 {
   301     SDL_DFB_WINDOWDATA(window);
   302 
   303     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, windata->opacity));
   304 
   305 }
   306 
   307 void
   308 DirectFB_HideWindow(_THIS, SDL_Window * window)
   309 {
   310     SDL_DFB_WINDOWDATA(window);
   311 
   312     SDL_DFB_CHECK(windata->dfbwin->GetOpacity(windata->dfbwin, &windata->opacity));
   313     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0));
   314 }
   315 
   316 void
   317 DirectFB_RaiseWindow(_THIS, SDL_Window * window)
   318 {
   319     SDL_DFB_WINDOWDATA(window);
   320 
   321     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   322     SDL_DFB_CHECK(windata->dfbwin->RequestFocus(windata->dfbwin));
   323 }
   324 
   325 void
   326 DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
   327 {
   328     SDL_DFB_WINDOWDATA(window);
   329     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   330     DFBWindowOptions wopts;
   331 
   332     SDL_DFB_CHECK(windata->dfbwin->GetPosition(windata->dfbwin,
   333                                  &windata->restore.x, &windata->restore.y));
   334     SDL_DFB_CHECK(windata->dfbwin->GetSize(windata->dfbwin, &windata->restore.w,
   335                              &windata->restore.h));
   336 
   337     DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
   338 
   339     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, 0, 0));
   340     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin,
   341                             display->current_mode.w, display->current_mode.h));
   342 
   343     /* Set Options */
   344     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   345     wopts |= DWOP_KEEP_SIZE | DWOP_KEEP_POSITION;
   346     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   347 }
   348 
   349 void
   350 DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
   351 {
   352     /* FIXME: Size to 32x32 ? */
   353 
   354     SDL_Unsupported();
   355 }
   356 
   357 void
   358 DirectFB_RestoreWindow(_THIS, SDL_Window * window)
   359 {
   360     SDL_DFB_WINDOWDATA(window);
   361     DFBWindowOptions wopts;
   362 
   363     /* Set Options */
   364     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   365     wopts &= ~(DWOP_KEEP_SIZE | DWOP_KEEP_POSITION);
   366     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   367 
   368     /* Window layout */
   369     DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED),
   370         windata->restore.w, windata->restore.h);
   371     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin, windata->restore.w,
   372                             windata->restore.h));
   373     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, windata->restore.x,
   374                             windata->restore.y));
   375 
   376     if (!(window->flags & SDL_WINDOW_RESIZABLE))
   377         wopts |= DWOP_KEEP_SIZE;
   378 
   379     if (window->flags & SDL_WINDOW_FULLSCREEN)
   380         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_SIZE;
   381     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   382 
   383 
   384 }
   385 
   386 void
   387 DirectFB_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
   388 {
   389     SDL_DFB_DEVICEDATA(_this);
   390     SDL_DFB_WINDOWDATA(window);
   391     DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
   392 
   393     if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
   394         if (gwindata != NULL)
   395         {
   396             SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
   397             SDL_DFB_CHECK(gwindata->dfbwin->UngrabKeyboard(gwindata->dfbwin));
   398         }
   399         SDL_DFB_CHECK(windata->dfbwin->GrabPointer(windata->dfbwin));
   400         SDL_DFB_CHECK(windata->dfbwin->GrabKeyboard(windata->dfbwin));
   401         devdata->grabbed_window = window;
   402     } else {
   403         SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   404         SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   405         devdata->grabbed_window = NULL;
   406     }
   407 }
   408 
   409 void
   410 DirectFB_DestroyWindow(_THIS, SDL_Window * window)
   411 {
   412     SDL_DFB_DEVICEDATA(_this);
   413     SDL_DFB_WINDOWDATA(window);
   414     DFB_WindowData *p;
   415 
   416     /* Some cleanups */
   417     SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   418     SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   419 
   420 #if SDL_DIRECTFB_OPENGL
   421     DirectFB_GL_DestroyWindowContexts(_this, window);
   422 #endif
   423 
   424     if (window->shaper)
   425     {
   426         SDL_ShapeData *data = window->shaper->driverdata;
   427         SDL_DFB_CHECK(data->surface->ReleaseSource(data->surface));
   428         SDL_DFB_RELEASE(data->surface);
   429         SDL_DFB_FREE(data);
   430         SDL_DFB_FREE(window->shaper);
   431     }
   432 
   433     SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, NULL));
   434     SDL_DFB_CHECK(windata->surface->ReleaseSource(windata->surface));
   435     SDL_DFB_CHECK(windata->window_surface->ReleaseSource(windata->window_surface));
   436     SDL_DFB_RELEASE(windata->icon);
   437     SDL_DFB_RELEASE(windata->font);
   438     SDL_DFB_RELEASE(windata->eventbuffer);
   439     SDL_DFB_RELEASE(windata->surface);
   440     SDL_DFB_RELEASE(windata->window_surface);
   441 
   442     SDL_DFB_RELEASE(windata->dfbwin);
   443 
   444     /* Remove from list ... */
   445 
   446     p = devdata->firstwin->driverdata;
   447 
   448     while (p && p->next != window)
   449         p = (p->next ? p->next->driverdata : NULL);
   450     if (p)
   451         p->next = windata->next;
   452     else
   453         devdata->firstwin = windata->next;
   454     SDL_free(windata);
   455     return;
   456 }
   457 
   458 SDL_bool
   459 DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
   460                          struct SDL_SysWMinfo * info)
   461 {
   462     SDL_DFB_DEVICEDATA(_this);
   463     SDL_DFB_WINDOWDATA(window);
   464 
   465     if (info->version.major == SDL_MAJOR_VERSION &&
   466         info->version.minor == SDL_MINOR_VERSION) {
   467         info->subsystem = SDL_SYSWM_DIRECTFB;
   468         info->info.dfb.dfb = devdata->dfb;
   469         info->info.dfb.window = windata->dfbwin;
   470         info->info.dfb.surface = windata->surface;
   471         return SDL_TRUE;
   472     } else {
   473         SDL_SetError("Application not compiled with SDL %d.%d\n",
   474                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   475         return SDL_FALSE;
   476     }
   477 }
   478 
   479 void
   480 DirectFB_AdjustWindowSurface(SDL_Window * window)
   481 {
   482     SDL_DFB_WINDOWDATA(window);
   483     int adjust = windata->wm_needs_redraw;
   484     int cw, ch;
   485 
   486     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   487 
   488     SDL_DFB_CHECKERR(windata->
   489                      window_surface->GetSize(windata->window_surface, &cw,
   490                                              &ch));
   491     if (cw != windata->size.w || ch != windata->size.h) {
   492         adjust = 1;
   493     }
   494 
   495     if (adjust) {
   496 #if SDL_DIRECTFB_OPENGL
   497         DirectFB_GL_FreeWindowContexts(SDL_GetVideoDevice(), window);
   498 #endif
   499 
   500 #if (DFB_VERSION_ATLEAST(1,2,1))
   501         SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   502                                                         windata->size.w,
   503                                                         windata->size.h));
   504         SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
   505                                                           windata->
   506                                                           window_surface,
   507                                                           &windata->client));
   508 #else
   509         DFBWindowOptions opts;
   510 
   511         SDL_DFB_CHECKERR(windata->dfbwin->GetOptions(windata->dfbwin, &opts));
   512         /* recreate subsurface */
   513         SDL_DFB_RELEASE(windata->surface);
   514 
   515         if (opts & DWOP_SCALE)
   516             SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   517                                                             windata->size.w,
   518                                                             windata->size.h));
   519         SDL_DFB_CHECKERR(windata->window_surface->
   520                          GetSubSurface(windata->window_surface,
   521                                        &windata->client, &windata->surface));
   522 #endif
   523         DirectFB_WM_RedrawLayout(SDL_GetVideoDevice(), window);
   524 
   525 #if SDL_DIRECTFB_OPENGL
   526         DirectFB_GL_ReAllocWindowContexts(SDL_GetVideoDevice(), window);
   527 #endif
   528    }
   529   error:
   530     return;
   531 }
   532 
   533 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */