[SDL_TIZEN] code clean up
[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_tizenindicator.h"
32
33 #include "SDL_tizenvideo.h"
34 #include "SDL_tizentouch.h"
35 #include "SDL_tizenkeyboard.h"
36 #include "SDL_tizenmouse.h"
37 #include "SDL_tizenevents_c.h"
38
39 #include "SDL_tizenwindow.h"
40
41 #include "../../events/SDL_mouse_c.h"
42 #include "../../joystick/tizen/SDL_sysjoystick_c.h"
43
44 #include "../SDL_egl_c.h"
45 #include "../SDL_sysvideo.h"
46 #include "../../events/SDL_windowevents_c.h"
47
48 #define LOAD_FUNC(NAME) \
49 _this->tizen_pre_rotation_data->NAME = SDL_LoadFunction(_this->tizen_pre_rotation_data->prerotation_dll_handle, #NAME); \
50 if (!_this->tizen_pre_rotation_data->NAME) \
51 { \
52     SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Could not retrieve pre-rotation function " #NAME); \
53     return SDL_FALSE; \
54 }
55
56 int
57 _tizen_PreRotatotion_LoadLibrary(SDL_WindowData *_this, const char *lib_path)
58 {
59     void *lib_dll_handle = NULL;
60     char *path = NULL;
61
62     if (_this->isLoaded_pre_rotation)
63         return SDL_TRUE;
64
65     _this->tizen_pre_rotation_data = (Tizen_Prerotation_Data *) SDL_calloc(1, sizeof(Tizen_Prerotation_Data));
66     if (!_this->tizen_pre_rotation_data) {
67         return SDL_OutOfMemory();
68     }
69
70     if (!lib_path)
71         lib_dll_handle = SDL_LoadObject(lib_path);
72
73     if (!lib_dll_handle) {
74         path = "libwayland-egl.so";
75         lib_dll_handle = SDL_LoadObject(path);
76     }
77
78     _this->tizen_pre_rotation_data->prerotation_dll_handle = lib_dll_handle;
79
80     if (lib_dll_handle == NULL)
81         return SDL_FALSE;
82
83     LOAD_FUNC(wl_egl_window_set_rotation);
84     LOAD_FUNC(wl_egl_window_get_capabilities);
85     _this->isLoaded_pre_rotation = 1;
86
87     return SDL_TRUE;
88 }
89
90 SDL_bool
91 Tizen_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
92 {
93     SDL_WindowData *wmdata = (SDL_WindowData *)window->driverdata;
94     info->info.tizen.egl_display = NULL;
95     info->info.tizen.egl_surface = NULL;
96 #if SDL_VIDEO_OPENGL_EGL
97     if (_this->egl_data)
98     {
99        info->info.tizen.egl_display = (void*)_this->egl_data->egl_display;
100     }
101     info->info.tizen.egl_surface = (void*)wmdata->egl_surface;
102 #endif
103     info->subsystem = SDL_SYSWM_TIZEN;
104     return SDL_TRUE;
105 }
106
107 int
108 Tizen_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
109 {
110     return 0;  /* just succeed, the real work is done elsewhere. */
111 }
112
113 void
114 Tizen_ShowWindow(_THIS, SDL_Window *window)
115 {
116     SDL_WindowData *wind = window->driverdata;
117     ecore_wl_window_show(wind->window);
118 }
119
120 void
121 Tizen_SetWindowFullscreen(_THIS, SDL_Window *window,
122                           SDL_VideoDisplay *_display, SDL_bool fullscreen)
123 {
124     /*DO NOTHING*/
125 }
126
127 void
128 _tizen_pre_rotation_set(SDL_WindowData *_this)
129 {
130     tizen_wl_egl_window_rotation rot;
131     if (!_this->egl_window) return;
132
133     switch (_this->rotation) {
134          case 90:
135             rot = TIZEN_ROTATION_270;
136             break;
137          case 180:
138             rot = TIZEN_ROTATION_180;
139             break;
140          case 270:
141             rot = TIZEN_ROTATION_90;
142             break;
143          case 0:
144             rot = TIZEN_ROTATION_0;
145             break;
146          default:
147             rot = TIZEN_ROTATION_0;
148             break;
149       }
150
151       _this->tizen_pre_rotation_data->wl_egl_window_set_rotation(_this->egl_window, rot);
152 }
153
154 void
155 _tizen_window_orientaiton_hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue)
156 {
157     char *p_str = NULL;
158     char orientation_type[4][20] = {"Portrait","LandscapeLeft","PortraitUpsideDown","LandscapeRight"};
159     int checked[4] = {0,};
160     int i;
161     unsigned int j = 0;
162     SDL_WindowData *wind = (SDL_WindowData*)userdata;
163     Ecore_Wl_Window *window = wind->window;
164
165     if (wind->rotation_supported == 0) {
166         return;
167     }
168
169     SDL_assert(SDL_strncmp(name, SDL_HINT_ORIENTATIONS, SDL_strlen(SDL_HINT_ORIENTATIONS)) == 0);
170
171     if ((oldValue == NULL) && (newValue == NULL)) {
172         return;
173     }
174
175     for (i=0;i<4;i++) {
176         p_str = SDL_strstr(newValue, orientation_type[i]);
177         if (p_str) {
178             if (p_str == newValue) {
179                 int rot = 0;
180                 if (i == 0) rot = 0;
181                 else if (i == 1) rot = 90;
182                 else if (i == 2) rot = 180;
183                 else if (i == 3) rot = 270;
184                 wind->rotation = rot;
185             }
186
187             if (i == 0) {
188                 checked[j] = 0;
189             }
190             else if (i == 1) {
191                 checked[j] = 90;
192             }
193             else if (i == 2) {
194                 checked[j] = 180;
195             }
196             else if (i == 3) {
197                 checked[j] = 270;
198             }
199             j++;
200         }
201     }
202
203     if (j > 0) {
204         if (j == 1) {
205             ecore_wl_window_rotation_preferred_rotation_set(window,wind->rotation);
206             if (wind->support_pre_rotation) {
207                 _tizen_pre_rotation_set(wind);
208             }
209         }
210         ecore_wl_window_rotation_available_rotations_set(window, (const int*)checked, j);
211     }
212 }
213
214 void
215 _tizen_window_orientation_add_hint(void *data)
216 {
217     SDL_WindowData *wind = (SDL_WindowData*)data;
218     if (wind->rotation_supported == 0) {
219         return;
220     }
221
222     SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, _tizen_window_orientaiton_hint_callback, data);
223 }
224
225 int
226 Tizen_CreateWindow(_THIS, SDL_Window *window)
227 {
228     SDL_VideoData *data = _this->driverdata;
229     SDL_WindowData *wind;
230     Ecore_Wl_Global *global;
231     Eina_Inlist *globals;
232
233     wind = calloc(1, sizeof * wind);
234     if (!wind) {
235         return SDL_OutOfMemory();
236     }
237
238     window->driverdata = wind;
239     window->flags |= SDL_WINDOW_INPUT_FOCUS;    /* always has input focus */
240
241 #if SDL_VIDEO_OPENGL_EGL
242     if (window->flags & SDL_WINDOW_OPENGL) {
243         SDL_GL_LoadLibrary(NULL);
244     }
245 #endif
246
247     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
248         window->x = 0;
249     }
250     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
251         window->y = 0;
252     }
253
254     if (!(globals = ecore_wl_globals_get()))
255       {
256          SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Failed to get wayland globals");
257          return -1;
258       }
259
260     wind->window = ecore_wl_window_new(NULL,
261                                        window->x, window->y, window->w, window->h,
262                                        ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
263     wind->surface = ecore_wl_window_surface_create(wind->window);
264     wind->rotation = 0;
265     wind->rotation_supported = 0;
266     wind->received_rotation = 0;
267     ecore_wl_window_opaque_region_set(wind->window, window->x, window->y, window->w, window->h);
268
269 #if SDL_VIDEO_OPENGL_EGL
270     if (window->flags & SDL_WINDOW_OPENGL) {
271         wind->egl_window = wl_egl_window_create(ecore_wl_window_surface_get(wind->window), window->w, window->h);
272
273         /* Create the GLES window surface */
274         wind->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wind->egl_window);
275         if (wind->egl_surface == EGL_NO_SURFACE) {
276             SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "failed to create a window surface");
277             return -1;
278         }
279
280         //Support PreRotation
281         wind->support_pre_rotation = 0;
282         if (_tizen_PreRotatotion_LoadLibrary(wind, "libwayland-egl.so")) {
283             if (wind->tizen_pre_rotation_data->wl_egl_window_get_capabilities(wind->egl_window) == TIZEN_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) {
284                 wind->support_pre_rotation = 1;
285             }
286         }
287     }
288 #endif
289
290     wind->id = ecore_wl_window_id_get(wind->window);
291     eina_hash_add(data->windows, &wind->id, window);
292
293     Tizen_InitKeyboard(_this);
294     SDL_SetMouseFocus(window);
295
296     if (window->flags & 0x00008000) {
297         ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
298         ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
299     }
300
301     EINA_INLIST_FOREACH(globals, global) {
302          if (!strcmp(global->interface, "tizen_policy_ext")) {
303               wind->rotation_supported = 1;
304               break;
305            }
306       }
307     // Add orientaiton hint cb
308     _tizen_window_orientation_add_hint((void*)wind);
309
310     return 0;
311 }
312
313 void
314 _tizen_egl_window_resize(SDL_Window *window)
315 {
316     SDL_WindowData *wind = window->driverdata;
317     if (!wind->egl_window) {
318         return;
319     }
320
321     // TODO : consider to rotation status.
322 #if SDL_VIDEO_OPENGL_EGL
323     if (window->flags & SDL_WINDOW_OPENGL) {
324         // TODO : if window size is not FULL, we need the code about Non FullSize Window.
325         int aw, ah;
326         wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
327         wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
328     }
329 #endif
330
331 }
332
333 void
334 _tizen_setwindowsize(SDL_Window *window)
335 {
336     SDL_WindowData *wind = window->driverdata;
337     if (!wind->window) {
338         return;
339     }
340     ecore_wl_window_update_size(wind->window, window->w, window->h);
341 }
342
343 void
344 Tizen_SetWindowSize(_THIS, SDL_Window *window)
345 {
346 //    _tizen_setwindowsize(window);
347 //    _tizen_egl_window_resize(window);
348 }
349
350 void
351 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
352 {
353     SDL_WindowData *wind = window->driverdata;
354     if (!wind->window) {
355         return;
356     }
357
358     if (w) *w = window->w;
359     if (h) *h = window->h;
360 }
361
362 void
363 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
364 {
365     SDL_WindowData *wind = window->driverdata;
366     if (!wind->window) {
367         return;
368     }
369
370     // TODO : consider to rotation status.
371    ecore_wl_window_position_set(wind->window, window->x, window->y);
372 }
373
374 void
375 Tizen_DestroyWindow(_THIS, SDL_Window *window)
376 {
377     SDL_VideoData *data = _this->driverdata;
378     SDL_WindowData *wind = window->driverdata;
379
380     if (data) {
381         eina_hash_del(data->windows, &wind->id, window);
382 #if SDL_VIDEO_OPENGL_EGL
383     if (window->flags & SDL_WINDOW_OPENGL) {
384         SDL_EGL_DestroySurface(_this, wind->egl_surface);
385         wl_egl_window_destroy(wind->egl_window);
386     }
387 #endif
388         ecore_wl_window_free(wind->window);
389         SDL_free(wind);
390     }
391
392     window->driverdata = NULL;
393 }
394
395 SDL_Window*
396 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
397 {
398     SDL_VideoData *data = _this->driverdata;
399     int id;
400
401     id = ecore_wl_window_id_get(ewin);
402     return (SDL_Window*)eina_hash_find(data->windows, &id);
403 }
404
405 Eina_Bool
406 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
407 {
408     _THIS = data;
409     Ecore_Wl_Event_Window_Visibility_Change *ev;
410     Ecore_Wl_Window *ew;
411     SDL_Window *window;
412
413     ev = event;
414     ew = ecore_wl_window_find(ev->win);
415     window = Tizen_FindWindow(_this, ew);
416
417     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
418     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
419     return ECORE_CALLBACK_PASS_ON;
420 }
421
422 Eina_Bool
423 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
424 {
425    _THIS = data;
426    Ecore_Wl_Window *ew;
427    SDL_Window *window;
428    SDL_WindowData *wind;
429    Ecore_Wl_Event_Window_Configure *ev;
430    ev = event;
431    ew = ecore_wl_window_find(ev->win);
432    window = Tizen_FindWindow(_this, ew);
433    wind = window->driverdata;
434
435    if (wind->rotation_supported == 0){
436       return ECORE_CALLBACK_PASS_ON;
437    }
438 /*
439    int nx = 0, ny = 0, nw = 0, nh = 0;
440   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
441
442    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
443    if (nw < 1) nw = 1;
444    if (nh < 1) nh = 1;
445    
446    SDL_Log("[SDL_Size] * _tizen_cb_window_configure :: w->w:%d, w->h:%d, nw:%d, nh:%d", window->w, window->h, nw, nh);
447    if ((window->x != nx) || (window->y != ny))
448      ecore_wl_window_position_set(ew, nx, ny);
449
450    if ((window->w != nw) || (window->h != nh)) {
451      _tizen_setwindowsize(window);
452    }
453    */
454    return ECORE_CALLBACK_PASS_ON;
455 }
456
457
458 void
459 _tizen_send_rotation_event(SDL_Window *window, unsigned int angle)
460 {
461     SDL_Event event;
462     SDL_WindowData *wind;
463     wind = window->driverdata;
464
465     SDL_memset(&event, 0, sizeof(event));
466     event.type = SDL_ROTATEEVENT;
467     event.user.code = 0;
468     if (wind->support_pre_rotation)
469         event.user.data1 = (void*)0;
470     else
471         event.user.data1 = (void*)angle;
472     event.user.data2 = (void*)-1;
473
474     SDL_PushEvent(&event);
475     return;
476 }
477
478 Eina_Bool
479 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
480 {
481     _THIS = data;
482     Ecore_Wl_Event_Window_Rotate *ev;
483     Ecore_Wl_Window *ew;
484     SDL_Window *window;
485     SDL_WindowData *wind;
486
487     ev = event;
488     if (!ev) {
489         return ECORE_CALLBACK_PASS_ON;
490     }
491
492     ew = ecore_wl_window_find(ev->win);
493     window = Tizen_FindWindow(_this, ew);
494     wind = window->driverdata;
495
496     if (wind->rotation != ev->angle) {
497         /* set ecore_wayland window rotation */
498         wind->rotation = ev->angle;
499         ecore_wl_window_rotation_set(ew, ev->angle);
500
501         if(wind->support_pre_rotation) {
502             _tizen_pre_rotation_set(wind);
503
504             int aw, ah;
505             wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
506             wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
507
508             if(wind->rotation == 90 || wind->rotation == 270) {
509                 SDL_SetWindowSize(window, ah, aw);
510                 window->w = ah;//for Fullscreen
511                 window->h = aw;
512             } else {
513                 SDL_SetWindowSize(window, aw, ah);//->call wl_egl_window_resize()
514                 window->w = aw;//for Fullscreen
515                 window->h = ah;
516             }
517     }
518
519         // Send Rotation Event
520         _tizen_send_rotation_event(window, ev->angle);
521         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
522     }
523
524     wind->received_rotation = 1;
525     const char* hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
526     if(hint && *hint != '\0')
527         Tizen_IndicatorProcessEvent(_this->current_glwin, wind->rotation);
528
529     return ECORE_CALLBACK_PASS_ON;
530 }
531
532 int
533 Tizen_InitWindow(_THIS)
534 {
535     SDL_VideoData *data = _this->driverdata;
536
537     data->windows = eina_hash_int32_new(NULL);
538
539     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
540                         _tizen_cb_event_window_visibility_change,_this);
541     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
542                         _tizen_cb_event_keyup_change,_this);
543     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
544                         _tizen_cb_event_keydown_change,_this);
545     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
546                         _tizen_cb_event_mousedown_change,_this);
547     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
548                         _tizen_cb_event_mouseup_change,_this);
549     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
550                         _tizen_cb_event_mousemove_change,_this);
551     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
552                         _tizen_cb_event_window_rotate,_this);
553     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
554                         _tizen_cb_window_configure,_this);
555     ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
556                         _tizen_cb_event_joystick_change,_this);
557     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
558                         _tizen_cb_event_focus_in,_this);
559     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
560                         _tizen_cb_event_focus_out,_this);
561     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
562                         _tizen_cb_event_mouse_in,_this);
563     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
564                         _tizen_cb_event_mouse_out,_this);
565
566     data->current_thread = SDL_GetThreadID(0);
567
568     return 0;
569 }
570
571 void
572 Tizen_DeinitWindow(_THIS)
573 {
574     SDL_VideoData *data = _this->driverdata;
575
576     eina_hash_free(data->windows);
577 }
578 #endif /* SDL_VIDEO_DRIVER_TIZEN */
579
580 /* vi: set ts=4 sw=4 expandtab: */