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