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