[SDL_tizen] Modify pre-rotation enum type
[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_SetError("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     SDL_Log("%s with angle %d",__FUNCTION__, _this->rotation);
134     switch (_this->rotation) {
135          case 90:
136             rot = TIZEN_ROTATION_270;
137             break;
138          case 180:
139             rot = TIZEN_ROTATION_180;
140             break;
141          case 270:
142             rot = TIZEN_ROTATION_90;
143             break;
144          case 0:
145             rot = TIZEN_ROTATION_0;
146             break;
147          default:
148             rot = TIZEN_ROTATION_0;
149             break;
150       }
151
152       SDL_SetError("call wl_egl_win_set_rotation with rot %d",rot);
153       _this->tizen_pre_rotation_data->wl_egl_window_set_rotation(_this->egl_window, rot);
154 }
155
156 void
157 _tizen_window_orientaiton_hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue)
158 {
159     char *p_str = NULL;
160     char orientation_type[4][20] = {"Portrait","LandscapeLeft","PortraitUpsideDown","LandscapeRight"};
161     int checked[4] = {0,};
162     int i;
163     unsigned int j = 0;
164     SDL_WindowData *wind = (SDL_WindowData*)userdata;
165     Ecore_Wl_Window *window = wind->window;
166
167     if (wind->rotation_supported == 0) {
168         return;
169     }
170
171     SDL_assert(SDL_strncmp(name, SDL_HINT_ORIENTATIONS, SDL_strlen(SDL_HINT_ORIENTATIONS)) == 0);
172
173     if ((oldValue == NULL) && (newValue == NULL)) {
174         return;
175     }
176
177     for (i=0;i<4;i++) {
178         p_str = SDL_strstr(newValue, orientation_type[i]);
179         if (p_str) {
180             if (p_str == newValue) {
181                 int rot = 0;
182                 if (i == 0) rot = 0;
183                 else if (i == 1) rot = 90;
184                 else if (i == 2) rot = 180;
185                 else if (i == 3) rot = 270;
186                 wind->rotation = rot;
187             }
188
189             if (i == 0) {
190                 checked[j] = 0;
191                 SDL_Log("SDL  %s: avaiable rotation: 0", __FUNCTION__);
192             }
193             else if (i == 1) {
194                 checked[j] = 90;
195                 SDL_Log("SDL %s: avaiable rotation: 90", __FUNCTION__);
196             }
197             else if (i == 2) {
198                 checked[j] = 180;
199                 SDL_Log("SDL %s: avaiable rotation: 180", __FUNCTION__);
200             }
201             else if (i == 3) {
202                 checked[j] = 270;
203                 SDL_Log("SDL %s: avaiable rotation: 270", __FUNCTION__);
204             }
205             j++;
206         }
207     }
208
209     if (j > 0) {
210         if (j == 1) {
211             ecore_wl_window_rotation_preferred_rotation_set(window,wind->rotation);
212             SDL_Log("SDL %s: support pre_rotation %d", __FUNCTION__,wind->support_pre_rotation);
213             if (wind->support_pre_rotation) {
214                 SDL_Log("SDL %s: set pre rotation %d", __FUNCTION__,wind->rotation);
215                 _tizen_pre_rotation_set(wind);
216             }
217         }
218         ecore_wl_window_rotation_available_rotations_set(window, (const int*)checked, j);
219     }
220 }
221
222 void
223 _tizen_window_orientation_add_hint(void *data)
224 {
225     SDL_WindowData *wind = (SDL_WindowData*)data;
226     if (wind->rotation_supported == 0) {
227         return;
228     }
229
230     SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, _tizen_window_orientaiton_hint_callback, data);
231 }
232
233 int
234 Tizen_CreateWindow(_THIS, SDL_Window *window)
235 {
236     SDL_VideoData *data = _this->driverdata;
237     SDL_WindowData *wind;
238     Ecore_Wl_Global *global;
239     Eina_Inlist *globals;
240
241     wind = calloc(1, sizeof * wind);
242     if (!wind) {
243         return SDL_OutOfMemory();
244     }
245
246     window->driverdata = wind;
247     window->flags |= SDL_WINDOW_INPUT_FOCUS;    /* always has input focus */
248
249 #if SDL_VIDEO_OPENGL_EGL
250     if (window->flags & SDL_WINDOW_OPENGL) {
251         SDL_GL_LoadLibrary(NULL);
252     }
253 #endif
254
255     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
256         window->x = 0;
257     }
258     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
259         window->y = 0;
260     }
261
262     if (!(globals = ecore_wl_globals_get()))
263       {
264          SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get wayland globals");
265          return -1;
266       }
267
268     wind->window = ecore_wl_window_new(NULL,
269                                        window->x, window->y, window->w, window->h,
270                                        ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
271     wind->surface = ecore_wl_window_surface_create(wind->window);
272     wind->rotation = 0;
273     wind->rotation_supported = 0;
274     wind->received_rotation = 0;
275     ecore_wl_window_opaque_region_set(wind->window, window->x, window->y, window->w, window->h);
276
277 #if SDL_VIDEO_OPENGL_EGL
278     if (window->flags & SDL_WINDOW_OPENGL) {
279         wind->egl_window = wl_egl_window_create(ecore_wl_window_surface_get(wind->window), window->w, window->h);
280
281         /* Create the GLES window surface */
282         wind->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wind->egl_window);
283         if (wind->egl_surface == EGL_NO_SURFACE) {
284             SDL_SetError("failed to create a window surface");
285             return -1;
286         }
287
288         //Support PreRotation
289         wind->support_pre_rotation = 0;
290         if (_tizen_PreRotatotion_LoadLibrary(wind, "libwayland-egl.so")) {
291             if (wind->tizen_pre_rotation_data->wl_egl_window_get_capabilities(wind->egl_window) == TIZEN_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) {
292                 wind->support_pre_rotation = 1;
293                 SDL_Log("Can support PreRotation");
294             }
295             else {
296                 SDL_Log("can not support PreRotation !!");
297             }
298         }
299         else {
300             SDL_Log("can not support PreRotation !!");
301         }
302     }
303 #endif
304
305     wind->id = ecore_wl_window_id_get(wind->window);
306     eina_hash_add(data->windows, &wind->id, window);
307
308     Tizen_InitKeyboard(_this);
309     SDL_SetMouseFocus(window);
310
311     if (window->flags & 0x00008000) {
312         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "---------------------------------------");
313         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[SDL] touch bypass setting is done!\n");
314         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "---------------------------------------");
315         ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
316         ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
317     }
318
319     EINA_INLIST_FOREACH(globals, global) {
320          if (!strcmp(global->interface, "tizen_policy_ext")) {
321               wind->rotation_supported = 1;
322               SDL_Log("SDL can support rotation in this device!!!!!!!!!!!");
323               break;
324            }
325       }
326     // Add orientaiton hint cb
327     _tizen_window_orientation_add_hint((void*)wind);
328     return 0;
329 }
330
331 void
332 _tizen_egl_window_resize(SDL_Window *window)
333 {
334     SDL_WindowData *wind = window->driverdata;
335     if (!wind->egl_window) {
336         return;
337     }
338
339     // TODO : consider to rotation status.
340 #if SDL_VIDEO_OPENGL_EGL
341     if (window->flags & SDL_WINDOW_OPENGL) {
342         // TODO : if window size is not FULL, we need the code about Non FullSize Window.
343         int aw, ah;
344         wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
345         wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
346     }
347 #endif
348
349 }
350
351 void
352 _tizen_setwindowsize(SDL_Window *window)
353 {
354     SDL_WindowData *wind = window->driverdata;
355     if (!wind->window) {
356         return;
357     }
358     ecore_wl_window_update_size(wind->window, window->w, window->h);
359 }
360
361 void
362 Tizen_SetWindowSize(_THIS, SDL_Window *window)
363 {
364    SDL_Log("[SDL_Size] Tizen_SetWindowSize");
365 //    _tizen_setwindowsize(window);
366 //    _tizen_egl_window_resize(window);
367 }
368
369 void
370 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
371 {
372     SDL_WindowData *wind = window->driverdata;
373     if (!wind->window) {
374         return;
375     }
376
377     if (w) *w = window->w;
378     if (h) *h = window->h;
379 }
380
381 void
382 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
383 {
384     SDL_WindowData *wind = window->driverdata;
385     if (!wind->window) {
386         return;
387     }
388
389     // TODO : consider to rotation status.
390    ecore_wl_window_position_set(wind->window, window->x, window->y);
391 }
392
393 void
394 Tizen_DestroyWindow(_THIS, SDL_Window *window)
395 {
396     SDL_VideoData *data = _this->driverdata;
397     SDL_WindowData *wind = window->driverdata;
398
399     if (data) {
400         eina_hash_del(data->windows, &wind->id, window);
401 #if SDL_VIDEO_OPENGL_EGL
402     if (window->flags & SDL_WINDOW_OPENGL) {
403         SDL_EGL_DestroySurface(_this, wind->egl_surface);
404         wl_egl_window_destroy(wind->egl_window);
405     }
406 #endif
407         ecore_wl_window_free(wind->window);
408         SDL_free(wind);
409     }
410
411     window->driverdata = NULL;
412 }
413
414 SDL_Window*
415 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
416 {
417     SDL_VideoData *data = _this->driverdata;
418     int id;
419
420     id = ecore_wl_window_id_get(ewin);
421     return (SDL_Window*)eina_hash_find(data->windows, &id);
422 }
423
424 Eina_Bool
425 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
426 {
427     _THIS = data;
428     Ecore_Wl_Event_Window_Visibility_Change *ev;
429     Ecore_Wl_Window *ew;
430     SDL_Window *window;
431
432     ev = event;
433     ew = ecore_wl_window_find(ev->win);
434     window = Tizen_FindWindow(_this, ew);
435
436     SDL_Log( "visibility window: %p, ecore_wl_window: %p\n", window, ew);
437
438     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
439     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
440     return ECORE_CALLBACK_PASS_ON;
441 }
442
443 Eina_Bool
444 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
445 {
446    _THIS = data;
447    Ecore_Wl_Window *ew;
448    SDL_Window *window;
449    SDL_WindowData *wind;
450    Ecore_Wl_Event_Window_Configure *ev;
451    ev = event;
452    ew = ecore_wl_window_find(ev->win);
453    window = Tizen_FindWindow(_this, ew);
454    wind = window->driverdata;
455
456    if (wind->rotation_supported == 0){
457       return ECORE_CALLBACK_PASS_ON;
458    }
459 /*
460    int nx = 0, ny = 0, nw = 0, nh = 0;
461   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
462
463    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
464    if (nw < 1) nw = 1;
465    if (nh < 1) nh = 1;
466    
467    SDL_Log("[SDL_Size] * _tizen_cb_window_configure :: w->w:%d, w->h:%d, nw:%d, nh:%d", window->w, window->h, nw, nh);
468    if ((window->x != nx) || (window->y != ny))
469      ecore_wl_window_position_set(ew, nx, ny);
470
471    if ((window->w != nw) || (window->h != nh)) {
472      _tizen_setwindowsize(window);
473    }
474    */
475    return ECORE_CALLBACK_PASS_ON;
476 }
477
478
479 void
480 _tizen_send_rotation_event(SDL_Window *window, unsigned int angle)
481 {
482     SDL_Event event;
483     SDL_WindowData *wind;
484     wind = window->driverdata;
485
486     SDL_memset(&event, 0, sizeof(event));
487     event.type = SDL_ROTATEEVENT;
488     event.user.code = 0;
489     if (wind->support_pre_rotation)
490         event.user.data1 = (void*)0;
491     else
492         event.user.data1 = (void*)angle;
493     event.user.data2 = (void*)-1;
494
495     SDL_PushEvent(&event);
496     return;
497 }
498
499 Eina_Bool
500 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
501 {
502     _THIS = data;
503     Ecore_Wl_Event_Window_Rotate *ev;
504     Ecore_Wl_Window *ew;
505     SDL_Window *window;
506     SDL_WindowData *wind;
507
508     ev = event;
509     if (!ev) {
510         return ECORE_CALLBACK_PASS_ON;
511     }
512
513     ew = ecore_wl_window_find(ev->win);
514     window = Tizen_FindWindow(_this, ew);
515     wind = window->driverdata;
516
517     if (wind->rotation != ev->angle) {
518         /* set ecore_wayland window rotation */
519         wind->rotation = ev->angle;
520         ecore_wl_window_rotation_set(ew, ev->angle);
521
522         if(wind->support_pre_rotation) {
523             _tizen_pre_rotation_set(wind);
524
525             int aw, ah;
526             wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
527             wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
528
529             SDL_Log("[SDL_Size] * _tizen_cb_event_window_rotate aw ah : %d, %d", aw, ah);
530
531             if(wind->rotation == 90 || wind->rotation == 270) {
532                 SDL_SetWindowSize(window, ah, aw);
533                 window->w = ah;//for Fullscreen
534                 window->h = aw;
535             } else {
536                 SDL_SetWindowSize(window, aw, ah);//->call wl_egl_window_resize()
537                 window->w = aw;//for Fullscreen
538                 window->h = ah;
539             }
540             SDL_Log("[SDL_Size] * _tizen_cb_event_window_rotate aw ah : %d, %d", window->w, window->h);
541     }
542
543         // Send Rotation Event
544         _tizen_send_rotation_event(window, ev->angle);
545         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
546     }
547
548     wind->received_rotation = 1;
549     const char* hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
550     if(hint && *hint != '\0')
551         Tizen_IndicatorProcessEvent(_this->current_glwin, wind->rotation);
552
553     return ECORE_CALLBACK_PASS_ON;
554 }
555
556 int
557 Tizen_InitWindow(_THIS)
558 {
559     SDL_VideoData *data = _this->driverdata;
560
561     data->windows = eina_hash_int32_new(NULL);
562
563     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
564                         _tizen_cb_event_window_visibility_change,_this);
565     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
566                         _tizen_cb_event_keyup_change,_this);
567     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
568                         _tizen_cb_event_keydown_change,_this);
569     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
570                         _tizen_cb_event_mousedown_change,_this);
571     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
572                         _tizen_cb_event_mouseup_change,_this);
573     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
574                         _tizen_cb_event_mousemove_change,_this);
575     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
576                         _tizen_cb_event_window_rotate,_this);
577     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
578                         _tizen_cb_window_configure,_this);
579     ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
580                         _tizen_cb_event_joystick_change,_this);
581     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
582                         _tizen_cb_event_focus_in,_this);
583     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
584                         _tizen_cb_event_focus_out,_this);
585     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
586                         _tizen_cb_event_mouse_in,_this);
587     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
588                         _tizen_cb_event_mouse_out,_this);
589
590     data->current_thread = SDL_GetThreadID(0);
591
592     return 0;
593 }
594
595 void
596 Tizen_DeinitWindow(_THIS)
597 {
598     SDL_VideoData *data = _this->driverdata;
599
600     eina_hash_free(data->windows);
601 }
602 #endif /* SDL_VIDEO_DRIVER_TIZEN */
603
604 /* vi: set ts=4 sw=4 expandtab: */