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