[SDL_Tizen] Improve indicator functions
[platform/upstream/SDL.git] / src / video / tizen / SDL_tizenmouse.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 #ifndef _GNU_SOURCE
26 #define _GNU_SOURCE
27 #endif
28
29 #include <sys/mman.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33
34 #include "../../events/SDL_mouse_c.h"
35
36 #include "SDL_log.h"
37 #include "SDL_timer.h"
38 #include "SDL_tizenmouse.h"
39 #include "SDL_tizentouch.h"
40
41 #include "SDL_tizenvideo.h"
42
43 typedef struct {
44     struct wl_buffer   *buffer;
45     struct wl_surface  *surface;
46     SDL_WindowData     *win_data;
47
48     int                hot_x, hot_y;
49     int                w, h;
50
51     /* Either a preloaded cursor, or one we created ourselves */
52     struct wl_cursor   *cursor;
53     void               *shm_data;
54 } Tizen_CursorData;
55
56 static int
57 wayland_create_tmp_file(off_t size)
58 {
59     static const char template[] = "/sdl-shared-XXXXXX";
60     char *xdg_path;
61     char tmp_path[PATH_MAX];
62     int fd;
63
64     xdg_path = SDL_getenv("XDG_RUNTIME_DIR");
65     if (!xdg_path) {
66         errno = ENOENT;
67         return -1;
68     }
69
70     SDL_strlcpy(tmp_path, xdg_path, PATH_MAX);
71     SDL_strlcat(tmp_path, template, PATH_MAX);
72
73     fd = mkostemp(tmp_path, O_CLOEXEC);
74     if (fd < 0)
75         return -1;
76
77     if (ftruncate(fd, size) < 0) {
78         close(fd);
79         return -1;
80     }
81
82     return fd;
83 }
84
85 static void
86 mouse_buffer_release(void *data, struct wl_buffer *buffer)
87 {
88 }
89
90 static const struct wl_buffer_listener mouse_buffer_listener = {
91     mouse_buffer_release
92 };
93
94 static int
95 create_buffer_from_shm(Tizen_CursorData *d, int width, int height, uint32_t format)
96 {
97     struct wl_shm_pool *shm_pool;
98
99     int stride = width * 4;
100     int size = stride * height;
101
102     int shm_fd;
103
104     shm_fd = wayland_create_tmp_file(size);
105     if (shm_fd < 0)
106     {
107         SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "creating mouse cursor buffer failed!\n");
108         return -1;
109     }
110
111     d->shm_data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
112     if (d->shm_data == MAP_FAILED) {
113         d->shm_data = NULL;
114         SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "mmap () failed\n");
115         close (shm_fd);
116         return -1;
117     }
118
119     shm_pool = wl_shm_create_pool(ecore_wl_shm_get(), shm_fd, size);
120     d->buffer = wl_shm_pool_create_buffer(shm_pool, 0, width, height, stride, format);
121     wl_buffer_add_listener(d->buffer, &mouse_buffer_listener, d);
122
123     wl_shm_pool_destroy (shm_pool);
124     close (shm_fd);
125
126     return 0;
127 }
128
129 static SDL_Cursor *
130 Tizen_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
131 {
132     SDL_Cursor *cursor;
133
134     cursor = calloc(1, sizeof (*cursor));
135     if (cursor) {
136         SDL_VideoDevice *vd = SDL_GetVideoDevice ();
137         SDL_Window* window = vd->windows;
138
139         Tizen_CursorData *data = calloc (1, sizeof (Tizen_CursorData));
140         data->win_data = window->driverdata;
141         cursor->driverdata = (void *) data;
142
143         /* Assume ARGB8888 */
144         SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
145         SDL_assert(surface->pitch == surface->w * 4);
146
147         /* Allocate shared memory buffer for this cursor */
148         if (create_buffer_from_shm (data,
149                                     surface->w,
150                                     surface->h,
151                                     WL_SHM_FORMAT_XRGB8888) < 0)
152         {
153             free (cursor->driverdata);
154             free (cursor);
155             return NULL;
156         }
157
158         SDL_memcpy(data->shm_data,
159                    surface->pixels,
160                    surface->h * surface->pitch);
161
162         data->surface = wl_compositor_create_surface(ecore_wl_compositor_get());
163
164         data->hot_x = hot_x;
165         data->hot_y = hot_y;
166         data->w = surface->w;
167         data->h = surface->h;
168     }
169
170     return cursor;
171 }
172
173
174 static void
175 Tizen_FreeCursor(SDL_Cursor *cursor)
176 {
177     Tizen_CursorData *d;
178
179     if (!cursor)
180         return;
181
182     d = cursor->driverdata;
183
184     /* Probably not a cursor we own */
185     if (!d)
186         return;
187
188     if (d->buffer && !d->cursor)
189         wl_buffer_destroy(d->buffer);
190
191     if (d->surface)
192         wl_surface_destroy(d->surface);
193
194     /* Not sure what's meant to happen to shm_data */
195     free (cursor->driverdata);
196     SDL_free(cursor);
197 }
198 /*
199 static int
200 Tizen_ShowCursor(SDL_Cursor *cursor)
201 {
202     if (cursor)
203     {
204         Tizen_CursorData *data = cursor->driverdata;
205         SDL_WindowData *win_data = data->win_data;
206         ecore_wl_window_buffer_attach(win_data->window, data->buffer, 0,0);
207         ecore_wl_input_pointer_set(ecore_wl_input_get(), data->surface, data->hot_x, data->hot_y);
208     }
209     else
210     {
211         ecore_wl_input_pointer_set(ecore_wl_input_get(), NULL, 0, 0);
212     }
213
214     return 0;
215 }
216 */
217 void
218 Tizen_InitMouse(void)
219 {
220     SDL_Mouse *mouse = SDL_GetMouse();
221
222     mouse->CreateCursor = Tizen_CreateCursor;
223     mouse->FreeCursor = Tizen_FreeCursor;
224 }
225
226 void
227 Tizen_FiniMouse(void)
228 {
229     /* This effectively assumes that nobody else touches SDL_Mouse which is effectively a singleton */
230     SDL_Mouse *mouse = SDL_GetMouse();
231
232     /* Free the current cursor if not the same pointer as the default cursor */
233     if (mouse->def_cursor != mouse->cur_cursor)
234         Tizen_FreeCursor (mouse->cur_cursor);
235
236     Tizen_FreeCursor (mouse->def_cursor);
237     mouse->def_cursor = NULL;
238     mouse->cur_cursor = NULL;
239
240     mouse->CreateCursor =  NULL;
241     mouse->CreateSystemCursor = NULL;
242     mouse->ShowCursor = NULL;
243     mouse->FreeCursor = NULL;
244     mouse->WarpMouse = NULL;
245     mouse->SetRelativeMouseMode = NULL;
246 }
247
248 void _tizen_get_mouseXY(SDL_Window* window, int x, int y, int* retX, int* retY)
249 {
250     SDL_WindowData *wind = window->driverdata;
251     if((wind->output_rotation + wind->rotation) % 360 == 0)
252     {
253         *retX = x;
254         *retY = y;
255         return;
256     };
257
258     switch (wind->rotation)
259     {
260         case 90:
261         *retX = window->w-y;
262         *retY = x;
263         break;
264         case 270:
265         *retX = y;
266         *retY = window->h-x;
267         break;
268     }
269     return;
270 }
271
272 Eina_Bool
273 _tizen_cb_event_mousedown_change(void *data, int type, void *event)
274 {
275     SDL_VideoDevice *_this = SDL_GetVideoDevice();
276
277     if (!event) return ECORE_CALLBACK_PASS_ON;
278
279     Ecore_Event_Mouse_Button *e = event;
280     Ecore_Wl_Window *ew;
281     SDL_Window *window;
282
283     ew = ecore_wl_window_find(e->window);
284     window = Tizen_FindWindow(_this, ew);
285
286     int x = 0, y = 0;
287     _tizen_get_mouseXY(window, (int)e->x, (int)e->y, &x, &y);
288
289     SDL_VideoData* videoData = SDL_GetVideoDevice()->driverdata;
290     SDL_WindowData *wind = window->driverdata;
291     if(x >= 0 && x <= window->w && y >= 0 && y <= videoData->indicator_height)
292     {
293         if(!videoData->indicator_visible && wind->support_indicator)
294         {
295             videoData->indicator_parent_id = wind->id;
296             _tizen_ecore_ipc_client_send(OP_INDICATOR_SHOW, wind->rotation, wind->g_res_id, 0);
297         }
298     }
299
300     SDL_SendMouseMotion(window, 0, 0, x, y);
301     SDL_SendMouseButton(window, 0, SDL_PRESSED, SDL_BUTTON_LEFT);
302
303     Tizen_OnTouch(_this, 1, e->multi.device, ACTION_POINTER_DOWN, x, y, 1.0f);
304
305     return ECORE_CALLBACK_PASS_ON;
306 }
307
308 Eina_Bool
309 _tizen_cb_event_mouseup_change(void *data, int type, void *event)
310 {
311     SDL_VideoDevice *_this = SDL_GetVideoDevice();
312     if (!event) return ECORE_CALLBACK_PASS_ON;
313
314     Ecore_Event_Mouse_Button *e = event;
315     Ecore_Wl_Window *ew;
316     SDL_Window *window;
317
318     ew = ecore_wl_window_find(e->window);
319     window = Tizen_FindWindow(_this, ew);
320
321     SDL_VideoData* videoData = SDL_GetVideoDevice()->driverdata;
322     SDL_WindowData *wind = window->driverdata;
323
324     if(videoData->indicator_on && wind->support_indicator && videoData->indicator_visible)
325     {
326         _tizen_quickpanel_on(window->driverdata);
327     }
328
329     int x = 0, y = 0;
330     _tizen_get_mouseXY(window, (int)e->x, (int)e->y, &x, &y);
331     SDL_SendMouseMotion(window, 0, 0, x, y);
332     SDL_SendMouseButton(window, 0, SDL_RELEASED, SDL_BUTTON_LEFT);
333
334     Tizen_OnTouch(_this,1,e->multi.device,ACTION_POINTER_UP, x, y, 1.0f);
335
336     return ECORE_CALLBACK_PASS_ON;
337 }
338
339 Eina_Bool
340 _tizen_cb_event_mousemove_change(void *data, int type, void *event)
341 {
342     SDL_VideoDevice *_this = SDL_GetVideoDevice();
343
344     if (!event) return ECORE_CALLBACK_PASS_ON;
345
346     Ecore_Event_Mouse_Move *e = event;
347     Ecore_Wl_Window *ew;
348     SDL_Window *window;
349
350     ew = ecore_wl_window_find(e->window);
351     window = Tizen_FindWindow(_this, ew);
352
353     int x = 0, y = 0;
354     _tizen_get_mouseXY(window, (int)e->x, (int)e->y, &x, &y);
355     SDL_SendMouseMotion(window, 0, 0, x, y);
356
357     Tizen_OnTouch(_this,1,e->multi.device,ACTION_POINTER_MOVE, x, y, 1.0f);
358
359     return ECORE_CALLBACK_PASS_ON;
360 }
361
362 Eina_Bool
363 _tizen_cb_event_mouse_in(void *data, int type EINA_UNUSED, void *event)
364 {
365     SDL_VideoDevice *_this = SDL_GetVideoDevice();
366     Ecore_Wl_Event_Mouse_In *ev;
367     Ecore_Wl_Window *ew;
368     SDL_Window *window;
369
370     ev = event;
371     ew = ecore_wl_window_find(ev->window);
372     window = Tizen_FindWindow(_this, ew);
373
374     SDL_SetMouseFocus(window);
375     return ECORE_CALLBACK_PASS_ON;
376 }
377
378 Eina_Bool
379 _tizen_cb_event_mouse_out(void *data, int type EINA_UNUSED, void *event)
380 {
381     SDL_SetMouseFocus(NULL);
382     return ECORE_CALLBACK_PASS_ON;
383 }
384