src/video/directfb/SDL_DirectFB_window.c
author Sam Lantinga
Sun, 24 Jan 2010 21:10:53 +0000
changeset 3697 f7b03b6838cb
parent 3685 64ce267332c6
child 4568 25b9cd8bdc30
permissions -rw-r--r--
Fixed bug #926

Updated copyright to LGPL version 2.1 and year 2010
     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 #include "SDL_config.h"
    23 
    24 #include "SDL_syswm.h"
    25 #include "../SDL_sysvideo.h"
    26 #include "../../events/SDL_keyboard_c.h"
    27 
    28 #include "SDL_DirectFB_video.h"
    29 
    30 
    31 int
    32 DirectFB_CreateWindow(_THIS, SDL_Window * window)
    33 {
    34     SDL_DFB_DEVICEDATA(_this);
    35     SDL_DFB_DISPLAYDATA(_this, window);
    36     DFB_WindowData *windata = NULL;
    37     DFBWindowOptions wopts;
    38     DFBWindowDescription desc;
    39     IDirectFBFont *font;
    40     int ret, x, y;
    41 
    42     SDL_DFB_CALLOC(window->driverdata, 1, sizeof(DFB_WindowData));
    43     windata = (DFB_WindowData *) window->driverdata;
    44 
    45     windata->is_managed = devdata->has_own_wm;
    46 
    47     SDL_DFB_CHECKERR(devdata->dfb->SetCooperativeLevel(devdata->dfb,
    48                                                        DFSCL_NORMAL));
    49     SDL_DFB_CHECKERR(dispdata->layer->SetCooperativeLevel(dispdata->layer,
    50                                                           DLSCL_ADMINISTRATIVE));
    51 
    52     /* Fill the window description. */
    53     if (window->x == SDL_WINDOWPOS_CENTERED) {
    54         x = (dispdata->cw - window->w) / 2;
    55     } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
    56         x = 0;
    57     } else {
    58         x = window->x;
    59     }
    60     if (window->y == SDL_WINDOWPOS_CENTERED) {
    61         y = (dispdata->ch - window->h) / 2;
    62     } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
    63         y = 0;
    64     } else {
    65         y = window->y;
    66     }
    67     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    68         x = 0;
    69         y = 0;
    70     }
    71 
    72     DirectFB_WM_AdjustWindowLayout(window);
    73 
    74     /* Create Window */
    75     desc.flags =
    76         DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_PIXELFORMAT | DWDESC_POSX
    77         | DWDESC_POSY | DWDESC_SURFACE_CAPS;
    78     desc.posx = x;
    79     desc.posy = y;
    80     desc.width = windata->size.w;
    81     desc.height = windata->size.h;
    82     desc.pixelformat = dispdata->pixelformat;
    83     desc.surface_caps = DSCAPS_PREMULTIPLIED;
    84 
    85     /* Create the window. */
    86     SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
    87                                                    &windata->window));
    88 
    89     /* Set Options */
    90     windata->window->GetOptions(windata->window, &wopts);
    91 
    92     if (window->flags & SDL_WINDOW_RESIZABLE)
    93         wopts |= DWOP_SCALE;
    94     else
    95         wopts |= DWOP_KEEP_SIZE;
    96 
    97     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    98         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
    99         windata->window->SetStackingClass(windata->window, DWSC_UPPER);
   100     }
   101     windata->window->SetOptions(windata->window, wopts);
   102 
   103     /* See what we got */
   104     SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   105                      (_this, window, &window->w, &window->h));
   106 
   107     /* Get the window's surface. */
   108     SDL_DFB_CHECKERR(windata->window->GetSurface(windata->window,
   109                                                  &windata->window_surface));
   110     /* And get a subsurface for rendering */
   111     SDL_DFB_CHECKERR(windata->window_surface->
   112                      GetSubSurface(windata->window_surface, &windata->client,
   113                                    &windata->surface));
   114 
   115     windata->window->SetOpacity(windata->window, 0xFF);
   116 
   117     /* Create Eventbuffer */
   118     SDL_DFB_CHECKERR(windata->window->CreateEventBuffer(windata->window,
   119                                                         &windata->
   120                                                         eventbuffer));
   121     SDL_DFB_CHECKERR(windata->window->
   122                      EnableEvents(windata->window, DWET_ALL));
   123 
   124     /* Create a font */
   125     /* FIXME: once during Video_Init */
   126     if (windata->is_managed) {
   127         DFBFontDescription fdesc;
   128 
   129         fdesc.flags = DFDESC_HEIGHT;
   130         fdesc.height = windata->theme.font_size;
   131         font = NULL;
   132         SDL_DFB_CHECK(devdata->
   133                       dfb->CreateFont(devdata->dfb, windata->theme.font,
   134                                       &fdesc, &font));
   135         windata->window_surface->SetFont(windata->window_surface, font);
   136         SDL_DFB_RELEASE(font);
   137     }
   138 
   139     /* Make it the top most window. */
   140     windata->window->RaiseToTop(windata->window);
   141 
   142     /* remember parent */
   143     windata->window = window;
   144 
   145     /* Add to list ... */
   146 
   147     windata->next = devdata->firstwin;
   148     windata->opacity = 0xFF;
   149     devdata->firstwin = windata;
   150 
   151     /* Draw Frame */
   152     DirectFB_WM_RedrawLayout(window);
   153 
   154     return 0;
   155   error:
   156     SDL_DFB_RELEASE(windata->window);
   157     SDL_DFB_RELEASE(windata->surface);
   158     return -1;
   159 }
   160 
   161 int
   162 DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   163 {
   164     SDL_Unsupported();
   165     return -1;
   166 }
   167 
   168 void
   169 DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
   170 {
   171     SDL_DFB_WINDOWDATA(window);
   172 
   173     if (windata->is_managed) {
   174         windata->wm_needs_redraw = 1;
   175     } else
   176         SDL_Unsupported();
   177 }
   178 
   179 void
   180 DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   181 {
   182     SDL_DFB_DEVICEDATA(_this);
   183     SDL_DFB_WINDOWDATA(window);
   184     SDL_Surface *surface = NULL;
   185     DFBResult ret;
   186 
   187     if (icon) {
   188         SDL_PixelFormat format;
   189         DFBSurfaceDescription dsc;
   190         Uint32 *dest;
   191         Uint32 *p;
   192         int pitch, i;
   193 
   194         /* Convert the icon to ARGB for modern window managers */
   195         SDL_InitFormat(&format, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
   196                        0xFF000000);
   197         surface = SDL_ConvertSurface(icon, &format, 0);
   198         if (!surface) {
   199             return;
   200         }
   201         dsc.flags =
   202             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   203         dsc.caps = DSCAPS_VIDEOONLY;
   204         dsc.width = surface->w;
   205         dsc.height = surface->h;
   206         dsc.pixelformat = DSPF_ARGB;
   207 
   208         SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   209                                                      &windata->icon));
   210 
   211         SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
   212                                              (void *) &dest, &pitch));
   213 
   214         p = surface->pixels;
   215         for (i = 0; i < surface->h; i++)
   216             memcpy((char *) dest + i * pitch,
   217                    (char *) p + i * surface->pitch, 4 * surface->w);
   218 
   219         windata->icon->Unlock(windata->icon);
   220         SDL_FreeSurface(surface);
   221     } else {
   222         SDL_DFB_RELEASE(windata->icon);
   223     }
   224     return;
   225   error:
   226     if (surface)
   227         SDL_FreeSurface(surface);
   228     SDL_DFB_RELEASE(windata->icon);
   229     return;
   230 }
   231 
   232 void
   233 DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
   234 {
   235     SDL_DFB_WINDOWDATA(window);
   236     int x, y;
   237 
   238     if (window->y == SDL_WINDOWPOS_UNDEFINED)
   239         y = 0;
   240     else
   241         y = window->y;
   242 
   243     if (window->x == SDL_WINDOWPOS_UNDEFINED)
   244         x = 0;
   245     else
   246         x = window->x;
   247 
   248     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   249         x = 0;
   250         y = 0;
   251     }
   252     DirectFB_WM_AdjustWindowLayout(window);
   253     windata->window->MoveTo(windata->window, x, y);
   254 }
   255 
   256 void
   257 DirectFB_SetWindowSize(_THIS, SDL_Window * window)
   258 {
   259     SDL_DFB_DEVICEDATA(_this);
   260     SDL_DFB_WINDOWDATA(window);
   261     int ret;
   262 
   263     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   264         int cw;
   265         int ch;
   266 
   267         /* Make sure all events are disabled for this operation ! */
   268         SDL_DFB_CHECKERR(windata->window->DisableEvents(windata->window,
   269                                                         DWET_ALL));
   270 
   271         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
   272 
   273         if (cw != window->w || ch != window->h) {
   274 
   275             DirectFB_WM_AdjustWindowLayout(window);
   276             SDL_DFB_CHECKERR(windata->window->Resize(windata->window,
   277                                                      windata->size.w,
   278                                                      windata->size.h));
   279         }
   280 
   281         SDL_DFB_CHECKERR(windata->window->EnableEvents(windata->window,
   282                                                        DWET_ALL));
   283 
   284         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   285                          (_this, window, &window->w, &window->h));
   286 
   287         SDL_OnWindowResized(window);
   288     }
   289     return;
   290   error:
   291     windata->window->EnableEvents(windata->window, DWET_ALL);
   292     return;
   293 }
   294 
   295 void
   296 DirectFB_ShowWindow(_THIS, SDL_Window * window)
   297 {
   298     SDL_DFB_WINDOWDATA(window);
   299 
   300     windata->window->SetOpacity(windata->window, windata->opacity);
   301 
   302 }
   303 
   304 void
   305 DirectFB_HideWindow(_THIS, SDL_Window * window)
   306 {
   307     SDL_DFB_WINDOWDATA(window);
   308 
   309     windata->window->GetOpacity(windata->window, &windata->opacity);
   310     windata->window->SetOpacity(windata->window, 0);
   311 }
   312 
   313 void
   314 DirectFB_RaiseWindow(_THIS, SDL_Window * window)
   315 {
   316     SDL_DFB_WINDOWDATA(window);
   317 
   318     windata->window->RaiseToTop(windata->window);
   319     windata->window->RequestFocus(windata->window);
   320 }
   321 
   322 void
   323 DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
   324 {
   325     SDL_DFB_WINDOWDATA(window);
   326 
   327     if (windata->is_managed) {
   328         DirectFB_WM_MaximizeWindow(_this, window);
   329     } else
   330         SDL_Unsupported();
   331 }
   332 
   333 void
   334 DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
   335 {
   336     /* FIXME: Size to 32x32 ? */
   337 
   338     SDL_Unsupported();
   339 }
   340 
   341 void
   342 DirectFB_RestoreWindow(_THIS, SDL_Window * window)
   343 {
   344     SDL_DFB_WINDOWDATA(window);
   345 
   346     if (windata->is_managed) {
   347         DirectFB_WM_RestoreWindow(_this, window);
   348     } else
   349         SDL_Unsupported();
   350 }
   351 
   352 void
   353 DirectFB_SetWindowGrab(_THIS, SDL_Window * window)
   354 {
   355     SDL_DFB_WINDOWDATA(window);
   356 
   357     if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
   358         windata->window->GrabPointer(windata->window);
   359         windata->window->GrabKeyboard(windata->window);
   360     } else {
   361         windata->window->UngrabPointer(windata->window);
   362         windata->window->UngrabKeyboard(windata->window);
   363     }
   364 }
   365 
   366 void
   367 DirectFB_DestroyWindow(_THIS, SDL_Window * window)
   368 {
   369     SDL_DFB_DEVICEDATA(_this);
   370     SDL_DFB_WINDOWDATA(window);
   371     DFB_WindowData *p;
   372 
   373     SDL_DFB_DEBUG("Trace\n");
   374 
   375     /* Some cleanups */
   376     windata->window->UngrabPointer(windata->window);
   377     windata->window->UngrabKeyboard(windata->window);
   378 
   379     windata->window_surface->SetFont(windata->window_surface, NULL);
   380     SDL_DFB_RELEASE(windata->icon);
   381     SDL_DFB_RELEASE(windata->eventbuffer);
   382     SDL_DFB_RELEASE(windata->surface);
   383     SDL_DFB_RELEASE(windata->window_surface);
   384 
   385     SDL_DFB_RELEASE(windata->window);
   386 
   387     /* Remove from list ... */
   388 
   389     p = devdata->firstwin;
   390     while (p && p->next != windata)
   391         p = p->next;
   392     if (p)
   393         p->next = windata->next;
   394     else
   395         devdata->firstwin = windata->next;
   396     SDL_free(windata);
   397     return;
   398 }
   399 
   400 SDL_bool
   401 DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
   402                          struct SDL_SysWMinfo * info)
   403 {
   404     SDL_Unsupported();
   405     return SDL_FALSE;
   406 }
   407 
   408 void
   409 DirectFB_AdjustWindowSurface(SDL_Window * window)
   410 {
   411     SDL_DFB_WINDOWDATA(window);
   412     int adjust = windata->wm_needs_redraw;
   413     int cw, ch;
   414     int ret;
   415 
   416     DirectFB_WM_AdjustWindowLayout(window);
   417 
   418     SDL_DFB_CHECKERR(windata->
   419                      window_surface->GetSize(windata->window_surface, &cw,
   420                                              &ch));
   421     if (cw != windata->size.w || ch != windata->size.h) {
   422         adjust = 1;
   423     }
   424 
   425     if (adjust) {
   426 #if DFB_VERSION_ATLEAST(1,2,1)
   427         SDL_DFB_CHECKERR(windata->window->ResizeSurface(windata->window,
   428                                                         windata->size.w,
   429                                                         windata->size.h));
   430         SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
   431                                                           windata->
   432                                                           window_surface,
   433                                                           &windata->client));
   434 #else
   435         DFBWindowOptions opts;
   436 
   437         SDL_DFB_CHECKERR(windata->window->GetOptions(windata->window, &opts));
   438         /* recreate subsurface */
   439         SDL_DFB_RELEASE(windata->surface);
   440 
   441         if (opts & DWOP_SCALE)
   442             SDL_DFB_CHECKERR(windata->window->ResizeSurface(windata->window,
   443                                                             windata->size.w,
   444                                                             windata->size.h));
   445         SDL_DFB_CHECKERR(windata->window_surface->
   446                          GetSubSurface(windata->window_surface,
   447                                        &windata->client, &windata->surface));
   448 #endif
   449         DirectFB_WM_RedrawLayout(window);
   450     }
   451   error:
   452     return;
   453 }