[SDL_Tizen] Delete LGPL files
[platform/upstream/SDL.git] / src / video / tizen / SDL_tizenwindow.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4   Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
5
6   This software is provided 'as-is', without any express or implied
7   warranty.  In no event will the authors be held liable for any damages
8   arising from the use of this software.
9
10   Permission is granted to anyone to use this software for any purpose,
11   including commercial applications, and to alter it and redistribute it
12   freely, subject to the following restrictions:
13
14   1. The origin of this software must not be misrepresented; you must not
15      claim that you wrote the original software. If you use this software
16      in a product, an acknowledgment in the product documentation would be
17      appreciated but is not required.
18   2. Altered source versions must be plainly marked as such, and must not be
19      misrepresented as being the original software.
20   3. This notice may not be removed or altered from any source distribution.
21 */
22
23 #include "../../SDL_internal.h"
24
25 #if SDL_VIDEO_DRIVER_TIZEN
26
27 #include "SDL_log.h"
28 #include "SDL_hints.h"
29 #include "SDL_loadso.h"
30
31 #include "SDL_tizenvideo.h"
32 #include "SDL_tizentouch.h"
33 #include "SDL_tizenkeyboard.h"
34 #include "SDL_tizenmouse.h"
35 #include "SDL_tizenevents_c.h"
36
37 #include "SDL_tizenwindow.h"
38 #include "SDL_tizenopengles.h"
39
40 #include "../../events/SDL_mouse_c.h"
41 #include "../../joystick/tizen/SDL_sysjoystick_c.h"
42
43 #include "../SDL_egl_c.h"
44 #include "../SDL_vulkan_c.h"
45 #include "../SDL_sysvideo.h"
46 #include "../../events/SDL_windowevents_c.h"
47
48 enum {
49     ROTATION_TYPE_NORMAL_ROTATION = 0,
50     ROTATION_TYPE_PRE_ROTATION,      /* use pre-rotation */
51 };
52
53 #define LOAD_FUNC(NAME) \
54 _this->tizen_pre_rotation_data->NAME = SDL_LoadFunction(_this->tizen_pre_rotation_data->prerotation_dll_handle, #NAME); \
55 if (!_this->tizen_pre_rotation_data->NAME) \
56 { \
57     SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Could not retrieve pre-rotation function " #NAME); \
58     return SDL_FALSE; \
59 }
60
61 static int
62 _tizen_rotation_type_get()
63 {
64     static int type = ROTATION_TYPE_PRE_ROTATION;
65     static int checked = 0;
66     char *engine = NULL;
67
68     if (checked) return type;
69
70     engine = getenv("SDL_ROTATION");
71
72     if (engine)
73       {
74          if ((!strcasecmp(engine, "normal")))
75             type = ROTATION_TYPE_NORMAL_ROTATION;
76          else if ((!strcasecmp(engine, "pre_rotation")))
77             type = ROTATION_TYPE_PRE_ROTATION;
78          else
79             type = ROTATION_TYPE_PRE_ROTATION;
80       }
81     checked = 1;
82     return type;
83 }
84
85 int
86 _tizen_PreRotatotion_LoadLibrary(SDL_WindowData *_this, const char *lib_path)
87 {
88     void *lib_dll_handle = NULL;
89     char *path = NULL;
90
91     if (_this->isLoaded_pre_rotation)
92         return SDL_TRUE;
93
94     _this->tizen_pre_rotation_data = (Tizen_Prerotation_Data *) SDL_calloc(1, sizeof(Tizen_Prerotation_Data));
95     if (!_this->tizen_pre_rotation_data) {
96         return SDL_OutOfMemory();
97     }
98
99     if (!lib_path)
100         lib_dll_handle = SDL_LoadObject(lib_path);
101
102     if (!lib_dll_handle) {
103         path = "libwayland-egl.so";
104         lib_dll_handle = SDL_LoadObject(path);
105     }
106
107     _this->tizen_pre_rotation_data->prerotation_dll_handle = lib_dll_handle;
108
109     if (lib_dll_handle == NULL)
110         return SDL_FALSE;
111
112     LOAD_FUNC(wl_egl_window_set_rotation);
113     LOAD_FUNC(wl_egl_window_get_capabilities);
114     _this->isLoaded_pre_rotation = 1;
115
116     return SDL_TRUE;
117 }
118
119 SDL_bool
120 Tizen_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
121 {
122     SDL_WindowData *wmdata = (SDL_WindowData *)window->driverdata;
123     info->info.tizen.egl_display = NULL;
124     info->info.tizen.egl_surface = NULL;
125 #if SDL_VIDEO_OPENGL_EGL
126     if (_this->egl_data)
127     {
128        info->info.tizen.egl_display = (void*)_this->egl_data->egl_display;
129     }
130     info->info.tizen.egl_surface = (void*)wmdata->egl_surface;
131 #endif
132     info->subsystem = SDL_SYSWM_TIZEN;
133     return SDL_TRUE;
134 }
135
136 int
137 Tizen_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
138 {
139     return 0;  /* just succeed, the real work is done elsewhere. */
140 }
141
142 void
143 Tizen_ShowWindow(_THIS, SDL_Window *window)
144 {
145     SDL_WindowData *wind = window->driverdata;
146
147     if((window->flags & SDL_WINDOW_FULLSCREEN) || (window->flags & SDL_WINDOW_BORDERLESS))
148     {
149         ecore_wl_window_indicator_state_set(wind->window, ECORE_WL_INDICATOR_STATE_OFF);
150         ecore_wl_window_indicator_opacity_set(wind->window, ECORE_WL_INDICATOR_TRANSPARENT);
151         ecore_wl_indicator_visible_type_set(wind->window, ECORE_WL_INDICATOR_VISIBLE_TYPE_HIDDEN);
152     }
153     else
154     {
155         ecore_wl_window_indicator_state_set(wind->window, ECORE_WL_INDICATOR_STATE_ON);
156         ecore_wl_window_indicator_opacity_set(wind->window, ECORE_WL_INDICATOR_OPAQUE);
157         ecore_wl_indicator_visible_type_set(wind->window, ECORE_WL_INDICATOR_VISIBLE_TYPE_SHOWN);
158     }
159     ecore_wl_window_show(wind->window);
160 }
161
162 void
163 Tizen_SetWindowFullscreen(_THIS, SDL_Window *window,
164                           SDL_VideoDisplay *_display, SDL_bool fullscreen)
165 {
166     /*DO NOTHING*/
167 }
168
169 void
170 Tizen_pre_rotation_set(SDL_WindowData *_this)
171 {
172     tizen_wl_egl_window_rotation rot;
173     if (!_this->egl_window) return;
174
175     switch (_this->rotation) {
176          case 90:
177             rot = TIZEN_ROTATION_270;
178             break;
179          case 180:
180             rot = TIZEN_ROTATION_180;
181             break;
182          case 270:
183             rot = TIZEN_ROTATION_90;
184             break;
185          case 0:
186             rot = TIZEN_ROTATION_0;
187             break;
188          default:
189             rot = TIZEN_ROTATION_0;
190             break;
191       }
192
193       _this->tizen_pre_rotation_data->wl_egl_window_set_rotation(_this->egl_window, rot);
194 }
195
196 void
197 _tizen_window_orientaiton_hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue)
198 {
199     char *p_str = NULL;
200     char orientation_type[4][20] = {"Portrait","LandscapeLeft","PortraitUpsideDown","LandscapeRight"};
201     int checked[4] = {0,};
202     int i;
203     unsigned int j = 0;
204     SDL_WindowData *wind = (SDL_WindowData*)userdata;
205     Ecore_Wl_Window *window = wind->window;
206
207     if (wind->rotation_supported == 0) {
208         return;
209     }
210
211     SDL_assert(SDL_strncmp(name, SDL_HINT_ORIENTATIONS, SDL_strlen(SDL_HINT_ORIENTATIONS)) == 0);
212
213     if ((oldValue == NULL) && (newValue == NULL)) {
214         return;
215     }
216
217     for (i=0;i<4;i++) {
218         p_str = SDL_strstr(newValue, orientation_type[i]);
219         if (p_str) {
220             if (p_str == newValue) {
221                 int rot = 0;
222                 if (i == 0) rot = 0;
223                 else if (i == 1) rot = 90;
224                 else if (i == 2) rot = 180;
225                 else if (i == 3) rot = 270;
226                 wind->rotation = rot;
227             }
228
229             if (i == 0) {
230                 checked[j] = 0;
231             }
232             else if (i == 1) {
233                 checked[j] = 90;
234             }
235             else if (i == 2) {
236                 checked[j] = 180;
237             }
238             else if (i == 3) {
239                 checked[j] = 270;
240             }
241             j++;
242         }
243     }
244
245     if (j > 0) {
246         if (j == 1) {
247             ecore_wl_window_rotation_preferred_rotation_set(window,wind->rotation);
248             if (wind->support_pre_rotation)
249                 Tizen_pre_rotation_set(wind);
250         }else {
251             ecore_wl_window_rotation_available_rotations_set(window, (const int*)checked, j);
252         }
253     }
254 }
255
256 void
257 _tizen_window_orientation_add_hint(void *data)
258 {
259     SDL_WindowData *wind = (SDL_WindowData*)data;
260     if (wind->rotation_supported == 0) {
261         return;
262     }
263
264     SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, _tizen_window_orientaiton_hint_callback, data);
265 }
266
267 int
268 Tizen_CreateWindow(_THIS, SDL_Window *window)
269 {
270     SDL_VideoData *data = _this->driverdata;
271     SDL_WindowData *wind;
272     Ecore_Wl_Global *global;
273     Eina_Inlist *globals;
274
275     wind = calloc(1, sizeof * wind);
276     if (!wind) {
277         return SDL_OutOfMemory();
278     }
279
280     window->driverdata = wind;
281     window->flags |= SDL_WINDOW_INPUT_FOCUS;    /* always has input focus */
282
283 #if SDL_VIDEO_OPENGL_EGL
284     if (window->flags & SDL_WINDOW_OPENGL) {
285         SDL_GL_LoadLibrary(NULL);
286     }
287 #endif
288
289 #if SDL_VIDEO_VULKAN
290     if (window->flags & SDL_WINDOW_VULKAN) {
291         if (!_this->vulkan_GetInstanceExtensions) {
292             SDL_SetError("No Vulkan support in video driver");
293         }
294
295         if (_this->vulkan_LoadLibrary(_this, NULL) < 0) {
296             SDL_SetError("Fail to load Vulkan Library");
297         }
298     }
299 #endif
300
301     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
302         window->x = 0;
303     }
304     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
305         window->y = 0;
306     }
307
308     if (!(globals = ecore_wl_globals_get()))
309       {
310          SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Failed to get wayland globals");
311          return -1;
312       }
313
314     wind->window = ecore_wl_window_new(NULL,
315                                        window->x, window->y, window->w, window->h,
316                                        ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
317     wind->surface = ecore_wl_window_surface_create(wind->window);
318     ecore_wl_window_type_set(wind->window, ECORE_WL_WINDOW_TYPE_UTILITY);
319
320     wind->rotation = 0;
321     wind->rotation_supported = 0;
322     wind->received_rotation = 0;
323
324 #if SDL_VIDEO_OPENGL_EGL
325     if (window->flags & SDL_WINDOW_OPENGL) {
326         wind->egl_window = wl_egl_window_create(ecore_wl_window_surface_get(wind->window), window->w, window->h);
327
328         /* Create the GLES window surface */
329         wind->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wind->egl_window);
330         if (wind->egl_surface == EGL_NO_SURFACE) {
331             SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "failed to create a window surface");
332             return -1;
333         }
334
335         if (!Tizen_GLES_GetAlphaSize(_this)) {
336             ecore_wl_window_opaque_region_set(wind->window, window->x, window->y, window->w, window->h);
337         }
338         else {
339             wl_surface_set_opaque_region(ecore_wl_window_surface_get(wind->window), NULL);
340         }
341
342         //Support PreRotation
343         wind->support_pre_rotation = 0;
344         if (_tizen_rotation_type_get() && _tizen_PreRotatotion_LoadLibrary(wind, "libwayland-egl.so")) {
345             if (wind->tizen_pre_rotation_data->wl_egl_window_get_capabilities(wind->egl_window) == TIZEN_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) {
346                 wind->support_pre_rotation = 1;
347             }
348         }
349     }
350 #endif
351
352     wind->id = ecore_wl_window_id_get(wind->window);
353     eina_hash_add(data->windows, &wind->id, window);
354
355     Tizen_InitKeyboard(_this);
356     SDL_SetMouseFocus(window);
357
358     if (window->flags & 0x00008000) {
359         ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
360         ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
361     }
362
363     EINA_INLIST_FOREACH(globals, global) {
364          if (!strcmp(global->interface, "tizen_policy_ext")) {
365               wind->rotation_supported = 1;
366               break;
367            }
368       }
369     // Add orientaiton hint cb
370     _tizen_window_orientation_add_hint((void*)wind);
371
372
373     return 0;
374 }
375
376 void
377 Tizen_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
378 {
379 //Add setting window bordered.
380 }
381
382 void
383 _tizen_window_resize(SDL_Window *window)
384 {
385     SDL_WindowData *wind = window->driverdata;
386     if (!wind->egl_window) {
387         return;
388     }
389
390     if(wind->support_pre_rotation && (wind->rotation==90 || wind->rotation==270))
391         ecore_wl_window_update_size(wind->window, window->h, window->w);
392     else
393         ecore_wl_window_update_size(wind->window, window->w, window->h);
394
395     // TODO : consider to rotation status.
396 #if SDL_VIDEO_OPENGL_EGL
397     if (window->flags & SDL_WINDOW_OPENGL) {
398       if(wind->support_pre_rotation && (wind->rotation==90 || wind->rotation==270))
399           wl_egl_window_resize(wind->egl_window, window->h, window->w, 0, 0);
400       else
401           wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
402     }
403 #endif
404 }
405
406 void
407 _tizen_setwindowsize(SDL_Window *window)
408 {
409     SDL_WindowData *wind = window->driverdata;
410     if (!wind->window) {
411         return;
412     }
413 }
414
415 void
416 Tizen_SetWindowSize(_THIS, SDL_Window *window)
417 {
418     _tizen_window_resize(window);
419 }
420
421 void
422 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
423 {
424     SDL_WindowData *wind = window->driverdata;
425     if (!wind->window) {
426         return;
427     }
428
429     if (w) *w = window->w;
430     if (h) *h = window->h;
431 }
432
433 void
434 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
435 {
436     SDL_WindowData *wind = window->driverdata;
437     if (!wind->window) {
438         return;
439     }
440
441     // TODO : consider to rotation status.
442    ecore_wl_window_position_set(wind->window, window->x, window->y);
443 }
444
445 void
446 Tizen_DestroyWindow(_THIS, SDL_Window *window)
447 {
448     SDL_VideoData *data = _this->driverdata;
449     SDL_WindowData *wind = window->driverdata;
450
451     if (data) {
452         eina_hash_del(data->windows, &wind->id, window);
453 #if SDL_VIDEO_OPENGL_EGL
454     if (window->flags & SDL_WINDOW_OPENGL) {
455         SDL_EGL_DestroySurface(_this, wind->egl_surface);
456         wl_egl_window_destroy(wind->egl_window);
457     }
458 #endif
459         ecore_wl_window_free(wind->window);
460         SDL_free(wind);
461     }
462
463     window->driverdata = NULL;
464 }
465
466 SDL_Window*
467 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
468 {
469     SDL_VideoData *data = _this->driverdata;
470     int id;
471
472     id = ecore_wl_window_id_get(ewin);
473     return (SDL_Window*)eina_hash_find(data->windows, &id);
474 }
475
476 Eina_Bool
477 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
478 {
479     _THIS = data;
480     Ecore_Wl_Event_Window_Visibility_Change *ev;
481     Ecore_Wl_Window *ew;
482     SDL_Window *window;
483
484     ev = event;
485     ew = ecore_wl_window_find(ev->win);
486     window = Tizen_FindWindow(_this, ew);
487
488     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
489     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
490     return ECORE_CALLBACK_PASS_ON;
491 }
492
493 Eina_Bool
494 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
495 {
496    _THIS = data;
497    Ecore_Wl_Window *ew;
498    SDL_Window *window;
499    SDL_WindowData *wind;
500    Ecore_Wl_Event_Window_Configure *ev;
501    ev = event;
502    ew = ecore_wl_window_find(ev->win);
503    window = Tizen_FindWindow(_this, ew);
504    wind = window->driverdata;
505
506    if (wind->rotation_supported == 0){
507       return ECORE_CALLBACK_PASS_ON;
508    }
509 /*
510    int nx = 0, ny = 0, nw = 0, nh = 0;
511   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
512
513    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
514    if (nw < 1) nw = 1;
515    if (nh < 1) nh = 1;
516    
517    SDL_Log("[SDL_Size] * _tizen_cb_window_configure :: w->w:%d, w->h:%d, nw:%d, nh:%d", window->w, window->h, nw, nh);
518    if ((window->x != nx) || (window->y != ny))
519      ecore_wl_window_position_set(ew, nx, ny);
520
521    if ((window->w != nw) || (window->h != nh)) {
522      _tizen_setwindowsize(window);
523    }
524    */
525    return ECORE_CALLBACK_PASS_ON;
526 }
527
528
529 void
530 _tizen_send_rotation_event(SDL_Window *window, unsigned int angle)
531 {
532     SDL_Event event;
533     SDL_WindowData *wind;
534     wind = window->driverdata;
535
536     SDL_memset(&event, 0, sizeof(event));
537     event.type = SDL_ROTATEEVENT;
538     event.user.code = 0;
539     if (wind->support_pre_rotation)
540         event.user.data1 = (void*)0;
541     else
542         event.user.data1 = (void*)angle;
543     event.user.data2 = (void*)-1;
544
545     SDL_PushEvent(&event);
546     return;
547 }
548
549 void
550 _tizen_set_window_size(SDL_Window * window, int w, int h)
551 {
552     if(!window)
553     {
554         SDL_SetError("Invalid window");
555         return;
556     }
557
558     SDL_VideoDevice *_this = SDL_GetVideoDevice();
559     if (!_this) {
560         SDL_SetError("Video subsystem has not been initialized");
561         return;
562     }
563
564     if (window->magic != &_this->window_magic) {
565         return;
566     }
567
568     if (w <= 0) {
569         SDL_InvalidParamError("w");
570         return;
571     }
572     if (h <= 0) {
573         SDL_InvalidParamError("h");
574         return;
575     }
576
577     /* Make sure we don't exceed any window size limits */
578     if (window->min_w && w < window->min_w)
579     {
580         w = window->min_w;
581     }
582     if (window->max_w && w > window->max_w)
583     {
584         w = window->max_w;
585     }
586     if (window->min_h && h < window->min_h)
587     {
588         h = window->min_h;
589     }
590     if (window->max_h && h > window->max_h)
591     {
592         h = window->max_h;
593     }
594
595     window->windowed.w = w;
596     window->windowed.h = h;
597
598     window->w = w;
599     window->h = h;
600 }
601
602 Eina_Bool
603 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
604 {
605     _THIS = data;
606     Ecore_Wl_Event_Window_Rotate *ev;
607     Ecore_Wl_Window *ew;
608     SDL_Window *window;
609     SDL_WindowData *wind;
610
611     ev = event;
612     if (!ev) {
613         return ECORE_CALLBACK_PASS_ON;
614     }
615
616     ew = ecore_wl_window_find(ev->win);
617     window = Tizen_FindWindow(_this, ew);
618     wind = window->driverdata;
619
620     if (wind->rotation != ev->angle) {
621         /* set ecore_wayland window rotation */
622         wind->rotation = ev->angle;
623         ecore_wl_window_rotation_set(ew, ev->angle);
624         if(wind->support_pre_rotation) {
625             int window_w, window_h;
626             if(wind->rotation==90 || wind->rotation==270)
627                 ecore_wl_window_geometry_get(wind->window, 0, 0, &window_h, &window_w);
628             else
629                 ecore_wl_window_geometry_get(wind->window, 0, 0, &window_w, &window_h);
630
631             _tizen_set_window_size(window, window_w, window_h);
632             Tizen_pre_rotation_set(wind);
633         }
634         _tizen_send_rotation_event(window, ev->angle);
635         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
636         wind->received_rotation = 1;
637     }
638
639     return ECORE_CALLBACK_PASS_ON;
640 }
641
642 int
643 Tizen_InitWindow(_THIS)
644 {
645     SDL_VideoData *data = _this->driverdata;
646
647     data->windows = eina_hash_int32_new(NULL);
648
649     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
650                         _tizen_cb_event_window_visibility_change,_this);
651     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
652                         _tizen_cb_event_keyup_change,_this);
653     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
654                         _tizen_cb_event_keydown_change,_this);
655     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
656                         _tizen_cb_event_mousedown_change,_this);
657     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
658                         _tizen_cb_event_mouseup_change,_this);
659     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
660                         _tizen_cb_event_mousemove_change,_this);
661     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
662                         _tizen_cb_event_window_rotate,_this);
663     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
664                         _tizen_cb_window_configure,_this);
665     ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
666                         _tizen_cb_event_joystick_change,_this);
667     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
668                         _tizen_cb_event_focus_in,_this);
669     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
670                         _tizen_cb_event_focus_out,_this);
671     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
672                         _tizen_cb_event_mouse_in,_this);
673     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
674                         _tizen_cb_event_mouse_out,_this);
675
676     data->current_thread = SDL_GetThreadID(0);
677
678     return 0;
679 }
680
681 void
682 Tizen_DeinitWindow(_THIS)
683 {
684     SDL_VideoData *data = _this->driverdata;
685
686     eina_hash_free(data->windows);
687 }
688 #endif /* SDL_VIDEO_DRIVER_TIZEN */
689
690 /* vi: set ts=4 sw=4 expandtab: */