SDL  2.0
SDL_emscriptenmouse.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 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 #include "../../SDL_internal.h"
24 
25 #if SDL_VIDEO_DRIVER_EMSCRIPTEN
26 
27 #include <emscripten/emscripten.h>
28 #include <emscripten/html5.h>
29 
30 #include "SDL_emscriptenmouse.h"
31 
32 #include "../../events/SDL_mouse_c.h"
33 #include "SDL_assert.h"
34 
35 static SDL_Cursor*
36 Emscripten_CreateCursorFromString(const char* cursor_str, SDL_bool is_custom)
37 {
39  Emscripten_CursorData *curdata;
40 
41  cursor = SDL_calloc(1, sizeof(SDL_Cursor));
42  if (cursor) {
43  curdata = (Emscripten_CursorData *) SDL_calloc(1, sizeof(*curdata));
44  if (!curdata) {
46  SDL_free(cursor);
47  return NULL;
48  }
49 
50  curdata->system_cursor = cursor_str;
51  curdata->is_custom = is_custom;
52  cursor->driverdata = curdata;
53  }
54  else {
56  }
57 
58  return cursor;
59 }
60 
61 static SDL_Cursor*
62 Emscripten_CreateDefaultCursor()
63 {
64  return Emscripten_CreateCursorFromString("default", SDL_FALSE);
65 }
66 
67 static SDL_Cursor*
68 Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
69 {
70  const char *cursor_url = NULL;
71  SDL_Surface *conv_surf;
72 
73  conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
74 
75  if (!conv_surf) {
76  return NULL;
77  }
78 
79  cursor_url = (const char *)EM_ASM_INT({
80  var w = $0;
81  var h = $1;
82  var pixels = $2;
83 
84  var canvas = document.createElement("canvas");
85  canvas.width = w;
86  canvas.height = h;
87 
88  var ctx = canvas.getContext("2d");
89 
90  var image = ctx.createImageData(w, h);
91  var data = image.data;
92  var src = pixels >> 2;
93  var dst = 0;
94  var num;
95  if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
96  // IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
97  // not UInt8ClampedArray. These don't have buffers, so we need to revert
98  // to copying a byte at a time. We do the undefined check because modern
99  // browsers do not define CanvasPixelArray anymore.
100  num = data.length;
101  while (dst < num) {
102  var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
103  data[dst ] = val & 0xff;
104  data[dst+1] = (val >> 8) & 0xff;
105  data[dst+2] = (val >> 16) & 0xff;
106  data[dst+3] = (val >> 24) & 0xff;
107  src++;
108  dst += 4;
109  }
110  } else {
111  var data32 = new Int32Array(data.buffer);
112  num = data32.length;
113  data32.set(HEAP32.subarray(src, src + num));
114  }
115 
116  ctx.putImageData(image, 0, 0);
117  var url = "url(" + canvas.toDataURL() + "), auto";
118 
119  var urlBuf = _malloc(url.length + 1);
120  stringToUTF8(url, urlBuf, url.length + 1);
121 
122  return urlBuf;
123  }, surface->w, surface->h, conv_surf->pixels);
124 
125  SDL_FreeSurface(conv_surf);
126 
127  return Emscripten_CreateCursorFromString(cursor_url, SDL_TRUE);
128 }
129 
130 static SDL_Cursor*
131 Emscripten_CreateSystemCursor(SDL_SystemCursor id)
132 {
133  const char *cursor_name = NULL;
134 
135  switch(id) {
137  cursor_name = "default";
138  break;
140  cursor_name = "text";
141  break;
143  cursor_name = "wait";
144  break;
146  cursor_name = "crosshair";
147  break;
149  cursor_name = "progress";
150  break;
152  cursor_name = "nwse-resize";
153  break;
155  cursor_name = "nesw-resize";
156  break;
158  cursor_name = "ew-resize";
159  break;
161  cursor_name = "ns-resize";
162  break;
164  break;
166  cursor_name = "not-allowed";
167  break;
169  cursor_name = "pointer";
170  break;
171  default:
172  SDL_assert(0);
173  return NULL;
174  }
175 
176  return Emscripten_CreateCursorFromString(cursor_name, SDL_FALSE);
177 }
178 
179 static void
180 Emscripten_FreeCursor(SDL_Cursor* cursor)
181 {
182  Emscripten_CursorData *curdata;
183  if (cursor) {
184  curdata = (Emscripten_CursorData *) cursor->driverdata;
185 
186  if (curdata != NULL) {
187  if (curdata->is_custom) {
188  SDL_free((char *)curdata->system_cursor);
189  }
190  SDL_free(cursor->driverdata);
191  }
192 
193  SDL_free(cursor);
194  }
195 }
196 
197 static int
198 Emscripten_ShowCursor(SDL_Cursor* cursor)
199 {
200  Emscripten_CursorData *curdata;
201  if (SDL_GetMouseFocus() != NULL) {
202  if(cursor && cursor->driverdata) {
203  curdata = (Emscripten_CursorData *) cursor->driverdata;
204 
205  if(curdata->system_cursor) {
206  EM_ASM_INT({
207  if (Module['canvas']) {
208  Module['canvas'].style['cursor'] = Module['Pointer_stringify']($0);
209  }
210  return 0;
211  }, curdata->system_cursor);
212  }
213  }
214  else {
215  EM_ASM(
216  if (Module['canvas']) {
217  Module['canvas'].style['cursor'] = 'none';
218  }
219  );
220  }
221  }
222  return 0;
223 }
224 
225 static void
226 Emscripten_WarpMouse(SDL_Window* window, int x, int y)
227 {
228  SDL_Unsupported();
229 }
230 
231 static int
232 Emscripten_SetRelativeMouseMode(SDL_bool enabled)
233 {
234  /* TODO: pointer lock isn't actually enabled yet */
235  if(enabled) {
236  if(emscripten_request_pointerlock(NULL, 1) >= EMSCRIPTEN_RESULT_SUCCESS) {
237  return 0;
238  }
239  } else {
240  if(emscripten_exit_pointerlock() >= EMSCRIPTEN_RESULT_SUCCESS) {
241  return 0;
242  }
243  }
244  return -1;
245 }
246 
247 void
249 {
250  SDL_Mouse* mouse = SDL_GetMouse();
251 
252  mouse->CreateCursor = Emscripten_CreateCursor;
253  mouse->ShowCursor = Emscripten_ShowCursor;
254  mouse->FreeCursor = Emscripten_FreeCursor;
255  mouse->WarpMouse = Emscripten_WarpMouse;
256  mouse->CreateSystemCursor = Emscripten_CreateSystemCursor;
257  mouse->SetRelativeMouseMode = Emscripten_SetRelativeMouseMode;
258 
259  SDL_SetDefaultCursor(Emscripten_CreateDefaultCursor());
260 }
261 
262 void
264 {
265 }
266 
267 #endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
268 
269 /* vi: set ts=4 sw=4 expandtab: */
270 
#define SDL_ConvertSurfaceFormat
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:112
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:52
GLuint num
GLeglImageOES image
Definition: SDL_opengl.h:2148
GLenum GLenum dst
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
int(* SetRelativeMouseMode)(SDL_bool enabled)
Definition: SDL_mouse_c.h:67
void Emscripten_FiniMouse()
GLfloat GLfloat GLfloat GLfloat h
EGLSurface surface
Definition: eglext.h:248
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLenum src
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:46
GLuint GLfloat * val
void * pixels
Definition: SDL_surface.h:75
#define SDL_FreeSurface
#define SDL_free
GLubyte GLubyte GLubyte GLubyte w
SDL_SystemCursor
Cursor types for SDL_CreateSystemCursor().
Definition: SDL_mouse.h:46
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:101
GLenum GLenum GLsizei const GLuint GLboolean enabled
SDL_Cursor * cursor
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:58
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
#define SDL_GetMouseFocus
#define SDL_calloc
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
The type used to identify a window.
Definition: SDL_sysvideo.h:73
void(* WarpMouse)(SDL_Window *window, int x, int y)
Definition: SDL_mouse_c.h:61
SDL_Cursor *(* CreateSystemCursor)(SDL_SystemCursor id)
Definition: SDL_mouse_c.h:49
void * driverdata
Definition: SDL_mouse_c.h:33
#define SDL_Unsupported()
Definition: SDL_error.h:53
void Emscripten_InitMouse()
int uint32_t uint32_t uint32_t uint32_t uint32_t int drmModeModeInfoPtr mode int uint32_t uint32_t uint32_t uint32_t int32_t hot_x
Definition: SDL_kmsdrmsym.h:55
EGLContext ctx
Definition: eglext.h:208