SDL  2.0
SDL_emscriptenmouse.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_EMSCRIPTEN
24 
25 #include <emscripten/emscripten.h>
26 #include <emscripten/html5.h>
27 
28 #include "SDL_emscriptenmouse.h"
29 #include "SDL_emscriptenvideo.h"
30 
31 #include "../../events/SDL_mouse_c.h"
32 
33 static SDL_Cursor*
34 Emscripten_CreateCursorFromString(const char* cursor_str, SDL_bool is_custom)
35 {
37  Emscripten_CursorData *curdata;
38 
39  cursor = SDL_calloc(1, sizeof(SDL_Cursor));
40  if (cursor) {
41  curdata = (Emscripten_CursorData *) SDL_calloc(1, sizeof(*curdata));
42  if (!curdata) {
45  return NULL;
46  }
47 
48  curdata->system_cursor = cursor_str;
49  curdata->is_custom = is_custom;
50  cursor->driverdata = curdata;
51  }
52  else {
54  }
55 
56  return cursor;
57 }
58 
59 static SDL_Cursor*
60 Emscripten_CreateDefaultCursor()
61 {
62  return Emscripten_CreateCursorFromString("default", SDL_FALSE);
63 }
64 
65 static SDL_Cursor*
66 Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
67 {
68  const char *cursor_url = NULL;
69  SDL_Surface *conv_surf;
70 
72 
73  if (!conv_surf) {
74  return NULL;
75  }
76 
77  cursor_url = (const char *)EM_ASM_INT({
78  var w = $0;
79  var h = $1;
80  var hot_x = $2;
81  var hot_y = $3;
82  var pixels = $4;
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 = hot_x === 0 && hot_y === 0
118  ? "url(" + canvas.toDataURL() + "), auto"
119  : "url(" + canvas.toDataURL() + ") " + hot_x + " " + hot_y + ", auto";
120 
121  var urlBuf = _malloc(url.length + 1);
122  stringToUTF8(url, urlBuf, url.length + 1);
123 
124  return urlBuf;
125  }, surface->w, surface->h, hot_x, hot_y, conv_surf->pixels);
126 
127  SDL_FreeSurface(conv_surf);
128 
129  return Emscripten_CreateCursorFromString(cursor_url, SDL_TRUE);
130 }
131 
132 static SDL_Cursor*
133 Emscripten_CreateSystemCursor(SDL_SystemCursor id)
134 {
135  const char *cursor_name = NULL;
136 
137  switch(id) {
139  cursor_name = "default";
140  break;
142  cursor_name = "text";
143  break;
145  cursor_name = "wait";
146  break;
148  cursor_name = "crosshair";
149  break;
151  cursor_name = "progress";
152  break;
154  cursor_name = "nwse-resize";
155  break;
157  cursor_name = "nesw-resize";
158  break;
160  cursor_name = "ew-resize";
161  break;
163  cursor_name = "ns-resize";
164  break;
166  cursor_name = "move";
167  break;
169  cursor_name = "not-allowed";
170  break;
172  cursor_name = "pointer";
173  break;
174  default:
175  SDL_assert(0);
176  return NULL;
177  }
178 
179  return Emscripten_CreateCursorFromString(cursor_name, SDL_FALSE);
180 }
181 
182 static void
183 Emscripten_FreeCursor(SDL_Cursor* cursor)
184 {
185  Emscripten_CursorData *curdata;
186  if (cursor) {
187  curdata = (Emscripten_CursorData *) cursor->driverdata;
188 
189  if (curdata != NULL) {
190  if (curdata->is_custom) {
191  SDL_free((char *)curdata->system_cursor);
192  }
194  }
195 
196  SDL_free(cursor);
197  }
198 }
199 
200 static int
201 Emscripten_ShowCursor(SDL_Cursor* cursor)
202 {
203  Emscripten_CursorData *curdata;
204  if (SDL_GetMouseFocus() != NULL) {
205  if(cursor && cursor->driverdata) {
206  curdata = (Emscripten_CursorData *) cursor->driverdata;
207 
208  if(curdata->system_cursor) {
209  EM_ASM_INT({
210  if (Module['canvas']) {
211  Module['canvas'].style['cursor'] = UTF8ToString($0);
212  }
213  return 0;
214  }, curdata->system_cursor);
215  }
216  }
217  else {
218  EM_ASM(
219  if (Module['canvas']) {
220  Module['canvas'].style['cursor'] = 'none';
221  }
222  );
223  }
224  }
225  return 0;
226 }
227 
228 static void
229 Emscripten_WarpMouse(SDL_Window* window, int x, int y)
230 {
231  SDL_Unsupported();
232 }
233 
234 static int
235 Emscripten_SetRelativeMouseMode(SDL_bool enabled)
236 {
238  SDL_WindowData *window_data;
239 
240  /* TODO: pointer lock isn't actually enabled yet */
241  if(enabled) {
243  if (window == NULL) {
244  return -1;
245  }
246 
247  window_data = (SDL_WindowData *) window->driverdata;
248 
249  if(emscripten_request_pointerlock(window_data->canvas_id, 1) >= EMSCRIPTEN_RESULT_SUCCESS) {
250  return 0;
251  }
252  } else {
253  if(emscripten_exit_pointerlock() >= EMSCRIPTEN_RESULT_SUCCESS) {
254  return 0;
255  }
256  }
257  return -1;
258 }
259 
260 void
262 {
263  SDL_Mouse* mouse = SDL_GetMouse();
264 
265  mouse->CreateCursor = Emscripten_CreateCursor;
266  mouse->ShowCursor = Emscripten_ShowCursor;
267  mouse->FreeCursor = Emscripten_FreeCursor;
268  mouse->WarpMouse = Emscripten_WarpMouse;
269  mouse->CreateSystemCursor = Emscripten_CreateSystemCursor;
270  mouse->SetRelativeMouseMode = Emscripten_SetRelativeMouseMode;
271 
272  SDL_SetDefaultCursor(Emscripten_CreateDefaultCursor());
273 }
274 
275 void
277 {
278 }
279 
280 #endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
281 
282 /* vi: set ts=4 sw=4 expandtab: */
283 
#define SDL_assert(condition)
Definition: SDL_assert.h:171
#define SDL_ConvertSurfaceFormat
#define SDL_free
#define SDL_GetMouseFocus
#define SDL_FreeSurface
#define SDL_calloc
void Emscripten_FiniMouse()
void Emscripten_InitMouse()
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define SDL_Unsupported()
Definition: SDL_error.h:89
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
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:175
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:164
SDL_SystemCursor
Cursor types for SDL_CreateSystemCursor().
Definition: SDL_mouse.h:47
@ SDL_SYSTEM_CURSOR_SIZENS
Definition: SDL_mouse.h:56
@ SDL_SYSTEM_CURSOR_HAND
Definition: SDL_mouse.h:59
@ SDL_SYSTEM_CURSOR_ARROW
Definition: SDL_mouse.h:48
@ SDL_SYSTEM_CURSOR_SIZENWSE
Definition: SDL_mouse.h:53
@ SDL_SYSTEM_CURSOR_SIZENESW
Definition: SDL_mouse.h:54
@ SDL_SYSTEM_CURSOR_IBEAM
Definition: SDL_mouse.h:49
@ SDL_SYSTEM_CURSOR_NO
Definition: SDL_mouse.h:58
@ SDL_SYSTEM_CURSOR_WAITARROW
Definition: SDL_mouse.h:52
@ SDL_SYSTEM_CURSOR_SIZEALL
Definition: SDL_mouse.h:57
@ SDL_SYSTEM_CURSOR_WAIT
Definition: SDL_mouse.h:50
@ SDL_SYSTEM_CURSOR_SIZEWE
Definition: SDL_mouse.h:55
@ SDL_SYSTEM_CURSOR_CROSSHAIR
Definition: SDL_mouse.h:51
GLeglImageOES image
Definition: SDL_opengl.h:2148
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
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint GLfloat * val
GLenum src
GLenum GLenum dst
GLuint num
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:263
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
#define NULL
Definition: begin_code.h:163
EGLSurface surface
Definition: eglext.h:248
EGLContext ctx
Definition: eglext.h:208
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
void * driverdata
Definition: SDL_mouse_c.h:33
int(* SetRelativeMouseMode)(SDL_bool enabled)
Definition: SDL_mouse_c.h:67
void(* WarpMouse)(SDL_Window *window, int x, int y)
Definition: SDL_mouse_c.h:61
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:46
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:58
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:52
SDL_Cursor *(* CreateSystemCursor)(SDL_SystemCursor id)
Definition: SDL_mouse_c.h:49
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
void * pixels
Definition: SDL_surface.h:76
The type used to identify a window.
Definition: SDL_sysvideo.h:75
SDL_Cursor * cursor
Definition: testwm2.c:40