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