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