src/video/directfb/SDL_DirectFB_window.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sun, 30 Oct 2016 21:01:33 +0100
changeset 10563 e3d84016cb79
parent 10025 bf4f8cde1c54
child 10737 3406a0f8b041
permissions -rw-r--r--
Fixed outdated info in README.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2016 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_internal.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 >= 6
    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     SDL_FreeSurface(surface);
   241     SDL_DFB_RELEASE(windata->icon);
   242     return;
   243 }
   244 
   245 void
   246 DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
   247 {
   248     SDL_DFB_WINDOWDATA(window);
   249     int x, y;
   250 
   251     x = window->x;
   252     y = window->y;
   253 
   254     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   255     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, x, y));
   256 }
   257 
   258 void
   259 DirectFB_SetWindowSize(_THIS, SDL_Window * window)
   260 {
   261     SDL_DFB_WINDOWDATA(window);
   262 
   263     if(SDL_IsShapedWindow(window))
   264         DirectFB_ResizeWindowShape(window);
   265 
   266     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   267         int cw;
   268         int ch;
   269 
   270         /* Make sure all events are disabled for this operation ! */
   271         SDL_DFB_CHECKERR(windata->dfbwin->DisableEvents(windata->dfbwin,
   272                                                         DWET_ALL));
   273         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
   274 
   275         if (cw != window->w || ch != window->h) {
   276 
   277             DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   278             SDL_DFB_CHECKERR(windata->dfbwin->Resize(windata->dfbwin,
   279                                                      windata->size.w,
   280                                                      windata->size.h));
   281         }
   282 
   283         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   284                      (_this, window, &window->w, &window->h));
   285         DirectFB_AdjustWindowSurface(window);
   286 
   287         SDL_DFB_CHECKERR(windata->dfbwin->EnableEvents(windata->dfbwin,
   288                                                        DWET_ALL));
   289 
   290     }
   291     return;
   292   error:
   293     SDL_DFB_CHECK(windata->dfbwin->EnableEvents(windata->dfbwin, DWET_ALL));
   294     return;
   295 }
   296 
   297 void
   298 DirectFB_ShowWindow(_THIS, SDL_Window * window)
   299 {
   300     SDL_DFB_WINDOWDATA(window);
   301 
   302     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, windata->opacity));
   303 
   304 }
   305 
   306 void
   307 DirectFB_HideWindow(_THIS, SDL_Window * window)
   308 {
   309     SDL_DFB_WINDOWDATA(window);
   310 
   311     SDL_DFB_CHECK(windata->dfbwin->GetOpacity(windata->dfbwin, &windata->opacity));
   312     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0));
   313 }
   314 
   315 void
   316 DirectFB_RaiseWindow(_THIS, SDL_Window * window)
   317 {
   318     SDL_DFB_WINDOWDATA(window);
   319 
   320     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   321     SDL_DFB_CHECK(windata->dfbwin->RequestFocus(windata->dfbwin));
   322 }
   323 
   324 void
   325 DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
   326 {
   327     SDL_DFB_WINDOWDATA(window);
   328     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   329     DFBWindowOptions wopts;
   330 
   331     SDL_DFB_CHECK(windata->dfbwin->GetPosition(windata->dfbwin,
   332                                  &windata->restore.x, &windata->restore.y));
   333     SDL_DFB_CHECK(windata->dfbwin->GetSize(windata->dfbwin, &windata->restore.w,
   334                              &windata->restore.h));
   335 
   336     DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
   337 
   338     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, 0, 0));
   339     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin,
   340                             display->current_mode.w, display->current_mode.h));
   341 
   342     /* Set Options */
   343     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   344     wopts |= DWOP_KEEP_SIZE | DWOP_KEEP_POSITION;
   345     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   346 }
   347 
   348 void
   349 DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
   350 {
   351     /* FIXME: Size to 32x32 ? */
   352 
   353     SDL_Unsupported();
   354 }
   355 
   356 void
   357 DirectFB_RestoreWindow(_THIS, SDL_Window * window)
   358 {
   359     SDL_DFB_WINDOWDATA(window);
   360     DFBWindowOptions wopts;
   361 
   362     /* Set Options */
   363     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   364     wopts &= ~(DWOP_KEEP_SIZE | DWOP_KEEP_POSITION);
   365     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   366 
   367     /* Window layout */
   368     DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED),
   369         windata->restore.w, windata->restore.h);
   370     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin, windata->restore.w,
   371                             windata->restore.h));
   372     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, windata->restore.x,
   373                             windata->restore.y));
   374 
   375     if (!(window->flags & SDL_WINDOW_RESIZABLE))
   376         wopts |= DWOP_KEEP_SIZE;
   377 
   378     if (window->flags & SDL_WINDOW_FULLSCREEN)
   379         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_SIZE;
   380     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   381 
   382 
   383 }
   384 
   385 void
   386 DirectFB_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
   387 {
   388     SDL_DFB_DEVICEDATA(_this);
   389     SDL_DFB_WINDOWDATA(window);
   390     DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
   391 
   392     if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
   393         if (gwindata != NULL)
   394         {
   395             SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
   396             SDL_DFB_CHECK(gwindata->dfbwin->UngrabKeyboard(gwindata->dfbwin));
   397         }
   398         SDL_DFB_CHECK(windata->dfbwin->GrabPointer(windata->dfbwin));
   399         SDL_DFB_CHECK(windata->dfbwin->GrabKeyboard(windata->dfbwin));
   400         devdata->grabbed_window = window;
   401     } else {
   402         SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   403         SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   404         devdata->grabbed_window = NULL;
   405     }
   406 }
   407 
   408 void
   409 DirectFB_DestroyWindow(_THIS, SDL_Window * window)
   410 {
   411     SDL_DFB_DEVICEDATA(_this);
   412     SDL_DFB_WINDOWDATA(window);
   413     DFB_WindowData *p;
   414 
   415     /* Some cleanups */
   416     SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   417     SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   418 
   419 #if SDL_DIRECTFB_OPENGL
   420     DirectFB_GL_DestroyWindowContexts(_this, window);
   421 #endif
   422 
   423     if (window->shaper)
   424     {
   425         SDL_ShapeData *data = window->shaper->driverdata;
   426         SDL_DFB_CHECK(data->surface->ReleaseSource(data->surface));
   427         SDL_DFB_RELEASE(data->surface);
   428         SDL_DFB_FREE(data);
   429         SDL_DFB_FREE(window->shaper);
   430     }
   431 
   432     SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, NULL));
   433     SDL_DFB_CHECK(windata->surface->ReleaseSource(windata->surface));
   434     SDL_DFB_CHECK(windata->window_surface->ReleaseSource(windata->window_surface));
   435     SDL_DFB_RELEASE(windata->icon);
   436     SDL_DFB_RELEASE(windata->font);
   437     SDL_DFB_RELEASE(windata->eventbuffer);
   438     SDL_DFB_RELEASE(windata->surface);
   439     SDL_DFB_RELEASE(windata->window_surface);
   440 
   441     SDL_DFB_RELEASE(windata->dfbwin);
   442 
   443     /* Remove from list ... */
   444 
   445     p = devdata->firstwin->driverdata;
   446 
   447     while (p && p->next != window)
   448         p = (p->next ? p->next->driverdata : NULL);
   449     if (p)
   450         p->next = windata->next;
   451     else
   452         devdata->firstwin = windata->next;
   453     SDL_free(windata);
   454     return;
   455 }
   456 
   457 SDL_bool
   458 DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
   459                          struct SDL_SysWMinfo * info)
   460 {
   461     SDL_DFB_DEVICEDATA(_this);
   462     SDL_DFB_WINDOWDATA(window);
   463 
   464     if (info->version.major == SDL_MAJOR_VERSION &&
   465         info->version.minor == SDL_MINOR_VERSION) {
   466         info->subsystem = SDL_SYSWM_DIRECTFB;
   467         info->info.dfb.dfb = devdata->dfb;
   468         info->info.dfb.window = windata->dfbwin;
   469         info->info.dfb.surface = windata->surface;
   470         return SDL_TRUE;
   471     } else {
   472         SDL_SetError("Application not compiled with SDL %d.%d\n",
   473                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   474         return SDL_FALSE;
   475     }
   476 }
   477 
   478 void
   479 DirectFB_AdjustWindowSurface(SDL_Window * window)
   480 {
   481     SDL_DFB_WINDOWDATA(window);
   482     int adjust = windata->wm_needs_redraw;
   483     int cw, ch;
   484 
   485     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   486 
   487     SDL_DFB_CHECKERR(windata->
   488                      window_surface->GetSize(windata->window_surface, &cw,
   489                                              &ch));
   490     if (cw != windata->size.w || ch != windata->size.h) {
   491         adjust = 1;
   492     }
   493 
   494     if (adjust) {
   495 #if SDL_DIRECTFB_OPENGL
   496         DirectFB_GL_FreeWindowContexts(SDL_GetVideoDevice(), window);
   497 #endif
   498 
   499 #if (DFB_VERSION_ATLEAST(1,2,1))
   500         SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   501                                                         windata->size.w,
   502                                                         windata->size.h));
   503         SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
   504                                                           windata->
   505                                                           window_surface,
   506                                                           &windata->client));
   507 #else
   508         DFBWindowOptions opts;
   509 
   510         SDL_DFB_CHECKERR(windata->dfbwin->GetOptions(windata->dfbwin, &opts));
   511         /* recreate subsurface */
   512         SDL_DFB_RELEASE(windata->surface);
   513 
   514         if (opts & DWOP_SCALE)
   515             SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   516                                                             windata->size.w,
   517                                                             windata->size.h));
   518         SDL_DFB_CHECKERR(windata->window_surface->
   519                          GetSubSurface(windata->window_surface,
   520                                        &windata->client, &windata->surface));
   521 #endif
   522         DirectFB_WM_RedrawLayout(SDL_GetVideoDevice(), window);
   523 
   524 #if SDL_DIRECTFB_OPENGL
   525         DirectFB_GL_ReAllocWindowContexts(SDL_GetVideoDevice(), window);
   526 #endif
   527    }
   528   error:
   529     return;
   530 }
   531 
   532 int
   533 DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
   534 {
   535     const Uint8 alpha = (Uint8) ((unsigned int) (opacity * 255.0f));
   536     SDL_DFB_WINDOWDATA(window);
   537     SDL_DFB_CHECKERR(windata->dfbwin->SetOpacity(windata->dfbwin, alpha));
   538     windata->opacity = alpha;
   539     return 0;
   540 
   541 error:
   542     return -1;
   543 }
   544 
   545 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */