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