[SDL_Tizen] Modify prerotation
[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         int aw, ah, dx = 0, dy = 0;
292
293         if ((wind->rotation == 90) || (wind->rotation == 270))
294             wl_egl_window_get_attached_size(wind->egl_window, &ah, &aw);
295         else
296             wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
297
298         SDL_Log("SDL %s:wl_egl_window_get_attached_size:rot(%i)%ix%i",__FUNCTION__,wind->rotation,aw,ah);
299
300         // TODO : if window size is not FULL, we need the code about Non FullSize Window.
301         wl_egl_window_resize(wind->egl_window, window->w, window->h, dx, dy);
302     }
303 #endif
304
305 }
306
307 void
308 _tizen_setwindowsize(SDL_Window *window)
309 {
310     SDL_WindowData *wind = window->driverdata;
311     if (!wind->window) {
312         return;
313     }
314
315     if ((wind->rotation == 0) || (wind->rotation == 180))
316         ecore_wl_window_update_size(wind->window, window->w, window->h);
317     else
318         ecore_wl_window_update_size(wind->window, window->h, window->w);
319 }
320
321 void
322 Tizen_SetWindowSize(_THIS, SDL_Window *window)
323 {
324    SDL_Log("[SDL_Size] Tizen_SetWindowSize");
325     _tizen_setwindowsize(window);
326     _tizen_egl_window_resize(window);
327 }
328
329 void
330 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
331 {
332     SDL_WindowData *wind = window->driverdata;
333     int tmp_w, tmp_h;
334     if (!wind->window) {
335         return;
336     }
337
338     tmp_w = window->w;
339     tmp_h = window->h;
340     if (wind->rotation == 90 || wind->rotation == 270) {
341         tmp_w = window->h;
342         tmp_h = window->w;
343     }
344
345     if (w) *w = tmp_w;
346     if (h) *h = tmp_h;
347 }
348
349 void
350 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
351 {
352     SDL_WindowData *wind = window->driverdata;
353     if (!wind->window) {
354         return;
355     }
356
357     // TODO : consider to rotation status.
358    ecore_wl_window_position_set(wind->window, window->x, window->y);
359 }
360
361 void
362 Tizen_DestroyWindow(_THIS, SDL_Window *window)
363 {
364     SDL_VideoData *data = _this->driverdata;
365     SDL_WindowData *wind = window->driverdata;
366
367     if (data) {
368         eina_hash_del(data->windows, &wind->id, window);
369 #if SDL_VIDEO_OPENGL_EGL
370     if (window->flags & SDL_WINDOW_OPENGL) {
371         SDL_EGL_DestroySurface(_this, wind->egl_surface);
372         wl_egl_window_destroy(wind->egl_window);
373     }
374 #endif
375         ecore_wl_window_free(wind->window);
376         SDL_free(wind);
377     }
378
379     window->driverdata = NULL;
380 }
381
382 SDL_Window*
383 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
384 {
385     SDL_VideoData *data = _this->driverdata;
386     int id;
387
388     id = ecore_wl_window_id_get(ewin);
389     return (SDL_Window*)eina_hash_find(data->windows, &id);
390 }
391
392 Eina_Bool
393 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
394 {
395     _THIS = data;
396     Ecore_Wl_Event_Window_Visibility_Change *ev;
397     Ecore_Wl_Window *ew;
398     SDL_Window *window;
399
400     ev = event;
401     ew = ecore_wl_window_find(ev->win);
402     window = Tizen_FindWindow(_this, ew);
403
404     SDL_Log( "visibility window: %p, ecore_wl_window: %p\n", window, ew);
405
406     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
407     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
408     return ECORE_CALLBACK_PASS_ON;
409 }
410
411 Eina_Bool
412 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
413 {
414    _THIS = data;
415    Ecore_Wl_Window *ew;
416    SDL_Window *window;
417    SDL_WindowData *wind;
418    Ecore_Wl_Event_Window_Configure *ev;
419    int nx = 0, ny = 0, nw = 0, nh = 0;
420    ev = event;
421    ew = ecore_wl_window_find(ev->win);
422    window = Tizen_FindWindow(_this, ew);
423    wind = window->driverdata;
424
425    if (wind->rotation_supported == 0){
426       return ECORE_CALLBACK_PASS_ON;
427    }
428
429   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
430
431    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
432    if (nw < 1) nw = 1;
433    if (nh < 1) nh = 1;
434    
435    SDL_Log("[SDL_Size] * _tizen_cb_window_configure :: w->w:%d, w->h:%d, nw:%d, nh:%d", window->w, window->h, nw, nh);
436    if ((window->x != nx) || (window->y != ny))
437      ecore_wl_window_position_set(ew, nx, ny);
438
439    if ((window->w != nw) || (window->h != nh)) {
440      _tizen_setwindowsize(window);
441    }
442    return ECORE_CALLBACK_PASS_ON;
443 }
444
445
446 void
447 _tizen_send_rotation_event(SDL_Window *window, unsigned int angle)
448 {
449     SDL_Event event;
450     SDL_WindowData *wind;
451     wind = window->driverdata;
452
453     SDL_memset(&event, 0, sizeof(event));
454     event.type = SDL_ROTATEEVENT;
455     event.user.code = 0;
456     if (wind->support_pre_rotation)
457         event.user.data1 = (void*)0;
458     else
459         event.user.data1 = (void*)angle;
460     event.user.data2 = (void*)-1;
461
462     SDL_PushEvent(&event);
463     return;
464 }
465
466 Eina_Bool
467 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
468 {
469     _THIS = data;
470     Ecore_Wl_Event_Window_Rotate *ev;
471     Ecore_Wl_Window *ew;
472     SDL_Window *window;
473     SDL_WindowData *wind;
474
475     ev = event;
476     if (!ev) {
477         return ECORE_CALLBACK_PASS_ON;
478     }
479
480     ew = ecore_wl_window_find(ev->win);
481     window = Tizen_FindWindow(_this, ew);
482     wind = window->driverdata;
483
484     if (wind->rotation != ev->angle) {
485         /* set ecore_wayland window rotation */
486         wind->rotation = ev->angle;
487         ecore_wl_window_rotation_set(ew, ev->angle);
488
489         // support prerotation
490         /* set ecore_wayland window rotation */
491         _tizen_setwindowsize(window);
492
493         SDL_Log("[SDL_Size] * _tizen_cb_event_window_rotate : %d, %d", window->w, window->h);
494         // Send Rotation Event
495         _tizen_send_rotation_event(window, ev->angle);
496
497         int retW = window->w;
498         int retH = window->h;
499         if(!wind->support_pre_rotation) {
500             _tizen_egl_window_resize(window);
501         }
502         else {
503             if ((wind->rotation == 90) || (wind->rotation == 270)) {
504                 retW = window->h;
505                 retH = window->w;
506             }
507             wl_egl_window_resize(wind->egl_window, retW, retH, 0, 0);
508         }
509          ecore_wl_window_rotation_geometry_set(wind->window, wind->rotation, 0, 0,retW, retH);
510         _tizen_pre_rotation_set(wind->egl_window, (int)ev->angle);
511         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, retW, retH);
512     }
513
514     wind->received_rotation = 1;
515     const char* hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
516     if(hint && *hint != '\0')
517         SDL_IndicatorProcessEvent(_this->current_glwin, wind->rotation);
518
519     return ECORE_CALLBACK_PASS_ON;
520 }
521
522 int
523 Tizen_InitWindow(_THIS)
524 {
525     SDL_VideoData *data = _this->driverdata;
526
527     data->windows = eina_hash_int32_new(NULL);
528
529     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
530                         _tizen_cb_event_window_visibility_change,_this);
531     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
532                         _tizen_cb_event_keyup_change,_this);
533     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
534                         _tizen_cb_event_keydown_change,_this);
535     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
536                         _tizen_cb_event_mousedown_change,_this);
537     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
538                         _tizen_cb_event_mouseup_change,_this);
539     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
540                         _tizen_cb_event_mousemove_change,_this);
541     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
542                         _tizen_cb_event_window_rotate,_this);
543     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
544                         _tizen_cb_window_configure,_this);
545     ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
546                         _tizen_cb_event_joystick_change,_this);
547     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
548                         _tizen_cb_event_focus_in,_this);
549     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
550                         _tizen_cb_event_focus_out,_this);
551     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
552                         _tizen_cb_event_mouse_in,_this);
553     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
554                         _tizen_cb_event_mouse_out,_this);
555
556     return 0;
557 }
558
559 void
560 Tizen_DeinitWindow(_THIS)
561 {
562     SDL_VideoData *data = _this->driverdata;
563
564     eina_hash_free(data->windows);
565 }
566 #endif /* SDL_VIDEO_DRIVER_TIZEN */
567
568 /* vi: set ts=4 sw=4 expandtab: */