sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_emscriptenmouse.c (8132B)


      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 {
     36     SDL_Cursor* cursor;
     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) {
     43             SDL_OutOfMemory();
     44             SDL_free(cursor);
     45             return NULL;
     46         }
     47 
     48         curdata->system_cursor = cursor_str;
     49         curdata->is_custom = is_custom;
     50         cursor->driverdata = curdata;
     51     }
     52     else {
     53         SDL_OutOfMemory();
     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 
     71     conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
     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) {
    138         case SDL_SYSTEM_CURSOR_ARROW:
    139             cursor_name = "default";
    140             break;
    141         case SDL_SYSTEM_CURSOR_IBEAM:
    142             cursor_name = "text";
    143             break;
    144         case SDL_SYSTEM_CURSOR_WAIT:
    145             cursor_name = "wait";
    146             break;
    147         case SDL_SYSTEM_CURSOR_CROSSHAIR:
    148             cursor_name = "crosshair";
    149             break;
    150         case SDL_SYSTEM_CURSOR_WAITARROW:
    151             cursor_name = "progress";
    152             break;
    153         case SDL_SYSTEM_CURSOR_SIZENWSE:
    154             cursor_name = "nwse-resize";
    155             break;
    156         case SDL_SYSTEM_CURSOR_SIZENESW:
    157             cursor_name = "nesw-resize";
    158             break;
    159         case SDL_SYSTEM_CURSOR_SIZEWE:
    160             cursor_name = "ew-resize";
    161             break;
    162         case SDL_SYSTEM_CURSOR_SIZENS:
    163             cursor_name = "ns-resize";
    164             break;
    165         case SDL_SYSTEM_CURSOR_SIZEALL:
    166             cursor_name = "move";
    167             break;
    168         case SDL_SYSTEM_CURSOR_NO:
    169             cursor_name = "not-allowed";
    170             break;
    171         case SDL_SYSTEM_CURSOR_HAND:
    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             }
    193             SDL_free(cursor->driverdata);
    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 {
    237     SDL_Window *window;
    238     SDL_WindowData *window_data;
    239 
    240     /* TODO: pointer lock isn't actually enabled yet */
    241     if(enabled) {
    242         window = SDL_GetMouseFocus();
    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
    261 Emscripten_InitMouse()
    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
    276 Emscripten_FiniMouse()
    277 {
    278 }
    279 
    280 #endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
    281 
    282 /* vi: set ts=4 sw=4 expandtab: */
    283