src/video/directfb/SDL_DirectFB_window.c
author Sam Lantinga
Thu, 10 Feb 2011 14:44:25 -0800
changeset 5246 58265e606e4e
parent 5199 164f20ba08eb
child 5262 b530ef003506
permissions -rw-r--r--
Window coordinates are in the global space and windows are not tied to a particular display.
Also added Ctrl-Enter keybinding to the test code to toggle fullscreen mode for testing.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 
    22     SDL1.3 DirectFB driver by couriersud@arcor.de
    23 	
    24 */
    25 
    26 #include "SDL_DirectFB_video.h"
    27 #include "SDL_DirectFB_modes.h"
    28 #include "SDL_DirectFB_window.h"
    29 #include "SDL_DirectFB_shape.h"
    30 
    31 #if SDL_DIRECTFB_OPENGL
    32 #include "SDL_DirectFB_opengl.h"
    33 #endif
    34 
    35 #include "SDL_syswm.h"
    36 
    37 #include "../SDL_pixels_c.h"
    38 
    39 int
    40 DirectFB_CreateWindow(_THIS, SDL_Window * window)
    41 {
    42     SDL_DFB_DEVICEDATA(_this);
    43     SDL_DFB_DISPLAYDATA(window);
    44     DFB_WindowData *windata = NULL;
    45     DFBWindowOptions wopts;
    46     DFBWindowDescription desc;
    47     int x, y;
    48     int bshaped = 0;
    49 
    50     SDL_DFB_ALLOC_CLEAR(window->driverdata, sizeof(DFB_WindowData));
    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     if (SDL_WINDOWPOS_ISCENTERED(window->x)) {
    66         x = (dispdata->cw - window->w) / 2;
    67     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->x)) {
    68         x = 0;
    69     } else {
    70         x = window->x;
    71     }
    72     
    73     if (SDL_WINDOWPOS_ISCENTERED(window->y)) {
    74         y = (dispdata->ch - window->h) / 2;
    75     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->y)) {
    76         y = 0;
    77     } else {
    78         y = window->y;
    79     }
    80     
    81     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    82         x = 0;
    83         y = 0;
    84     }
    85 
    86     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
    87 
    88     /* Create Window */
    89 	desc.caps = 0;
    90     desc.flags =
    91         DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY | DWDESC_SURFACE_CAPS;
    92 
    93     if (bshaped) {
    94     	desc.flags |= DWDESC_CAPS;
    95     	desc.caps |= DWCAPS_ALPHACHANNEL;
    96     }
    97     else
    98     {
    99     	desc.flags |= DWDESC_PIXELFORMAT;
   100     }
   101 
   102     if (!(window->flags & SDL_WINDOW_BORDERLESS))
   103 		desc.caps |= DWCAPS_NODECORATION;
   104 
   105     desc.posx = x;
   106     desc.posy = y;
   107     desc.width = windata->size.w;
   108     desc.height = windata->size.h;
   109     desc.pixelformat = dispdata->pixelformat;
   110     desc.surface_caps = DSCAPS_PREMULTIPLIED;
   111     
   112     /* Create the window. */
   113     SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
   114                                                    &windata->dfbwin));
   115 
   116     /* Set Options */
   117     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   118 
   119     /* explicit rescaling of surface */
   120     wopts |= DWOP_SCALE;
   121     if (window->flags & SDL_WINDOW_RESIZABLE) {
   122         wopts &= ~DWOP_KEEP_SIZE;
   123     }
   124     else {
   125         wopts |= DWOP_KEEP_SIZE;
   126     }
   127 
   128     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   129         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
   130         SDL_DFB_CHECK(windata->dfbwin->SetStackingClass(windata->dfbwin, DWSC_UPPER));
   131     }
   132     
   133     if (bshaped) {
   134         wopts |= DWOP_SHAPED | DWOP_ALPHACHANNEL;
   135         wopts &= ~DWOP_OPAQUE_REGION;
   136     }
   137 
   138     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   139 
   140     /* See what we got */
   141     SDL_DFB_CHECK(DirectFB_WM_GetClientSize
   142                      (_this, window, &window->w, &window->h));
   143 
   144     /* Get the window's surface. */
   145     SDL_DFB_CHECKERR(windata->dfbwin->GetSurface(windata->dfbwin,
   146                                                  &windata->window_surface));
   147 
   148     /* And get a subsurface for rendering */
   149     SDL_DFB_CHECKERR(windata->window_surface->
   150                      GetSubSurface(windata->window_surface, &windata->client,
   151                                    &windata->surface));
   152 
   153     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0xFF));
   154 
   155     /* Create Eventbuffer */
   156 
   157     SDL_DFB_CHECKERR(windata->dfbwin->CreateEventBuffer(windata->dfbwin,
   158                                                         &windata->
   159                                                         eventbuffer));
   160     SDL_DFB_CHECKERR(windata->dfbwin->
   161                      EnableEvents(windata->dfbwin, DWET_ALL));
   162 
   163     /* Create a font */
   164     /* FIXME: once during Video_Init */
   165     windata->font = NULL;
   166 
   167     /* Make it the top most window. */
   168     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   169 
   170     /* remember parent */
   171     //windata->sdlwin = window;
   172 
   173     /* Add to list ... */
   174 
   175     windata->next = devdata->firstwin;
   176     windata->opacity = 0xFF;
   177     devdata->firstwin = window;
   178 
   179     /* Draw Frame */
   180     DirectFB_WM_RedrawLayout(_this, window);
   181 
   182     return 0;
   183   error:
   184 	SDL_DFB_RELEASE(windata->surface);
   185     SDL_DFB_RELEASE(windata->dfbwin);
   186     return -1;
   187 }
   188 
   189 int
   190 DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   191 {
   192     SDL_Unsupported();
   193     return -1;
   194 }
   195 
   196 void
   197 DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
   198 {
   199     SDL_DFB_WINDOWDATA(window);
   200 
   201     if (windata->is_managed) {
   202         windata->wm_needs_redraw = 1;
   203         DirectFB_WM_RedrawLayout(_this, window);
   204     } else
   205         SDL_Unsupported();
   206 }
   207 
   208 void
   209 DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   210 {
   211     SDL_DFB_DEVICEDATA(_this);
   212     SDL_DFB_WINDOWDATA(window);
   213     SDL_Surface *surface = NULL;
   214 
   215     if (icon) {
   216         SDL_PixelFormat format;
   217         DFBSurfaceDescription dsc;
   218         Uint32 *dest;
   219         Uint32 *p;
   220         int pitch, i;
   221 
   222         /* Convert the icon to ARGB for modern window managers */
   223         SDL_InitFormat(&format, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
   224                        0xFF000000);
   225         surface = SDL_ConvertSurface(icon, &format, 0);
   226         if (!surface) {
   227             return;
   228         }
   229         dsc.flags =
   230             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   231         dsc.caps = DSCAPS_VIDEOONLY;
   232         dsc.width = surface->w;
   233         dsc.height = surface->h;
   234         dsc.pixelformat = DSPF_ARGB;
   235 
   236         SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   237                                                      &windata->icon));
   238 
   239         SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
   240                                              (void *) &dest, &pitch));
   241 
   242         p = surface->pixels;
   243         for (i = 0; i < surface->h; i++)
   244             memcpy((char *) dest + i * pitch,
   245                    (char *) p + i * surface->pitch, 4 * surface->w);
   246 
   247         SDL_DFB_CHECK(windata->icon->Unlock(windata->icon));
   248         SDL_FreeSurface(surface);
   249     } else {
   250         SDL_DFB_RELEASE(windata->icon);
   251     }
   252     return;
   253   error:
   254     if (surface)
   255         SDL_FreeSurface(surface);
   256     SDL_DFB_RELEASE(windata->icon);
   257     return;
   258 }
   259 
   260 void
   261 DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
   262 {
   263     SDL_DFB_WINDOWDATA(window);
   264     SDL_DFB_DISPLAYDATA(window);
   265     int x, y;
   266 
   267     if (SDL_WINDOWPOS_ISCENTERED(window->x)) {
   268         x = (dispdata->cw - window->w) / 2;
   269     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->x)) {
   270         x = 0;
   271     } else {
   272         x = window->x;
   273     }
   274     
   275     if (SDL_WINDOWPOS_ISCENTERED(window->y)) {
   276         y = (dispdata->ch - window->h) / 2;
   277     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->y)) {
   278         y = 0;
   279     } else {
   280         y = window->y;
   281     }
   282 
   283     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   284         x = 0;
   285         y = 0;
   286     }
   287     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   288     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, x, y));
   289 }
   290 
   291 void
   292 DirectFB_SetWindowSize(_THIS, SDL_Window * window)
   293 {
   294     SDL_DFB_WINDOWDATA(window);
   295 
   296     if(SDL_IsShapedWindow(window))
   297         DirectFB_ResizeWindowShape(window);
   298 
   299     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   300         int cw;
   301         int ch;
   302 
   303         /* Make sure all events are disabled for this operation ! */
   304         SDL_DFB_CHECKERR(windata->dfbwin->DisableEvents(windata->dfbwin,
   305                                                         DWET_ALL));
   306         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
   307 
   308         if (cw != window->w || ch != window->h) {
   309 
   310 		    DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   311             SDL_DFB_CHECKERR(windata->dfbwin->Resize(windata->dfbwin,
   312                                                      windata->size.w,
   313                                                      windata->size.h));
   314         }
   315 
   316         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   317                      (_this, window, &window->w, &window->h));
   318         DirectFB_AdjustWindowSurface(window);
   319 
   320         SDL_DFB_CHECKERR(windata->dfbwin->EnableEvents(windata->dfbwin,
   321                                                        DWET_ALL));
   322 
   323     }
   324     return;
   325   error:
   326     SDL_DFB_CHECK(windata->dfbwin->EnableEvents(windata->dfbwin, DWET_ALL));
   327     return;
   328 }
   329 
   330 void
   331 DirectFB_ShowWindow(_THIS, SDL_Window * window)
   332 {
   333     SDL_DFB_WINDOWDATA(window);
   334 
   335     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, windata->opacity));
   336 
   337 }
   338 
   339 void
   340 DirectFB_HideWindow(_THIS, SDL_Window * window)
   341 {
   342     SDL_DFB_WINDOWDATA(window);
   343 
   344     SDL_DFB_CHECK(windata->dfbwin->GetOpacity(windata->dfbwin, &windata->opacity));
   345     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0));
   346 }
   347 
   348 void
   349 DirectFB_RaiseWindow(_THIS, SDL_Window * window)
   350 {
   351     SDL_DFB_WINDOWDATA(window);
   352 
   353     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   354     SDL_DFB_CHECK(windata->dfbwin->RequestFocus(windata->dfbwin));
   355 }
   356 
   357 void
   358 DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
   359 {
   360     SDL_DFB_WINDOWDATA(window);
   361     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   362     DFBWindowOptions wopts;
   363 
   364     SDL_DFB_CHECK(windata->dfbwin->GetPosition(windata->dfbwin,
   365                                  &windata->restore.x, &windata->restore.y));
   366     SDL_DFB_CHECK(windata->dfbwin->GetSize(windata->dfbwin, &windata->restore.w,
   367                              &windata->restore.h));
   368 
   369     DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
   370 
   371     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, 0, 0));
   372     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin,
   373                             display->current_mode.w, display->current_mode.h));
   374 
   375     /* Set Options */
   376     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   377     wopts |= DWOP_KEEP_SIZE | DWOP_KEEP_POSITION;
   378     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   379 }
   380 
   381 void
   382 DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
   383 {
   384     /* FIXME: Size to 32x32 ? */
   385 
   386     SDL_Unsupported();
   387 }
   388 
   389 void
   390 DirectFB_RestoreWindow(_THIS, SDL_Window * window)
   391 {
   392     SDL_DFB_WINDOWDATA(window);
   393     DFBWindowOptions wopts;
   394 
   395     /* Set Options */
   396     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   397     wopts &= ~(DWOP_KEEP_SIZE | DWOP_KEEP_POSITION);
   398     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   399 
   400     /* Window layout */
   401     DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED),
   402     	windata->restore.w, windata->restore.h);
   403     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin, windata->restore.w,
   404                             windata->restore.h));
   405     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, windata->restore.x,
   406                             windata->restore.y));
   407 
   408     if (!(window->flags & SDL_WINDOW_RESIZABLE))
   409         wopts |= DWOP_KEEP_SIZE;
   410 
   411     if (window->flags & SDL_WINDOW_FULLSCREEN)
   412         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_SIZE;
   413     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   414 
   415 
   416 }
   417 
   418 void
   419 DirectFB_SetWindowGrab(_THIS, SDL_Window * window)
   420 {
   421     SDL_DFB_DEVICEDATA(_this);
   422     SDL_DFB_WINDOWDATA(window);
   423     DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
   424 
   425     if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
   426         if (gwindata != NULL)
   427         {
   428 		    SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
   429 		    SDL_DFB_CHECK(gwindata->dfbwin->UngrabKeyboard(gwindata->dfbwin));
   430         }
   431         SDL_DFB_CHECK(windata->dfbwin->GrabPointer(windata->dfbwin));
   432         SDL_DFB_CHECK(windata->dfbwin->GrabKeyboard(windata->dfbwin));
   433         devdata->grabbed_window = window;
   434     } else {
   435         SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   436         SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   437         devdata->grabbed_window = NULL;
   438     }
   439 }
   440 
   441 void
   442 DirectFB_DestroyWindow(_THIS, SDL_Window * window)
   443 {
   444     SDL_DFB_DEVICEDATA(_this);
   445     SDL_DFB_WINDOWDATA(window);
   446     DFB_WindowData *p;
   447 
   448     /* Some cleanups */
   449     SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   450     SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   451 
   452 #if SDL_DIRECTFB_OPENGL
   453 	DirectFB_GL_DestroyWindowContexts(_this, window);
   454 #endif
   455 
   456 	if (window->shaper)
   457 	{
   458 	    SDL_ShapeData *data = window->shaper->driverdata;
   459 	    SDL_DFB_CHECK(data->surface->ReleaseSource(data->surface));
   460     	SDL_DFB_RELEASE(data->surface);
   461     	SDL_DFB_FREE(data);
   462     	SDL_DFB_FREE(window->shaper);
   463 	}
   464 
   465     SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, NULL));
   466     SDL_DFB_CHECK(windata->surface->ReleaseSource(windata->surface));
   467     SDL_DFB_CHECK(windata->window_surface->ReleaseSource(windata->window_surface));
   468   	SDL_DFB_RELEASE(windata->icon);
   469     SDL_DFB_RELEASE(windata->font);
   470     SDL_DFB_RELEASE(windata->eventbuffer);
   471     SDL_DFB_RELEASE(windata->surface);
   472     SDL_DFB_RELEASE(windata->window_surface);
   473 
   474     SDL_DFB_RELEASE(windata->dfbwin);
   475 
   476     /* Remove from list ... */
   477 
   478     p = devdata->firstwin->driverdata;
   479 
   480     while (p && p->next != window)
   481         p = (p->next ? p->next->driverdata : NULL);
   482     if (p)
   483         p->next = windata->next;
   484     else
   485         devdata->firstwin = windata->next;
   486     SDL_free(windata);
   487     return;
   488 }
   489 
   490 SDL_bool
   491 DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
   492                          struct SDL_SysWMinfo * info)
   493 {
   494     SDL_DFB_DEVICEDATA(_this);
   495     SDL_DFB_WINDOWDATA(window);
   496 
   497     if (info->version.major == SDL_MAJOR_VERSION &&
   498         info->version.minor == SDL_MINOR_VERSION) {
   499         info->subsystem = SDL_SYSWM_DIRECTFB;
   500         info->info.dfb.dfb = devdata->dfb;
   501         info->info.dfb.window = windata->dfbwin;
   502         info->info.dfb.surface = windata->surface;
   503         return SDL_TRUE;
   504     } else {
   505         SDL_SetError("Application not compiled with SDL %d.%d\n",
   506                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   507         return SDL_FALSE;
   508     }
   509 }
   510 
   511 void
   512 DirectFB_AdjustWindowSurface(SDL_Window * window)
   513 {
   514     SDL_DFB_WINDOWDATA(window);
   515     int adjust = windata->wm_needs_redraw;
   516     int cw, ch;
   517 
   518     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   519 
   520     SDL_DFB_CHECKERR(windata->
   521                      window_surface->GetSize(windata->window_surface, &cw,
   522                                              &ch));
   523     if (cw != windata->size.w || ch != windata->size.h) {
   524         adjust = 1;
   525     }
   526 
   527     if (adjust) {
   528 #if SDL_DIRECTFB_OPENGL
   529 		DirectFB_GL_FreeWindowContexts(SDL_GetVideoDevice(), window);
   530 #endif
   531 
   532 #if (DFB_VERSION_ATLEAST(1,2,1))
   533         SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   534                                                         windata->size.w,
   535                                                         windata->size.h));
   536         SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
   537                                                           windata->
   538                                                           window_surface,
   539                                                           &windata->client));
   540 #else
   541         DFBWindowOptions opts;
   542 
   543         SDL_DFB_CHECKERR(windata->dfbwin->GetOptions(windata->dfbwin, &opts));
   544         /* recreate subsurface */
   545         SDL_DFB_RELEASE(windata->surface);
   546 
   547         if (opts & DWOP_SCALE)
   548             SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   549                                                             windata->size.w,
   550                                                             windata->size.h));
   551         SDL_DFB_CHECKERR(windata->window_surface->
   552                          GetSubSurface(windata->window_surface,
   553                                        &windata->client, &windata->surface));
   554 #endif
   555         DirectFB_WM_RedrawLayout(SDL_GetVideoDevice(), window);
   556         
   557 #if SDL_DIRECTFB_OPENGL
   558 		DirectFB_GL_ReAllocWindowContexts(SDL_GetVideoDevice(), window);
   559 #endif
   560    }
   561   error:
   562     return;
   563 }