Imported Upstream version 2.0.8
[platform/upstream/SDL.git] / src / video / mir / SDL_mirmouse.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21
22 /*
23   Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
24 */
25
26 #include "../../SDL_internal.h"
27
28 #if SDL_VIDEO_DRIVER_MIR
29
30 #include "../../events/SDL_mouse_c.h"
31 #include "../SDL_sysvideo.h"
32 #include "SDL_assert.h"
33
34 #include "SDL_mirdyn.h"
35
36 #include "SDL_mirvideo.h"
37 #include "SDL_mirmouse.h"
38 #include "SDL_mirwindow.h"
39
40 typedef struct
41 {
42     MirCursorConfiguration* conf;
43     MirBufferStream*        stream;
44     char const*             name;
45 } MIR_Cursor;
46
47 static SDL_Cursor*
48 MIR_CreateDefaultCursor()
49 {
50     SDL_Cursor* cursor;
51
52     cursor = SDL_calloc(1, sizeof(SDL_Cursor));
53     if (cursor) {
54
55         MIR_Cursor* mir_cursor = SDL_calloc(1, sizeof(MIR_Cursor));
56         if (mir_cursor) {
57             mir_cursor->conf   = NULL;
58             mir_cursor->stream = NULL;
59             mir_cursor->name   = NULL;
60             cursor->driverdata = mir_cursor;
61         }
62         else {
63             SDL_OutOfMemory();
64             SDL_free(cursor);
65             cursor = NULL;
66         }
67     }
68     else {
69         SDL_OutOfMemory();
70     }
71
72     return cursor;
73 }
74
75 static void
76 CopySurfacePixelsToMirStream(SDL_Surface* surface, MirBufferStream* stream)
77 {
78     char* dest, *pixels;
79     int i, s_w, s_h, r_stride, p_stride, bytes_per_pixel, bytes_per_row;
80
81     MirGraphicsRegion region;
82     MIR_mir_buffer_stream_get_graphics_region(stream, &region);
83
84     s_w = surface->w;
85     s_h = surface->h;
86
87     bytes_per_pixel = surface->format->BytesPerPixel;
88     bytes_per_row   = bytes_per_pixel * s_w;
89
90     dest = region.vaddr;
91     pixels = (char*)surface->pixels;
92
93     r_stride = region.stride;
94     p_stride = surface->pitch;
95
96     for (i = 0; i < s_h; i++)
97     {
98         SDL_memcpy(dest, pixels, bytes_per_row);
99         dest   += r_stride;
100         pixels += p_stride;
101     }
102 }
103
104 static SDL_Cursor*
105 MIR_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
106 {
107     MirCursorConfiguration* conf;
108     MirBufferStream*        stream;
109
110     int s_w = surface->w;
111     int s_h = surface->h;
112
113     MIR_Data* mir_data     = (MIR_Data*)SDL_GetVideoDevice()->driverdata;
114     SDL_Cursor* cursor     = MIR_CreateDefaultCursor();
115     MIR_Cursor* mir_cursor;
116
117     if (!cursor) {
118         return NULL;
119     }
120
121     mir_cursor = (MIR_Cursor*)cursor->driverdata;
122
123     stream = MIR_mir_connection_create_buffer_stream_sync(mir_data->connection,
124                                                           s_w, s_h, mir_data->pixel_format,
125                                                           mir_buffer_usage_software);
126
127     conf = MIR_mir_cursor_configuration_from_buffer_stream(stream, hot_x, hot_y);
128
129     CopySurfacePixelsToMirStream(surface, stream);
130     MIR_mir_buffer_stream_swap_buffers_sync(stream);
131
132     mir_cursor->conf   = conf;
133     mir_cursor->stream = stream;
134
135     return cursor;
136 }
137
138 static SDL_Cursor*
139 MIR_CreateSystemCursor(SDL_SystemCursor id)
140 {
141     char const* cursor_name = NULL;
142     SDL_Cursor* cursor;
143     MIR_Cursor* mir_cursor;
144
145     switch(id) {
146         case SDL_SYSTEM_CURSOR_ARROW:
147             cursor_name = MIR_mir_arrow_cursor_name;
148             break;
149         case SDL_SYSTEM_CURSOR_IBEAM:
150             cursor_name = MIR_mir_caret_cursor_name;
151             break;
152         case SDL_SYSTEM_CURSOR_WAIT:
153             cursor_name = MIR_mir_busy_cursor_name;
154             break;
155         case SDL_SYSTEM_CURSOR_CROSSHAIR:
156             /* Unsupported */
157             cursor_name = MIR_mir_arrow_cursor_name;
158             break;
159         case SDL_SYSTEM_CURSOR_WAITARROW:
160             cursor_name = MIR_mir_busy_cursor_name;
161             break;
162         case SDL_SYSTEM_CURSOR_SIZENWSE:
163             cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
164             break;
165         case SDL_SYSTEM_CURSOR_SIZENESW:
166             cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
167             break;
168         case SDL_SYSTEM_CURSOR_SIZEWE:
169             cursor_name = MIR_mir_horizontal_resize_cursor_name;
170             break;
171         case SDL_SYSTEM_CURSOR_SIZENS:
172             cursor_name = MIR_mir_vertical_resize_cursor_name;
173             break;
174         case SDL_SYSTEM_CURSOR_SIZEALL:
175             cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
176             break;
177         case SDL_SYSTEM_CURSOR_NO:
178             /* Unsupported */
179             cursor_name = MIR_mir_closed_hand_cursor_name;
180             break;
181         case SDL_SYSTEM_CURSOR_HAND:
182             cursor_name = MIR_mir_open_hand_cursor_name;
183             break;
184         default:
185             SDL_assert(0);
186             return NULL;
187     }
188
189     cursor = MIR_CreateDefaultCursor();
190     if (!cursor) {
191         return NULL;
192     }
193
194     mir_cursor = (MIR_Cursor*)cursor->driverdata;
195     mir_cursor->name = cursor_name;
196
197     return cursor;
198 }
199
200 static void
201 MIR_FreeCursor(SDL_Cursor* cursor)
202 {
203     if (cursor) {
204
205         if (cursor->driverdata) {
206             MIR_Cursor* mir_cursor = (MIR_Cursor*)cursor->driverdata;
207
208             if (mir_cursor->conf)
209                 MIR_mir_cursor_configuration_destroy(mir_cursor->conf);
210             if (mir_cursor->stream)
211                 MIR_mir_buffer_stream_release_sync(mir_cursor->stream);
212
213             SDL_free(mir_cursor);
214         }
215
216         SDL_free(cursor);
217     }
218 }
219
220 static int
221 MIR_ShowCursor(SDL_Cursor* cursor)
222 {
223     MIR_Data* mir_data      = (MIR_Data*)SDL_GetVideoDevice()->driverdata;
224     MIR_Window* mir_window  = mir_data->current_window;
225
226     if (cursor && cursor->driverdata) {
227         if (mir_window && MIR_mir_window_is_valid(mir_window->window)) {
228             MIR_Cursor* mir_cursor = (MIR_Cursor*)cursor->driverdata;
229
230             if (mir_cursor->name != NULL) {
231                 MirWindowSpec* spec = MIR_mir_create_window_spec(mir_data->connection);
232                 MIR_mir_window_spec_set_cursor_name(spec, mir_cursor->name);
233                 MIR_mir_window_apply_spec(mir_window->window, spec);
234                 MIR_mir_window_spec_release(spec);
235             }
236
237             if (mir_cursor->conf) {
238                 MIR_mir_window_configure_cursor(mir_window->window, mir_cursor->conf);
239             }
240         }
241     }
242     else if(mir_window && MIR_mir_window_is_valid(mir_window->window)) {
243         MIR_mir_window_configure_cursor(mir_window->window, NULL);
244     }
245
246     return 0;
247 }
248
249 static void
250 MIR_WarpMouse(SDL_Window* window, int x, int y)
251 {
252     SDL_Unsupported();
253 }
254
255 static int
256 MIR_WarpMouseGlobal(int x, int y)
257 {
258     return SDL_Unsupported();
259 }
260
261 static int
262 MIR_SetRelativeMouseMode(SDL_bool enabled)
263 {
264     return 0;
265 }
266
267 /* TODO Actually implement the cursor, need to wait for mir support */
268 void
269 MIR_InitMouse()
270 {
271     SDL_Mouse* mouse = SDL_GetMouse();
272
273     mouse->CreateCursor         = MIR_CreateCursor;
274     mouse->ShowCursor           = MIR_ShowCursor;
275     mouse->FreeCursor           = MIR_FreeCursor;
276     mouse->WarpMouse            = MIR_WarpMouse;
277     mouse->WarpMouseGlobal      = MIR_WarpMouseGlobal;
278     mouse->CreateSystemCursor   = MIR_CreateSystemCursor;
279     mouse->SetRelativeMouseMode = MIR_SetRelativeMouseMode;
280
281     SDL_SetDefaultCursor(MIR_CreateDefaultCursor());
282 }
283
284 void
285 MIR_FiniMouse()
286 {
287 }
288
289 #endif /* SDL_VIDEO_DRIVER_MIR */
290
291 /* vi: set ts=4 sw=4 expandtab: */
292