SDL_DirectFB_window.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../../SDL_internal.h"
  19. #if SDL_VIDEO_DRIVER_DIRECTFB
  20. #include "SDL_DirectFB_video.h"
  21. #include "SDL_DirectFB_modes.h"
  22. #include "SDL_DirectFB_window.h"
  23. #include "SDL_DirectFB_shape.h"
  24. #if SDL_DIRECTFB_OPENGL
  25. #include "SDL_DirectFB_opengl.h"
  26. #endif
  27. #include "SDL_syswm.h"
  28. #include "../SDL_pixels_c.h"
  29. int
  30. DirectFB_CreateWindow(_THIS, SDL_Window * window)
  31. {
  32. SDL_DFB_DEVICEDATA(_this);
  33. SDL_DFB_DISPLAYDATA(window);
  34. DFB_WindowData *windata = NULL;
  35. DFBWindowOptions wopts;
  36. DFBWindowDescription desc;
  37. int x, y;
  38. int bshaped = 0;
  39. SDL_DFB_ALLOC_CLEAR(window->driverdata, sizeof(DFB_WindowData));
  40. SDL_memset(&desc, 0, sizeof(DFBWindowDescription));
  41. windata = (DFB_WindowData *) window->driverdata;
  42. windata->is_managed = devdata->has_own_wm;
  43. #if 1
  44. SDL_DFB_CHECKERR(devdata->dfb->SetCooperativeLevel(devdata->dfb,
  45. DFSCL_NORMAL));
  46. SDL_DFB_CHECKERR(dispdata->layer->SetCooperativeLevel(dispdata->layer,
  47. DLSCL_ADMINISTRATIVE));
  48. #endif
  49. /* FIXME ... ughh, ugly */
  50. if (window->x == -1000 && window->y == -1000)
  51. bshaped = 1;
  52. /* Fill the window description. */
  53. x = window->x;
  54. y = window->y;
  55. DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
  56. /* Create Window */
  57. desc.caps = 0;
  58. desc.flags =
  59. DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY | DWDESC_SURFACE_CAPS;
  60. if (bshaped) {
  61. desc.flags |= DWDESC_CAPS;
  62. desc.caps |= DWCAPS_ALPHACHANNEL;
  63. }
  64. else
  65. {
  66. desc.flags |= DWDESC_PIXELFORMAT;
  67. }
  68. if (!(window->flags & SDL_WINDOW_BORDERLESS))
  69. desc.caps |= DWCAPS_NODECORATION;
  70. desc.posx = x;
  71. desc.posy = y;
  72. desc.width = windata->size.w;
  73. desc.height = windata->size.h;
  74. desc.pixelformat = dispdata->pixelformat;
  75. desc.surface_caps = DSCAPS_PREMULTIPLIED;
  76. #if DIRECTFB_MAJOR_VERSION == 1 && DIRECTFB_MINOR_VERSION >= 6
  77. if (window->flags & SDL_WINDOW_OPENGL) {
  78. desc.surface_caps |= DSCAPS_GL;
  79. }
  80. #endif
  81. /* Create the window. */
  82. SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
  83. &windata->dfbwin));
  84. /* Set Options */
  85. SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
  86. /* explicit rescaling of surface */
  87. wopts |= DWOP_SCALE;
  88. if (window->flags & SDL_WINDOW_RESIZABLE) {
  89. wopts &= ~DWOP_KEEP_SIZE;
  90. }
  91. else {
  92. wopts |= DWOP_KEEP_SIZE;
  93. }
  94. if (window->flags & SDL_WINDOW_FULLSCREEN) {
  95. wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
  96. SDL_DFB_CHECK(windata->dfbwin->SetStackingClass(windata->dfbwin, DWSC_UPPER));
  97. }
  98. if (bshaped) {
  99. wopts |= DWOP_SHAPED | DWOP_ALPHACHANNEL;
  100. wopts &= ~DWOP_OPAQUE_REGION;
  101. }
  102. SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
  103. /* See what we got */
  104. SDL_DFB_CHECK(DirectFB_WM_GetClientSize
  105. (_this, window, &window->w, &window->h));
  106. /* Get the window's surface. */
  107. SDL_DFB_CHECKERR(windata->dfbwin->GetSurface(windata->dfbwin,
  108. &windata->window_surface));
  109. /* And get a subsurface for rendering */
  110. SDL_DFB_CHECKERR(windata->window_surface->
  111. GetSubSurface(windata->window_surface, &windata->client,
  112. &windata->surface));
  113. SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0xFF));
  114. /* Create Eventbuffer */
  115. SDL_DFB_CHECKERR(windata->dfbwin->CreateEventBuffer(windata->dfbwin,
  116. &windata->
  117. eventbuffer));
  118. SDL_DFB_CHECKERR(windata->dfbwin->
  119. EnableEvents(windata->dfbwin, DWET_ALL));
  120. /* Create a font */
  121. /* FIXME: once during Video_Init */
  122. windata->font = NULL;
  123. /* Make it the top most window. */
  124. SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
  125. /* remember parent */
  126. /* windata->sdlwin = window; */
  127. /* Add to list ... */
  128. windata->next = devdata->firstwin;
  129. windata->opacity = 0xFF;
  130. devdata->firstwin = window;
  131. /* Draw Frame */
  132. DirectFB_WM_RedrawLayout(_this, window);
  133. return 0;
  134. error:
  135. SDL_DFB_RELEASE(windata->surface);
  136. SDL_DFB_RELEASE(windata->dfbwin);
  137. return -1;
  138. }
  139. int
  140. DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
  141. {
  142. return SDL_Unsupported();
  143. }
  144. void
  145. DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
  146. {
  147. SDL_DFB_WINDOWDATA(window);
  148. if (windata->is_managed) {
  149. windata->wm_needs_redraw = 1;
  150. DirectFB_WM_RedrawLayout(_this, window);
  151. } else {
  152. SDL_Unsupported();
  153. }
  154. }
  155. void
  156. DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
  157. {
  158. SDL_DFB_DEVICEDATA(_this);
  159. SDL_DFB_WINDOWDATA(window);
  160. SDL_Surface *surface = NULL;
  161. if (icon) {
  162. SDL_PixelFormat format;
  163. DFBSurfaceDescription dsc;
  164. Uint32 *dest;
  165. Uint32 *p;
  166. int pitch, i;
  167. /* Convert the icon to ARGB for modern window managers */
  168. SDL_InitFormat(&format, SDL_PIXELFORMAT_ARGB8888);
  169. surface = SDL_ConvertSurface(icon, &format, 0);
  170. if (!surface) {
  171. return;
  172. }
  173. dsc.flags =
  174. DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
  175. dsc.caps = DSCAPS_VIDEOONLY;
  176. dsc.width = surface->w;
  177. dsc.height = surface->h;
  178. dsc.pixelformat = DSPF_ARGB;
  179. SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
  180. &windata->icon));
  181. SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
  182. (void *) &dest, &pitch));
  183. p = surface->pixels;
  184. for (i = 0; i < surface->h; i++)
  185. memcpy((char *) dest + i * pitch,
  186. (char *) p + i * surface->pitch, 4 * surface->w);
  187. SDL_DFB_CHECK(windata->icon->Unlock(windata->icon));
  188. SDL_FreeSurface(surface);
  189. } else {
  190. SDL_DFB_RELEASE(windata->icon);
  191. }
  192. return;
  193. error:
  194. SDL_FreeSurface(surface);
  195. SDL_DFB_RELEASE(windata->icon);
  196. return;
  197. }
  198. void
  199. DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
  200. {
  201. SDL_DFB_WINDOWDATA(window);
  202. int x, y;
  203. x = window->x;
  204. y = window->y;
  205. DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
  206. SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, x, y));
  207. }
  208. void
  209. DirectFB_SetWindowSize(_THIS, SDL_Window * window)
  210. {
  211. SDL_DFB_WINDOWDATA(window);
  212. if(SDL_IsShapedWindow(window))
  213. DirectFB_ResizeWindowShape(window);
  214. if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
  215. int cw;
  216. int ch;
  217. /* Make sure all events are disabled for this operation ! */
  218. SDL_DFB_CHECKERR(windata->dfbwin->DisableEvents(windata->dfbwin,
  219. DWET_ALL));
  220. SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
  221. if (cw != window->w || ch != window->h) {
  222. DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
  223. SDL_DFB_CHECKERR(windata->dfbwin->Resize(windata->dfbwin,
  224. windata->size.w,
  225. windata->size.h));
  226. }
  227. SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
  228. (_this, window, &window->w, &window->h));
  229. DirectFB_AdjustWindowSurface(window);
  230. SDL_DFB_CHECKERR(windata->dfbwin->EnableEvents(windata->dfbwin,
  231. DWET_ALL));
  232. }
  233. return;
  234. error:
  235. SDL_DFB_CHECK(windata->dfbwin->EnableEvents(windata->dfbwin, DWET_ALL));
  236. return;
  237. }
  238. void
  239. DirectFB_ShowWindow(_THIS, SDL_Window * window)
  240. {
  241. SDL_DFB_WINDOWDATA(window);
  242. SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, windata->opacity));
  243. }
  244. void
  245. DirectFB_HideWindow(_THIS, SDL_Window * window)
  246. {
  247. SDL_DFB_WINDOWDATA(window);
  248. SDL_DFB_CHECK(windata->dfbwin->GetOpacity(windata->dfbwin, &windata->opacity));
  249. SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0));
  250. }
  251. void
  252. DirectFB_RaiseWindow(_THIS, SDL_Window * window)
  253. {
  254. SDL_DFB_WINDOWDATA(window);
  255. SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
  256. SDL_DFB_CHECK(windata->dfbwin->RequestFocus(windata->dfbwin));
  257. }
  258. void
  259. DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
  260. {
  261. SDL_DFB_WINDOWDATA(window);
  262. SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
  263. DFBWindowOptions wopts;
  264. SDL_DFB_CHECK(windata->dfbwin->GetPosition(windata->dfbwin,
  265. &windata->restore.x, &windata->restore.y));
  266. SDL_DFB_CHECK(windata->dfbwin->GetSize(windata->dfbwin, &windata->restore.w,
  267. &windata->restore.h));
  268. DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
  269. SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, 0, 0));
  270. SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin,
  271. display->current_mode.w, display->current_mode.h));
  272. /* Set Options */
  273. SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
  274. wopts |= DWOP_KEEP_SIZE | DWOP_KEEP_POSITION;
  275. SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
  276. }
  277. void
  278. DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
  279. {
  280. /* FIXME: Size to 32x32 ? */
  281. SDL_Unsupported();
  282. }
  283. void
  284. DirectFB_RestoreWindow(_THIS, SDL_Window * window)
  285. {
  286. SDL_DFB_WINDOWDATA(window);
  287. DFBWindowOptions wopts;
  288. /* Set Options */
  289. SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
  290. wopts &= ~(DWOP_KEEP_SIZE | DWOP_KEEP_POSITION);
  291. SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
  292. /* Window layout */
  293. DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED),
  294. windata->restore.w, windata->restore.h);
  295. SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin, windata->restore.w,
  296. windata->restore.h));
  297. SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, windata->restore.x,
  298. windata->restore.y));
  299. if (!(window->flags & SDL_WINDOW_RESIZABLE))
  300. wopts |= DWOP_KEEP_SIZE;
  301. if (window->flags & SDL_WINDOW_FULLSCREEN)
  302. wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_SIZE;
  303. SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
  304. }
  305. void
  306. DirectFB_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
  307. {
  308. SDL_DFB_DEVICEDATA(_this);
  309. SDL_DFB_WINDOWDATA(window);
  310. DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
  311. if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
  312. if (gwindata != NULL)
  313. {
  314. SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
  315. SDL_DFB_CHECK(gwindata->dfbwin->UngrabKeyboard(gwindata->dfbwin));
  316. }
  317. SDL_DFB_CHECK(windata->dfbwin->GrabPointer(windata->dfbwin));
  318. SDL_DFB_CHECK(windata->dfbwin->GrabKeyboard(windata->dfbwin));
  319. devdata->grabbed_window = window;
  320. } else {
  321. SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
  322. SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
  323. devdata->grabbed_window = NULL;
  324. }
  325. }
  326. void
  327. DirectFB_DestroyWindow(_THIS, SDL_Window * window)
  328. {
  329. SDL_DFB_DEVICEDATA(_this);
  330. SDL_DFB_WINDOWDATA(window);
  331. DFB_WindowData *p;
  332. /* Some cleanups */
  333. SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
  334. SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
  335. #if SDL_DIRECTFB_OPENGL
  336. DirectFB_GL_DestroyWindowContexts(_this, window);
  337. #endif
  338. if (window->shaper)
  339. {
  340. SDL_ShapeData *data = window->shaper->driverdata;
  341. SDL_DFB_CHECK(data->surface->ReleaseSource(data->surface));
  342. SDL_DFB_RELEASE(data->surface);
  343. SDL_DFB_FREE(data);
  344. SDL_DFB_FREE(window->shaper);
  345. }
  346. SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, NULL));
  347. SDL_DFB_CHECK(windata->surface->ReleaseSource(windata->surface));
  348. SDL_DFB_CHECK(windata->window_surface->ReleaseSource(windata->window_surface));
  349. SDL_DFB_RELEASE(windata->icon);
  350. SDL_DFB_RELEASE(windata->font);
  351. SDL_DFB_RELEASE(windata->eventbuffer);
  352. SDL_DFB_RELEASE(windata->surface);
  353. SDL_DFB_RELEASE(windata->window_surface);
  354. SDL_DFB_RELEASE(windata->dfbwin);
  355. /* Remove from list ... */
  356. p = devdata->firstwin->driverdata;
  357. while (p && p->next != window)
  358. p = (p->next ? p->next->driverdata : NULL);
  359. if (p)
  360. p->next = windata->next;
  361. else
  362. devdata->firstwin = windata->next;
  363. SDL_free(windata);
  364. return;
  365. }
  366. SDL_bool
  367. DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
  368. struct SDL_SysWMinfo * info)
  369. {
  370. SDL_DFB_DEVICEDATA(_this);
  371. SDL_DFB_WINDOWDATA(window);
  372. if (info->version.major == SDL_MAJOR_VERSION &&
  373. info->version.minor == SDL_MINOR_VERSION) {
  374. info->subsystem = SDL_SYSWM_DIRECTFB;
  375. info->info.dfb.dfb = devdata->dfb;
  376. info->info.dfb.window = windata->dfbwin;
  377. info->info.dfb.surface = windata->surface;
  378. return SDL_TRUE;
  379. } else {
  380. SDL_SetError("Application not compiled with SDL %d.%d",
  381. SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
  382. return SDL_FALSE;
  383. }
  384. }
  385. void
  386. DirectFB_AdjustWindowSurface(SDL_Window * window)
  387. {
  388. SDL_DFB_WINDOWDATA(window);
  389. int adjust = windata->wm_needs_redraw;
  390. int cw, ch;
  391. DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
  392. SDL_DFB_CHECKERR(windata->
  393. window_surface->GetSize(windata->window_surface, &cw,
  394. &ch));
  395. if (cw != windata->size.w || ch != windata->size.h) {
  396. adjust = 1;
  397. }
  398. if (adjust) {
  399. #if SDL_DIRECTFB_OPENGL
  400. DirectFB_GL_FreeWindowContexts(SDL_GetVideoDevice(), window);
  401. #endif
  402. #if (DFB_VERSION_ATLEAST(1,2,1))
  403. SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
  404. windata->size.w,
  405. windata->size.h));
  406. SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
  407. windata->
  408. window_surface,
  409. &windata->client));
  410. #else
  411. DFBWindowOptions opts;
  412. SDL_DFB_CHECKERR(windata->dfbwin->GetOptions(windata->dfbwin, &opts));
  413. /* recreate subsurface */
  414. SDL_DFB_RELEASE(windata->surface);
  415. if (opts & DWOP_SCALE)
  416. SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
  417. windata->size.w,
  418. windata->size.h));
  419. SDL_DFB_CHECKERR(windata->window_surface->
  420. GetSubSurface(windata->window_surface,
  421. &windata->client, &windata->surface));
  422. #endif
  423. DirectFB_WM_RedrawLayout(SDL_GetVideoDevice(), window);
  424. #if SDL_DIRECTFB_OPENGL
  425. DirectFB_GL_ReAllocWindowContexts(SDL_GetVideoDevice(), window);
  426. #endif
  427. }
  428. error:
  429. return;
  430. }
  431. int
  432. DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
  433. {
  434. const Uint8 alpha = (Uint8) ((unsigned int) (opacity * 255.0f));
  435. SDL_DFB_WINDOWDATA(window);
  436. SDL_DFB_CHECKERR(windata->dfbwin->SetOpacity(windata->dfbwin, alpha));
  437. windata->opacity = alpha;
  438. return 0;
  439. error:
  440. return -1;
  441. }
  442. #endif /* SDL_VIDEO_DRIVER_DIRECTFB */