Add remote surface indicator
[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 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     SDL_SetMouseFocus(window);
215
216     if (window->flags & 0x00008000) {
217         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "---------------------------------------");
218         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[SDL] touch bypass setting is done!\n");
219         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "---------------------------------------");
220         ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
221         ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
222     }
223
224     EINA_INLIST_FOREACH(globals, global) {
225          if (!strcmp(global->interface, "tizen_policy_ext")) {
226               wind->rotation_supported = 1;
227               SDL_Log("SDL can support rotation in this device!!!!!!!!!!!");
228               break;
229            }
230       }
231     // Add orientaiton hint cb
232     _tizen_window_orientation_add_hint((void*)wind);
233     return 0;
234 }
235
236 void
237 _tizen_setwindowsize(SDL_Window *window, int update_egl)
238 {
239     SDL_WindowData *wind = window->driverdata;
240     if (!wind->window)
241     {
242         return;
243     }
244
245     // TODO : consider to rotation status.
246 #if SDL_VIDEO_OPENGL_EGL
247     if ((window->flags & SDL_WINDOW_OPENGL) && (update_egl == 1)) {
248         int aw, ah, dx = 0, dy = 0;
249
250         if ((wind->rotation == 90) || (wind->rotation == 270))
251             wl_egl_window_get_attached_size(wind->egl_window, &ah, &aw);
252         else
253             wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
254
255         SDL_Log("SDL %s:wl_egl_window_get_attached_size:rot(%i)%ix%i",__FUNCTION__,wind->rotation,aw,ah);
256
257         // TODO : if window size is not FULL, we need the code about Non FullSize Window.
258         wl_egl_window_resize(wind->egl_window, window->w, window->h, dx, dy);
259     }
260 #endif
261     ecore_wl_window_update_size(wind->window, window->w, window->h);
262 }
263
264 void
265 Tizen_SetWindowSize(_THIS, SDL_Window *window)
266 {
267     _tizen_setwindowsize(window, 1);
268 }
269
270 void
271 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
272 {
273     SDL_WindowData *wind = window->driverdata;
274     int tmp_w, tmp_h;
275     if (!wind->window) {
276         return;
277     }
278
279     tmp_w = window->w;
280     tmp_h = window->h;
281     if (wind->rotation == 90 || wind->rotation == 270) {
282         tmp_w = window->h;
283         tmp_h = window->w;
284     }
285
286     if (w) {
287         *w = tmp_w;
288     }
289     if (h) {
290         *h = tmp_h;
291     }
292 }
293
294
295 void
296 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
297 {
298     SDL_WindowData *wind = window->driverdata;
299     if (!wind->window) {
300         return;
301     }
302
303     // TODO : consider to rotation status.
304    ecore_wl_window_position_set(wind->window, window->x, window->y);
305 }
306
307 void
308 Tizen_DestroyWindow(_THIS, SDL_Window *window)
309 {
310     SDL_VideoData *data = _this->driverdata;
311     SDL_WindowData *wind = window->driverdata;
312
313     if (data) {
314         eina_hash_del(data->windows, &wind->id, window);
315 #if SDL_VIDEO_OPENGL_EGL
316     if (window->flags & SDL_WINDOW_OPENGL) {
317         SDL_EGL_DestroySurface(_this, wind->egl_surface);
318         wl_egl_window_destroy(wind->egl_window);
319     }
320 #endif
321         ecore_wl_window_free(wind->window);
322         SDL_free(wind);
323     }
324
325     window->driverdata = NULL;
326 }
327
328 SDL_Window*
329 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
330 {
331     SDL_VideoData *data = _this->driverdata;
332     int id;
333
334     id = ecore_wl_window_id_get(ewin);
335     return (SDL_Window*)eina_hash_find(data->windows, &id);
336 }
337
338 static Eina_Bool
339 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
340 {
341     _THIS = data;
342     Ecore_Wl_Event_Window_Visibility_Change *ev;
343     Ecore_Wl_Window *ew;
344     SDL_Window *window;
345
346     ev = event;
347     ew = ecore_wl_window_find(ev->win);
348     window = Tizen_FindWindow(_this, ew);
349
350     SDL_Log( "visibility window: %p, ecore_wl_window: %p\n", window, ew);
351
352     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
353     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
354     return ECORE_CALLBACK_PASS_ON;
355 }
356
357 static Eina_Bool
358 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
359 {
360    _THIS = data;
361    Ecore_Wl_Window *ew;
362    SDL_Window *window;
363    SDL_WindowData *wind;
364    Ecore_Wl_Event_Window_Configure *ev;
365    int nx = 0, ny = 0, nw = 0, nh = 0;
366    ev = event;
367    ew = ecore_wl_window_find(ev->win);
368    window = Tizen_FindWindow(_this, ew);
369    wind = window->driverdata;
370
371    if (wind->rotation_supported == 0){
372       return ECORE_CALLBACK_PASS_ON;
373    }
374
375   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
376
377    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
378    if (nw < 1) nw = 1;
379    if (nh < 1) nh = 1;
380
381    if ((window->x != nx) || (window->y != ny))
382      ecore_wl_window_position_set(ew, nx, ny);
383
384    if ((window->w != nw) || (window->h != nh)) {
385      window->w = nw;
386      window->h = nh;
387
388      _tizen_setwindowsize(window, 0);
389    }
390    return ECORE_CALLBACK_PASS_ON;
391 }
392
393 static Eina_Bool
394 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
395 {
396     _THIS = data;
397     Ecore_Wl_Event_Window_Rotate *ev;
398     Ecore_Wl_Window *ew;
399     SDL_Window *window;
400     SDL_WindowData *wind;
401
402     ev = event;
403     if (!ev) {
404         return ECORE_CALLBACK_PASS_ON;
405     }
406
407     ew = ecore_wl_window_find(ev->win);
408     window = Tizen_FindWindow(_this, ew);
409     wind = window->driverdata;
410
411     if (wind->rotation != ev->angle) {
412         /* set ecore_wayland window rotation */
413         wind->rotation = ev->angle;
414         ecore_wl_window_rotation_set(ew, ev->angle);
415        _tizen_setwindowsize(window, 1);
416        if (wind->rotation == 0 || wind->rotation == 180)
417           SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
418        else if (wind->rotation == 90 || wind->rotation == 270)
419           SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->h, window->w);
420     }
421     wind->received_rotation = 1;
422
423     const char* hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
424     if(hint)
425     {
426         if(*hint != '\0')
427         {
428            SDL_IndicatorProcessEvent(_this->current_glwin, wind->rotation);
429         }
430     }
431
432     return ECORE_CALLBACK_PASS_ON;
433 }
434
435 int
436 Tizen_InitWindow(_THIS)
437 {
438     SDL_VideoData *data = _this->driverdata;
439
440     data->windows = eina_hash_int32_new(NULL);
441
442     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
443                         _tizen_cb_event_window_visibility_change,_this);
444     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
445                         _tizen_cb_event_keyup_change,_this);
446     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
447                         _tizen_cb_event_keydown_change,_this);
448     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
449                         _tizen_cb_event_mousedown_change,_this);
450     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
451                         _tizen_cb_event_mouseup_change,_this);
452     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
453                         _tizen_cb_event_mousemove_change,_this);
454     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
455                         _tizen_cb_event_window_rotate,_this);
456     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
457                         _tizen_cb_window_configure,_this);
458     ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
459                         _tizen_cb_event_joystick_change,_this);
460     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
461                         _tizen_cb_event_focus_in,_this);
462     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
463                         _tizen_cb_event_focus_out,_this);
464     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
465                         _tizen_cb_event_mouse_in,_this);
466     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
467                         _tizen_cb_event_mouse_out,_this);
468
469     return 0;
470 }
471
472 void
473 Tizen_DeinitWindow(_THIS)
474 {
475     SDL_VideoData *data = _this->driverdata;
476
477     eina_hash_free(data->windows);
478 }
479 #endif /* SDL_VIDEO_DRIVER_TIZEN */
480
481 /* vi: set ts=4 sw=4 expandtab: */