Merge "add multi-Touch support." 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_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
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 static void
81 _tizen_window_orientaiton_hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue)
82 {
83     char *p_str = NULL;
84     char orientation_type[4][20] = {"Portrait","LandscapeLeft","PortraitUpsideDown","LandscapeRight"};
85     int checked[4] = {0,};
86     int i;
87     unsigned int j = 0;
88     SDL_WindowData *wind = (SDL_WindowData*)userdata;
89     Ecore_Wl_Window *window = wind->window;
90
91     if (wind->rotation_supported == 0)
92     {
93         return;
94     }
95
96     SDL_assert(SDL_strncmp(name, SDL_HINT_ORIENTATIONS, SDL_strlen(SDL_HINT_ORIENTATIONS)) == 0);
97
98     if ((oldValue == NULL) && (newValue == NULL)) {
99         return;
100     }
101
102     for (i=0;i<4;i++) {
103         p_str = SDL_strstr(newValue, orientation_type[i]);
104         if (p_str) {
105             if (p_str == newValue) {
106                 int rot = 0;
107                 if (i == 0) rot = 0;
108                 else if (i == 1) rot = 90;
109                 else if (i == 2) rot = 180;
110                 else if (i == 3) rot = 270;
111                 wind->rotation = rot;
112             }
113
114             if (i == 0) {
115                 checked[j] = 0;
116                 SDL_Log("SDL  %s: avaiable rotation: 0", __FUNCTION__);
117             }
118             else if (i == 1) {
119                 checked[j] = 90;
120                 SDL_Log("SDL %s: avaiable rotation: 90", __FUNCTION__);
121             }
122             else if (i == 2) {
123                 checked[j] = 180;
124                 SDL_Log("SDL %s: avaiable rotation: 180", __FUNCTION__);
125             }
126             else if (i == 3) {
127                 checked[j] = 270;
128                 SDL_Log("SDL %s: avaiable rotation: 270", __FUNCTION__);
129             }
130             j++;
131         }
132     }
133
134     if (j > 0) {
135         if (j == 1) {
136             ecore_wl_window_rotation_preferred_rotation_set(window,wind->rotation);
137         }
138         ecore_wl_window_rotation_available_rotations_set(window, (const int*)checked, j);
139     }
140 }
141
142 static void
143 _tizen_window_orientation_add_hint(void *data)
144 {
145     SDL_WindowData *wind = (SDL_WindowData*)data;
146     if (wind->rotation_supported == 0) {
147         return;
148     }
149
150     SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, _tizen_window_orientaiton_hint_callback, data);
151 }
152
153 int
154 Tizen_CreateWindow(_THIS, SDL_Window *window)
155 {
156     SDL_VideoData *data = _this->driverdata;
157     SDL_WindowData *wind;
158     Ecore_Wl_Global *global;
159     Eina_Inlist *globals;
160
161     wind = calloc(1, sizeof * wind);
162     if (!wind) {
163         return SDL_OutOfMemory();
164     }
165
166     window->driverdata = wind;
167
168 #if SDL_VIDEO_OPENGL_EGL
169     if (window->flags & SDL_WINDOW_OPENGL) {
170         SDL_GL_LoadLibrary(NULL);
171     }
172 #endif
173
174     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
175         window->x = 0;
176     }
177     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
178         window->y = 0;
179     }
180
181     if (!(globals = ecore_wl_globals_get()))
182       {
183          SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get wayland globals");
184          return -1;
185       }
186
187     wind->window = ecore_wl_window_new(NULL,
188                                        window->x, window->y, window->w, window->h,
189                                        ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
190     wind->surface = ecore_wl_window_surface_create(wind->window);
191     wind->rotation = 0;
192     wind->rotation_supported = 0;
193     wind->received_rotation = 0;
194     ecore_wl_window_opaque_region_set(wind->window, window->x, window->y, window->w, window->h);
195
196 #if SDL_VIDEO_OPENGL_EGL
197     if (window->flags & SDL_WINDOW_OPENGL) {
198         wind->egl_window = wl_egl_window_create(ecore_wl_window_surface_get(wind->window), window->w, window->h);
199
200         /* Create the GLES window surface */
201         wind->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wind->egl_window);
202         if (wind->egl_surface == EGL_NO_SURFACE) {
203             SDL_SetError("failed to create a window surface");
204             return -1;
205         }
206     }
207 #endif
208
209     wind->id = ecore_wl_window_id_get(wind->window);
210     eina_hash_add(data->windows, &wind->id, window);
211
212     Tizen_InitKeyboard(_this);
213
214     if (window->flags & SDL_WINDOW_MOUSE_UNFOCUS) {
215         SDL_Log("SDL_WINDOW_MOUSE_UNFOCUS is set. Mouse event will be passed the focused window.");
216         ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
217     }
218     else {
219         SDL_SetMouseFocus(window);
220     }
221
222     if (window->flags & SDL_WINDOW_INPUT_UNFOCUS) {
223         SDL_Log("SDL_WINDOW_INPUT_UNFOCUS is set. Key event will be passed the focused window.");
224         ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
225     }
226
227     EINA_INLIST_FOREACH(globals, global) {
228          if (!strcmp(global->interface, "tizen_policy_ext")) {
229               wind->rotation_supported = 1;
230               SDL_Log("SDL can support rotation in this device!!!!!!!!!!!");
231               break;
232            }
233       }
234     // Add orientaiton hint cb
235     _tizen_window_orientation_add_hint((void*)wind);
236     return 0;
237 }
238
239 void
240 _tizen_setwindowsize(SDL_Window *window, int update_egl)
241 {
242     SDL_WindowData *wind = window->driverdata;
243     if (!wind->window)
244     {
245         return;
246     }
247
248     // TODO : consider to rotation status.
249 #if SDL_VIDEO_OPENGL_EGL
250     if ((window->flags & SDL_WINDOW_OPENGL) && (update_egl == 1)) {
251         int aw, ah, dx = 0, dy = 0;
252
253         if ((wind->rotation == 90) || (wind->rotation == 270))
254             wl_egl_window_get_attached_size(wind->egl_window, &ah, &aw);
255         else
256             wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
257
258         SDL_Log("SDL %s:wl_egl_window_get_attached_size:rot(%i)%ix%i",__FUNCTION__,wind->rotation,aw,ah);
259
260         // TODO : if window size is not FULL, we need the code about Non FullSize Window.
261         wl_egl_window_resize(wind->egl_window, window->w, window->h, dx, dy);
262     }
263 #endif
264     ecore_wl_window_update_size(wind->window, window->w, window->h);
265 }
266
267 void
268 Tizen_SetWindowSize(_THIS, SDL_Window *window)
269 {
270     _tizen_setwindowsize(window, 1);
271 }
272
273 void
274 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
275 {
276     SDL_WindowData *wind = window->driverdata;
277     int tmp_w, tmp_h;
278     if (!wind->window) {
279         return;
280     }
281
282     tmp_w = window->w;
283     tmp_h = window->h;
284     if (wind->rotation == 90 || wind->rotation == 270) {
285         tmp_w = window->h;
286         tmp_h = window->w;
287     }
288
289     if (w) {
290         *w = tmp_w;
291     }
292     if (h) {
293         *h = tmp_h;
294     }
295 }
296
297
298 void
299 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
300 {
301     SDL_WindowData *wind = window->driverdata;
302     if (!wind->window) {
303         return;
304     }
305
306     // TODO : consider to rotation status.
307    ecore_wl_window_position_set(wind->window, window->x, window->y);
308 }
309
310 void
311 Tizen_DestroyWindow(_THIS, SDL_Window *window)
312 {
313     SDL_VideoData *data = _this->driverdata;
314     SDL_WindowData *wind = window->driverdata;
315
316     if (data) {
317         eina_hash_del(data->windows, &wind->id, window);
318 #if SDL_VIDEO_OPENGL_EGL
319     if (window->flags & SDL_WINDOW_OPENGL) {
320         SDL_EGL_DestroySurface(_this, wind->egl_surface);
321         wl_egl_window_destroy(wind->egl_window);
322     }
323 #endif
324         ecore_wl_window_free(wind->window);
325         SDL_free(wind);
326     }
327
328     window->driverdata = NULL;
329 }
330
331 static SDL_Window*
332 _tizen_find_window(_THIS, Ecore_Wl_Window *ewin)
333 {
334     SDL_VideoData *data = _this->driverdata;
335     int id;
336
337     id = ecore_wl_window_id_get(ewin);
338     return (SDL_Window*)eina_hash_find(data->windows, &id);
339 }
340
341 static Eina_Bool
342 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
343 {
344     _THIS = data;
345     Ecore_Wl_Event_Window_Visibility_Change *ev;
346     Ecore_Wl_Window *ew;
347     SDL_Window *window;
348
349     ev = event;
350     ew = ecore_wl_window_find(ev->win);
351     window = _tizen_find_window(_this, ew);
352
353     SDL_Log( "visibility window: %p, ecore_wl_window: %p\n", window, ew);
354
355     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
356     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
357     return ECORE_CALLBACK_PASS_ON;
358 }
359
360 static Eina_Bool
361 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
362 {
363    _THIS = data;
364    Ecore_Wl_Window *ew;
365    SDL_Window *window;
366    SDL_WindowData *wind;
367    Ecore_Wl_Event_Window_Configure *ev;
368    int nx = 0, ny = 0, nw = 0, nh = 0;
369    ev = event;
370    ew = ecore_wl_window_find(ev->win);
371    window = _tizen_find_window(_this, ew);
372    wind = window->driverdata;
373
374    if (wind->rotation_supported == 0){
375       return ECORE_CALLBACK_PASS_ON;
376    }
377
378   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
379
380    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
381    if (nw < 1) nw = 1;
382    if (nh < 1) nh = 1;
383
384    if ((window->x != nx) || (window->y != ny))
385      ecore_wl_window_position_set(ew, nx, ny);
386
387    if ((window->w != nw) || (window->h != nh)) {
388      window->w = nw;
389      window->h = nh;
390
391      _tizen_setwindowsize(window, 0);
392    }
393    return ECORE_CALLBACK_PASS_ON;
394 }
395
396 static Eina_Bool
397 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
398 {
399     _THIS = data;
400     Ecore_Wl_Event_Window_Rotate *ev;
401     Ecore_Wl_Window *ew;
402     SDL_Window *window;
403     SDL_WindowData *wind;
404
405     ev = event;
406     if (!ev) {
407         return ECORE_CALLBACK_PASS_ON;
408     }
409
410     ew = ecore_wl_window_find(ev->win);
411     window = _tizen_find_window(_this, ew);
412     wind = window->driverdata;
413
414     if (wind->rotation != ev->angle) {
415         /* set ecore_wayland window rotation */
416         wind->rotation = ev->angle;
417         ecore_wl_window_rotation_set(ew, ev->angle);
418        _tizen_setwindowsize(window, 1);
419        if (wind->rotation == 0 || wind->rotation == 180)
420           SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
421        else if (wind->rotation == 90 || wind->rotation == 270)
422           SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->h, window->w);
423     }
424     wind->received_rotation = 1;
425     return ECORE_CALLBACK_PASS_ON;
426 }
427
428 int
429 Tizen_InitWindow(_THIS)
430 {
431     SDL_VideoData *data = _this->driverdata;
432
433     data->windows = eina_hash_int32_new(NULL);
434
435     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
436                         _tizen_cb_event_window_visibility_change,_this);
437     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
438                         _tizen_cb_event_keyup_change,_this);
439     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
440                         _tizen_cb_event_keydown_change,_this);
441     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
442                         _tizen_cb_event_mousedown_change,_this);
443     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
444                         _tizen_cb_event_mouseup_change,_this);
445     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
446                         _tizen_cb_event_mousemove_change,_this);
447     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
448                         _tizen_cb_event_window_rotate,_this);
449     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
450                         _tizen_cb_window_configure,_this);
451
452     return 0;
453 }
454
455 void
456 Tizen_DeinitWindow(_THIS)
457 {
458     SDL_VideoData *data = _this->driverdata;
459
460     eina_hash_free(data->windows);
461 }
462 #endif /* SDL_VIDEO_DRIVER_TIZEN */
463
464 /* vi: set ts=4 sw=4 expandtab: */