[SDL_Tizen]Add SDL_SetWindowBordered function
[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     window->flags |= SDL_WINDOW_BORDERLESS;     /* defalut - not support indicator*/
249
250 #if SDL_VIDEO_OPENGL_EGL
251     if (window->flags & SDL_WINDOW_OPENGL) {
252         SDL_GL_LoadLibrary(NULL);
253     }
254 #endif
255
256     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
257         window->x = 0;
258     }
259     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
260         window->y = 0;
261     }
262
263     if (!(globals = ecore_wl_globals_get()))
264       {
265          SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get wayland globals");
266          return -1;
267       }
268
269     wind->window = ecore_wl_window_new(NULL,
270                                        window->x, window->y, window->w, window->h,
271                                        ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
272     wind->surface = ecore_wl_window_surface_create(wind->window);
273     wind->rotation = 0;
274     wind->rotation_supported = 0;
275     wind->received_rotation = 0;
276     ecore_wl_window_opaque_region_set(wind->window, window->x, window->y, window->w, window->h);
277
278 #if SDL_VIDEO_OPENGL_EGL
279     if (window->flags & SDL_WINDOW_OPENGL) {
280         wind->egl_window = wl_egl_window_create(ecore_wl_window_surface_get(wind->window), window->w, window->h);
281
282         /* Create the GLES window surface */
283         wind->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wind->egl_window);
284         if (wind->egl_surface == EGL_NO_SURFACE) {
285             SDL_SetError("failed to create a window surface");
286             return -1;
287         }
288
289         //Support PreRotation
290         wind->support_pre_rotation = 0;
291         if (_tizen_PreRotatotion_LoadLibrary(wind, "libwayland-egl.so")) {
292             if (wind->tizen_pre_rotation_data->wl_egl_window_get_capabilities(wind->egl_window) == TIZEN_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) {
293                 wind->support_pre_rotation = 1;
294                 SDL_Log("Can support PreRotation");
295             }
296             else {
297                 SDL_Log("can not support PreRotation !!");
298             }
299         }
300         else {
301             SDL_Log("can not support PreRotation !!");
302         }
303     }
304 #endif
305
306     wind->id = ecore_wl_window_id_get(wind->window);
307     eina_hash_add(data->windows, &wind->id, window);
308
309     Tizen_InitKeyboard(_this);
310     SDL_SetMouseFocus(window);
311
312     if (window->flags & 0x00008000) {
313         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "---------------------------------------");
314         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[SDL] touch bypass setting is done!\n");
315         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "---------------------------------------");
316         ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
317         ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
318     }
319
320     EINA_INLIST_FOREACH(globals, global) {
321          if (!strcmp(global->interface, "tizen_policy_ext")) {
322               wind->rotation_supported = 1;
323               SDL_Log("SDL can support rotation in this device!!!!!!!!!!!");
324               break;
325            }
326       }
327     // Add orientaiton hint cb
328     _tizen_window_orientation_add_hint((void*)wind);
329
330     return 0;
331 }
332
333 void
334 Tizen_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
335 {
336 //Add setting window bordered.
337 }
338
339 void
340 _tizen_egl_window_resize(SDL_Window *window)
341 {
342     SDL_WindowData *wind = window->driverdata;
343     if (!wind->egl_window) {
344         return;
345     }
346
347     // TODO : consider to rotation status.
348 #if SDL_VIDEO_OPENGL_EGL
349     if (window->flags & SDL_WINDOW_OPENGL) {
350         // TODO : if window size is not FULL, we need the code about Non FullSize Window.
351         int aw, ah;
352         wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
353         wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
354     }
355 #endif
356
357 }
358
359 void
360 _tizen_setwindowsize(SDL_Window *window)
361 {
362     SDL_WindowData *wind = window->driverdata;
363     if (!wind->window) {
364         return;
365     }
366     ecore_wl_window_update_size(wind->window, window->w, window->h);
367 }
368
369 void
370 Tizen_SetWindowSize(_THIS, SDL_Window *window)
371 {
372    SDL_Log("[SDL_Size] Tizen_SetWindowSize");
373 //    _tizen_setwindowsize(window);
374 //    _tizen_egl_window_resize(window);
375 }
376
377 void
378 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
379 {
380     SDL_WindowData *wind = window->driverdata;
381     if (!wind->window) {
382         return;
383     }
384
385     if (w) *w = window->w;
386     if (h) *h = window->h;
387 }
388
389 void
390 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
391 {
392     SDL_WindowData *wind = window->driverdata;
393     if (!wind->window) {
394         return;
395     }
396
397     // TODO : consider to rotation status.
398    ecore_wl_window_position_set(wind->window, window->x, window->y);
399 }
400
401 void
402 Tizen_DestroyWindow(_THIS, SDL_Window *window)
403 {
404     SDL_VideoData *data = _this->driverdata;
405     SDL_WindowData *wind = window->driverdata;
406
407     if (data) {
408         eina_hash_del(data->windows, &wind->id, window);
409 #if SDL_VIDEO_OPENGL_EGL
410     if (window->flags & SDL_WINDOW_OPENGL) {
411         SDL_EGL_DestroySurface(_this, wind->egl_surface);
412         wl_egl_window_destroy(wind->egl_window);
413     }
414 #endif
415         ecore_wl_window_free(wind->window);
416         SDL_free(wind);
417     }
418
419     window->driverdata = NULL;
420 }
421
422 SDL_Window*
423 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
424 {
425     SDL_VideoData *data = _this->driverdata;
426     int id;
427
428     id = ecore_wl_window_id_get(ewin);
429     return (SDL_Window*)eina_hash_find(data->windows, &id);
430 }
431
432 Eina_Bool
433 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
434 {
435     _THIS = data;
436     Ecore_Wl_Event_Window_Visibility_Change *ev;
437     Ecore_Wl_Window *ew;
438     SDL_Window *window;
439
440     ev = event;
441     ew = ecore_wl_window_find(ev->win);
442     window = Tizen_FindWindow(_this, ew);
443
444     SDL_Log( "visibility window: %p, ecore_wl_window: %p\n", window, ew);
445
446     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
447     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
448     return ECORE_CALLBACK_PASS_ON;
449 }
450
451 Eina_Bool
452 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
453 {
454    _THIS = data;
455    Ecore_Wl_Window *ew;
456    SDL_Window *window;
457    SDL_WindowData *wind;
458    Ecore_Wl_Event_Window_Configure *ev;
459    ev = event;
460    ew = ecore_wl_window_find(ev->win);
461    window = Tizen_FindWindow(_this, ew);
462    wind = window->driverdata;
463
464    if (wind->rotation_supported == 0){
465       return ECORE_CALLBACK_PASS_ON;
466    }
467 /*
468    int nx = 0, ny = 0, nw = 0, nh = 0;
469   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
470
471    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
472    if (nw < 1) nw = 1;
473    if (nh < 1) nh = 1;
474    
475    SDL_Log("[SDL_Size] * _tizen_cb_window_configure :: w->w:%d, w->h:%d, nw:%d, nh:%d", window->w, window->h, nw, nh);
476    if ((window->x != nx) || (window->y != ny))
477      ecore_wl_window_position_set(ew, nx, ny);
478
479    if ((window->w != nw) || (window->h != nh)) {
480      _tizen_setwindowsize(window);
481    }
482    */
483    return ECORE_CALLBACK_PASS_ON;
484 }
485
486
487 void
488 _tizen_send_rotation_event(SDL_Window *window, unsigned int angle)
489 {
490     SDL_Event event;
491     SDL_WindowData *wind;
492     wind = window->driverdata;
493
494     SDL_memset(&event, 0, sizeof(event));
495     event.type = SDL_ROTATEEVENT;
496     event.user.code = 0;
497     if (wind->support_pre_rotation)
498         event.user.data1 = (void*)0;
499     else
500         event.user.data1 = (void*)angle;
501     event.user.data2 = (void*)-1;
502
503     SDL_PushEvent(&event);
504     return;
505 }
506
507 Eina_Bool
508 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
509 {
510     _THIS = data;
511     Ecore_Wl_Event_Window_Rotate *ev;
512     Ecore_Wl_Window *ew;
513     SDL_Window *window;
514     SDL_WindowData *wind;
515
516     ev = event;
517     if (!ev) {
518         return ECORE_CALLBACK_PASS_ON;
519     }
520
521     ew = ecore_wl_window_find(ev->win);
522     window = Tizen_FindWindow(_this, ew);
523     wind = window->driverdata;
524
525     if (wind->rotation != ev->angle) {
526         /* set ecore_wayland window rotation */
527         wind->rotation = ev->angle;
528         ecore_wl_window_rotation_set(ew, ev->angle);
529
530         if(wind->support_pre_rotation) {
531             _tizen_pre_rotation_set(wind);
532
533             int aw, ah;
534             wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
535             wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
536
537             SDL_Log("[SDL_Size] * _tizen_cb_event_window_rotate aw ah : %d, %d", aw, ah);
538
539             if(wind->rotation == 90 || wind->rotation == 270) {
540                 SDL_SetWindowSize(window, ah, aw);
541                 window->w = ah;//for Fullscreen
542                 window->h = aw;
543             } else {
544                 SDL_SetWindowSize(window, aw, ah);//->call wl_egl_window_resize()
545                 window->w = aw;//for Fullscreen
546                 window->h = ah;
547             }
548             SDL_Log("[SDL_Size] * _tizen_cb_event_window_rotate aw ah : %d, %d", window->w, window->h);
549     }
550
551         // Send Rotation Event
552         _tizen_send_rotation_event(window, ev->angle);
553         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
554     }
555
556     wind->received_rotation = 1;
557     const char* hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
558     if(hint && *hint != '\0')
559         Tizen_IndicatorProcessEvent(_this->current_glwin, wind->rotation);
560
561     return ECORE_CALLBACK_PASS_ON;
562 }
563
564 int
565 Tizen_InitWindow(_THIS)
566 {
567     SDL_VideoData *data = _this->driverdata;
568
569     data->windows = eina_hash_int32_new(NULL);
570
571     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
572                         _tizen_cb_event_window_visibility_change,_this);
573     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
574                         _tizen_cb_event_keyup_change,_this);
575     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
576                         _tizen_cb_event_keydown_change,_this);
577     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
578                         _tizen_cb_event_mousedown_change,_this);
579     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
580                         _tizen_cb_event_mouseup_change,_this);
581     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
582                         _tizen_cb_event_mousemove_change,_this);
583     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
584                         _tizen_cb_event_window_rotate,_this);
585     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
586                         _tizen_cb_window_configure,_this);
587     ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
588                         _tizen_cb_event_joystick_change,_this);
589     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
590                         _tizen_cb_event_focus_in,_this);
591     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
592                         _tizen_cb_event_focus_out,_this);
593     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
594                         _tizen_cb_event_mouse_in,_this);
595     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
596                         _tizen_cb_event_mouse_out,_this);
597
598     data->current_thread = SDL_GetThreadID(0);
599
600     return 0;
601 }
602
603 void
604 Tizen_DeinitWindow(_THIS)
605 {
606     SDL_VideoData *data = _this->driverdata;
607
608     eina_hash_free(data->windows);
609 }
610 #endif /* SDL_VIDEO_DRIVER_TIZEN */
611
612 /* vi: set ts=4 sw=4 expandtab: */