2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
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.
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:
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.
23 #include "../../SDL_internal.h"
25 #if SDL_VIDEO_DRIVER_TIZEN
28 #include "SDL_hints.h"
29 #include "SDL_loadso.h"
31 #include "SDL_tizenvideo.h"
32 #include "SDL_tizentouch.h"
33 #include "SDL_tizenkeyboard.h"
34 #include "SDL_tizenmouse.h"
35 #include "SDL_tizenevents_c.h"
37 #include "SDL_tizenwindow.h"
38 #include "SDL_tizenopengles.h"
40 #include "../../events/SDL_mouse_c.h"
41 #include "../../joystick/tizen/SDL_sysjoystick_c.h"
43 #include "../SDL_egl_c.h"
44 #include "../SDL_vulkan_c.h"
45 #include "../SDL_sysvideo.h"
46 #include "../../events/SDL_windowevents_c.h"
49 ROTATION_TYPE_NORMAL_ROTATION = 0,
50 ROTATION_TYPE_PRE_ROTATION, /* use pre-rotation */
53 #define LOAD_FUNC(NAME) \
54 _this->tizen_pre_rotation_data->NAME = SDL_LoadFunction(_this->tizen_pre_rotation_data->prerotation_dll_handle, #NAME); \
55 if (!_this->tizen_pre_rotation_data->NAME) \
57 SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Could not retrieve pre-rotation function " #NAME); \
62 _tizen_rotation_type_get()
64 static int type = ROTATION_TYPE_PRE_ROTATION;
65 static int checked = 0;
68 if (checked) return type;
70 engine = getenv("SDL_ROTATION");
74 if ((!strcasecmp(engine, "normal")))
75 type = ROTATION_TYPE_NORMAL_ROTATION;
76 else if ((!strcasecmp(engine, "pre_rotation")))
77 type = ROTATION_TYPE_PRE_ROTATION;
79 type = ROTATION_TYPE_PRE_ROTATION;
86 _tizen_PreRotatotion_LoadLibrary(SDL_WindowData *_this, const char *lib_path)
88 void *lib_dll_handle = NULL;
91 if (_this->isLoaded_pre_rotation)
94 _this->tizen_pre_rotation_data = (Tizen_Prerotation_Data *) SDL_calloc(1, sizeof(Tizen_Prerotation_Data));
95 if (!_this->tizen_pre_rotation_data) {
96 return SDL_OutOfMemory();
100 lib_dll_handle = SDL_LoadObject(lib_path);
102 if (!lib_dll_handle) {
103 path = "libwayland-egl.so";
104 lib_dll_handle = SDL_LoadObject(path);
107 _this->tizen_pre_rotation_data->prerotation_dll_handle = lib_dll_handle;
109 if (lib_dll_handle == NULL)
112 LOAD_FUNC(wl_egl_window_set_rotation);
113 LOAD_FUNC(wl_egl_window_get_capabilities);
114 _this->isLoaded_pre_rotation = 1;
120 Tizen_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
122 SDL_WindowData *wmdata = (SDL_WindowData *)window->driverdata;
123 info->info.tizen.egl_display = NULL;
124 info->info.tizen.egl_surface = NULL;
125 #if SDL_VIDEO_OPENGL_EGL
128 info->info.tizen.egl_display = (void*)_this->egl_data->egl_display;
130 info->info.tizen.egl_surface = (void*)wmdata->egl_surface;
132 info->subsystem = SDL_SYSWM_TIZEN;
137 Tizen_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
139 return 0; /* just succeed, the real work is done elsewhere. */
143 Tizen_ShowWindow(_THIS, SDL_Window *window)
145 SDL_WindowData *wind = window->driverdata;
147 if((window->flags & SDL_WINDOW_FULLSCREEN) || (window->flags & SDL_WINDOW_BORDERLESS))
149 ecore_wl_window_indicator_state_set(wind->window, ECORE_WL_INDICATOR_STATE_OFF);
150 ecore_wl_window_indicator_opacity_set(wind->window, ECORE_WL_INDICATOR_TRANSPARENT);
151 ecore_wl_indicator_visible_type_set(wind->window, ECORE_WL_INDICATOR_VISIBLE_TYPE_HIDDEN);
155 ecore_wl_window_indicator_state_set(wind->window, ECORE_WL_INDICATOR_STATE_ON);
156 ecore_wl_window_indicator_opacity_set(wind->window, ECORE_WL_INDICATOR_OPAQUE);
157 ecore_wl_indicator_visible_type_set(wind->window, ECORE_WL_INDICATOR_VISIBLE_TYPE_SHOWN);
159 ecore_wl_window_show(wind->window);
163 Tizen_SetWindowFullscreen(_THIS, SDL_Window *window,
164 SDL_VideoDisplay *_display, SDL_bool fullscreen)
170 Tizen_pre_rotation_set(SDL_WindowData *_this, int rotation)
172 tizen_wl_egl_window_rotation rot;
173 if (!_this->egl_window) return;
177 rot = TIZEN_ROTATION_270;
180 rot = TIZEN_ROTATION_180;
183 rot = TIZEN_ROTATION_90;
186 rot = TIZEN_ROTATION_0;
189 rot = TIZEN_ROTATION_0;
193 _this->tizen_pre_rotation_data->wl_egl_window_set_rotation(_this->egl_window, rot);
197 _tizen_window_orientaiton_hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue)
200 char orientation_type[4][20] = {"Portrait","LandscapeLeft","PortraitUpsideDown","LandscapeRight"};
201 int checked[4] = {0,};
204 SDL_WindowData *wind = (SDL_WindowData*)userdata;
205 Ecore_Wl_Window *window = wind->window;
207 if (wind->rotation_supported == 0) {
211 SDL_assert(SDL_strncmp(name, SDL_HINT_ORIENTATIONS, SDL_strlen(SDL_HINT_ORIENTATIONS)) == 0);
213 if ((oldValue == NULL) && (newValue == NULL)) {
218 p_str = SDL_strstr(newValue, orientation_type[i]);
220 if (p_str == newValue) {
223 else if (i == 1) rot = 90;
224 else if (i == 2) rot = 180;
225 else if (i == 3) rot = 270;
226 wind->rotation = rot;
247 ecore_wl_window_rotation_preferred_rotation_set(window,wind->rotation);
249 ecore_wl_window_rotation_available_rotations_set(window, (const int*)checked, j);
255 _tizen_window_orientation_add_hint(void *data)
257 SDL_WindowData *wind = (SDL_WindowData*)data;
258 if (wind->rotation_supported == 0) {
262 SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, _tizen_window_orientaiton_hint_callback, data);
266 _tizen_cb_output_transform(void *data, int type EINA_UNUSED, void *event)
268 SDL_Window * window = SDL_GetVideoDevice()->windows;
269 SDL_WindowData *wind = window->driverdata;
271 if(!wind) return ECORE_CALLBACK_PASS_ON;
273 Ecore_Wl_Event_Output_Transform *ev = event;
274 Ecore_Wl_Output *output;
276 output = ecore_wl_window_output_find(wind->window);
277 if (output != ev->output) return ECORE_CALLBACK_PASS_ON;
279 _tizen_rotate_update(wind);
281 return ECORE_CALLBACK_PASS_ON;
285 _tizen_cb_ignore_output_transform(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
287 SDL_Window * window = SDL_GetVideoDevice()->windows;
288 SDL_WindowData *wind = window->driverdata;
290 if(!wind) return ECORE_CALLBACK_PASS_ON;
292 _tizen_rotate_update(wind);
294 return ECORE_CALLBACK_PASS_ON;
298 _tizen_output_transform_register(SDL_WindowData *wind)
302 Ecore_Wl_Output *output = ecore_wl_window_output_find(wind->window);
303 wind->output_rotation = ecore_wl_output_transform_get(output) * 90;
305 ecore_event_handler_add(ECORE_WL_EVENT_OUTPUT_TRANSFORM,
306 _tizen_cb_output_transform, NULL);
307 ecore_event_handler_add(ECORE_WL_EVENT_IGNORE_OUTPUT_TRANSFORM,
308 _tizen_cb_ignore_output_transform, NULL);
313 _tizen_send_rotation_event(SDL_Window *window, unsigned int angle)
316 SDL_WindowData *wind;
317 wind = window->driverdata;
319 SDL_memset(&event, 0, sizeof(event));
320 event.type = SDL_ROTATEEVENT;
322 if (wind->support_pre_rotation)
323 event.user.data1 = (void*)0;
325 event.user.data1 = (void*)angle;
326 event.user.data2 = (void*)-1;
328 SDL_PushEvent(&event);
333 _tizen_set_window_size(SDL_Window * window, int w, int h)
337 SDL_SetError("Invalid window");
341 SDL_VideoDevice *_this = SDL_GetVideoDevice();
343 SDL_SetError("Video subsystem has not been initialized");
347 if (window->magic != &_this->window_magic) {
352 SDL_InvalidParamError("w");
356 SDL_InvalidParamError("h");
360 /* Make sure we don't exceed any window size limits */
361 if (window->min_w && w < window->min_w)
365 if (window->max_w && w > window->max_w)
369 if (window->min_h && h < window->min_h)
373 if (window->max_h && h > window->max_h)
378 window->windowed.w = w;
379 window->windowed.h = h;
386 _tizen_rotation_do(SDL_WindowData *wind, int rotation)
390 SDL_Window *window = SDL_GetVideoDevice()->windows;
393 int window_w, window_h;
394 if(wind->rotation == 0 || wind->rotation == 180)
395 ecore_wl_window_geometry_get(wind->window, 0, 0, &window_w, &window_h);
397 ecore_wl_window_geometry_get(wind->window, 0, 0, &window_h, &window_w);
399 _tizen_set_window_size(window, window_w, window_h);
401 if(wind->support_pre_rotation)
402 Tizen_pre_rotation_set(wind, rotation);
404 _tizen_send_rotation_event(window, wind->rotation);
405 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
406 wind->received_rotation = 1;
411 _tizen_rotate_update(SDL_WindowData *wind)
416 if (ecore_wl_window_ignore_output_transform_get(wind->window))
422 Ecore_Wl_Output *output = ecore_wl_window_output_find(wind->window);
423 screen_rotation = ecore_wl_output_transform_get(output) * 90;
426 //Set Screen Rotation
427 wind->output_rotation = screen_rotation;
429 if(wind->support_pre_rotation)
430 ecore_wl_window_buffer_transform_set(wind->window, wind->output_rotation / 90);
432 int rotation = (wind->output_rotation + wind->rotation) % 360;
433 _tizen_rotation_do(wind, rotation);
437 Tizen_CreateWindow(_THIS, SDL_Window *window)
439 SDL_VideoData *data = _this->driverdata;
440 SDL_WindowData *wind;
441 Ecore_Wl_Global *global;
442 Eina_Inlist *globals;
444 wind = calloc(1, sizeof * wind);
446 return SDL_OutOfMemory();
449 window->driverdata = wind;
450 window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */
452 #if SDL_VIDEO_OPENGL_EGL
453 if (window->flags & SDL_WINDOW_OPENGL) {
454 SDL_GL_LoadLibrary(NULL);
459 if (window->flags & SDL_WINDOW_VULKAN) {
460 if (!_this->vulkan_GetInstanceExtensions) {
461 SDL_SetError("No Vulkan support in video driver");
464 if (_this->vulkan_LoadLibrary(_this, NULL) < 0) {
465 SDL_SetError("Fail to load Vulkan Library");
470 if (window->x == SDL_WINDOWPOS_UNDEFINED) {
473 if (window->y == SDL_WINDOWPOS_UNDEFINED) {
477 if (!(globals = ecore_wl_globals_get()))
479 SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Failed to get wayland globals");
483 wind->window = ecore_wl_window_new(NULL,
484 window->x, window->y, window->w, window->h,
485 ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
487 SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Failed to create wayland window");
490 _tizen_output_transform_register(wind);
492 wind->surface = ecore_wl_window_surface_create(wind->window);
493 if (!wind->surface) {
494 SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Failed to create wayland window surface");
497 ecore_wl_window_type_set(wind->window, ECORE_WL_WINDOW_TYPE_UTILITY);
500 wind->rotation_supported = 0;
501 wind->received_rotation = 0;
503 #if SDL_VIDEO_OPENGL_EGL
504 if (window->flags & SDL_WINDOW_OPENGL) {
506 if(wind->output_rotation == 90 || wind->output_rotation == 270)
507 wind->egl_window = wl_egl_window_create(wind->surface, window->h, window->w);
509 wind->egl_window = wl_egl_window_create(wind->surface, window->w, window->h);
511 /* Create the GLES window surface */
512 wind->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wind->egl_window);
513 if (wind->egl_surface == EGL_NO_SURFACE) {
514 SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "failed to create a window surface");
518 if (!_this->gl_config.alpha_size) {
519 ecore_wl_window_opaque_region_set(wind->window, window->x, window->y, window->w, window->h);
522 wl_surface_set_opaque_region(wind->surface, NULL);
525 //Support PreRotation
526 wind->support_pre_rotation = 0;
527 if (_tizen_rotation_type_get() && _tizen_PreRotatotion_LoadLibrary(wind, "libwayland-egl.so")) {
528 if (wind->tizen_pre_rotation_data->wl_egl_window_get_capabilities(wind->egl_window) == TIZEN_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) {
529 wind->support_pre_rotation = 1;
534 wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
540 wind->id = ecore_wl_window_id_get(wind->window);
541 eina_hash_add(data->windows, &wind->id, window);
543 Tizen_InitKeyboard(_this);
544 SDL_SetMouseFocus(window);
546 if (window->flags & 0x00008000) {
547 ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
548 ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
551 EINA_INLIST_FOREACH(globals, global) {
552 if (!strcmp(global->interface, "tizen_policy_ext")) {
553 wind->rotation_supported = 1;
557 // Add orientaiton hint cb
558 _tizen_window_orientation_add_hint((void*)wind);
560 _tizen_rotate_update(wind);
566 Tizen_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
568 //Add setting window bordered.
572 _tizen_window_resize(SDL_Window *window)
574 SDL_WindowData *wind = window->driverdata;
575 if (!wind->egl_window) {
579 if(wind->support_pre_rotation && (wind->rotation==90 || wind->rotation==270))
580 ecore_wl_window_update_size(wind->window, window->h, window->w);
582 ecore_wl_window_update_size(wind->window, window->w, window->h);
584 // TODO : consider to rotation status.
585 #if SDL_VIDEO_OPENGL_EGL
586 if (window->flags & SDL_WINDOW_OPENGL) {
587 if(wind->output_rotation==90 || wind->output_rotation==270)
588 wl_egl_window_resize(wind->egl_window, window->h, window->w, 0, 0);
590 wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
596 _tizen_setwindowsize(SDL_Window *window)
598 SDL_WindowData *wind = window->driverdata;
605 Tizen_SetWindowSize(_THIS, SDL_Window *window)
607 _tizen_window_resize(window);
611 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
613 SDL_WindowData *wind = window->driverdata;
618 if (w) *w = window->w;
619 if (h) *h = window->h;
623 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
625 SDL_WindowData *wind = window->driverdata;
630 // TODO : consider to rotation status.
631 ecore_wl_window_position_set(wind->window, window->x, window->y);
635 Tizen_DestroyWindow(_THIS, SDL_Window *window)
637 SDL_VideoData *data = _this->driverdata;
638 SDL_WindowData *wind = window->driverdata;
641 eina_hash_del(data->windows, &wind->id, window);
642 #if SDL_VIDEO_OPENGL_EGL
643 if (window->flags & SDL_WINDOW_OPENGL) {
644 SDL_EGL_DestroySurface(_this, wind->egl_surface);
645 wl_egl_window_destroy(wind->egl_window);
648 ecore_wl_window_free(wind->window);
652 window->driverdata = NULL;
656 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
658 SDL_VideoData *data = _this->driverdata;
661 id = ecore_wl_window_id_get(ewin);
662 return (SDL_Window*)eina_hash_find(data->windows, &id);
666 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
669 Ecore_Wl_Event_Window_Visibility_Change *ev;
674 ew = ecore_wl_window_find(ev->win);
675 window = Tizen_FindWindow(_this, ew);
677 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
678 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
679 return ECORE_CALLBACK_PASS_ON;
683 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
688 SDL_WindowData *wind;
689 Ecore_Wl_Event_Window_Configure *ev;
691 ew = ecore_wl_window_find(ev->win);
692 window = Tizen_FindWindow(_this, ew);
693 wind = window->driverdata;
695 if (wind->rotation_supported == 0){
696 return ECORE_CALLBACK_PASS_ON;
699 int nx = 0, ny = 0, nw = 0, nh = 0;
700 SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
702 ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
706 SDL_Log("[SDL_Size] * _tizen_cb_window_configure :: w->w:%d, w->h:%d, nw:%d, nh:%d", window->w, window->h, nw, nh);
707 if ((window->x != nx) || (window->y != ny))
708 ecore_wl_window_position_set(ew, nx, ny);
710 if ((window->w != nw) || (window->h != nh)) {
711 _tizen_setwindowsize(window);
714 return ECORE_CALLBACK_PASS_ON;
719 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
722 Ecore_Wl_Event_Window_Rotate *ev;
725 SDL_WindowData *wind;
729 return ECORE_CALLBACK_PASS_ON;
732 ew = ecore_wl_window_find(ev->win);
733 window = Tizen_FindWindow(_this, ew);
734 wind = window->driverdata;
736 if (wind->rotation != ev->angle) {
737 /* set ecore_wayland window rotation */
738 wind->rotation = ev->angle;
739 ecore_wl_window_rotation_set(wind->window, wind->rotation);
740 _tizen_rotate_update(wind);
743 return ECORE_CALLBACK_PASS_ON;
747 Tizen_InitWindow(_THIS)
749 SDL_VideoData *data = _this->driverdata;
751 data->windows = eina_hash_int32_new(NULL);
753 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
754 _tizen_cb_event_window_visibility_change,_this);
755 ecore_event_handler_add(ECORE_EVENT_KEY_UP,
756 _tizen_cb_event_keyup_change,_this);
757 ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
758 _tizen_cb_event_keydown_change,_this);
759 ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
760 _tizen_cb_event_mousedown_change,_this);
761 ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
762 _tizen_cb_event_mouseup_change,_this);
763 ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
764 _tizen_cb_event_mousemove_change,_this);
765 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
766 _tizen_cb_event_window_rotate,_this);
767 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
768 _tizen_cb_window_configure,_this);
769 ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
770 _tizen_cb_event_joystick_change,_this);
771 ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
772 _tizen_cb_event_focus_in,_this);
773 ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
774 _tizen_cb_event_focus_out,_this);
775 ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
776 _tizen_cb_event_mouse_in,_this);
777 ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
778 _tizen_cb_event_mouse_out,_this);
780 data->current_thread = SDL_GetThreadID(0);
786 Tizen_DeinitWindow(_THIS)
788 SDL_VideoData *data = _this->driverdata;
790 eina_hash_free(data->windows);
792 #endif /* SDL_VIDEO_DRIVER_TIZEN */
794 /* vi: set ts=4 sw=4 expandtab: */