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