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