src/video/directfb/SDL_DirectFB_window.c
author Sam Lantinga
Fri, 11 Mar 2011 16:54:43 -0800
changeset 5478 6b65ff3cee62
parent 5288 d4381f3b0d1e
child 5488 c20436fd5627
permissions -rw-r--r--
Fixed bug 1167 (SDL_WINDOWPOS_CENTERED doesn't work if used right after fullscreen -> windowed switch)

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