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