ecere/ecere.epj: MinEmscripten, Static Changes
[sdk] / ecere / src / gui / drivers / EmscriptenInterface.ec
1 namespace gui::drivers;
2
3 #ifdef BUILDING_ECERE_COM
4 import "Window"
5 import "Interface"
6 #else
7 #ifdef ECERE_STATIC
8 public import static "ecere"
9 #else
10 public import "ecere"
11 #endif
12 #endif
13
14 #ifdef __EMSCRIPTEN__
15
16 #include <stdio.h>
17
18 // source file line number printf (sflnprintf)
19 #define sflnprintf(format,...) printf("%s:% 5d: " format, __FILE__, __LINE__, ##__VA_ARGS__)
20
21 #define property _property
22 #define uint _uint
23
24 #include <emscripten.h>
25 #include <html5.h>
26
27 #undef property
28 #undef uint
29
30 default:
31 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
32 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp;
33 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
34 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
35 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;
36 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
37 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
38 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;
39 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
40 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
41 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
42 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick;
43 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown;
44 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
45
46 private:
47
48 static Point lastMouse;
49
50 static inline const char *emscripten_event_type_to_string(int eventType) {
51   const char *events[] = { "(invalid)", "(none)", "keypress", "keydown", "keyup", "click", "mousedown", "mouseup", "dblclick", "mousemove", "wheel", "resize",
52     "scroll", "blur", "focus", "focusin", "focusout", "deviceorientation", "devicemotion", "orientationchange", "fullscreenchange", "pointerlockchange",
53     "visibilitychange", "touchstart", "touchend", "touchmove", "touchcancel", "gamepadconnected", "gamepaddisconnected", "beforeunload",
54     "batterychargingchange", "batterylevelchange", "webglcontextlost", "webglcontextrestored", "mouseenter", "mouseleave", "mouseover", "mouseout", "(invalid)" };
55   ++eventType;
56   if (eventType < 0) eventType = 0;
57   if (eventType >= sizeof(events)/sizeof(events[0])) eventType = sizeof(events)/sizeof(events[0])-1;
58   return events[eventType];
59 }
60
61 static int mouseButtons;
62 static int movementX, movementY;
63
64 static bool isFullScreen;
65
66 static EM_BOOL mouse_callback(int eventType, const EmscriptenMouseEvent *e, void *userData)
67 {
68    Window window = guiApp.desktop;
69    Modifiers mods { };
70    int methodID;
71
72    mods.alt = e->altKey ? true : false;
73    mods.shift = e->shiftKey ? true : false;
74    mods.ctrl = e->ctrlKey ? true : false;
75
76    mods.left = (mouseButtons & 1) ? true : false;
77    mods.right = (mouseButtons & 2) ? true : false;
78    mods.middle = (mouseButtons & 4) ? true : false;
79
80    switch(eventType)
81    {
82       case EMSCRIPTEN_EVENT_MOUSEMOVE:
83          lastMouse = { e->canvasX, e->canvasY };
84          window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove,
85             e->canvasX, e->canvasY, &mods, false, true);
86          movementX += e->movementX;
87          movementY += e->movementY;
88          break;
89       case EMSCRIPTEN_EVENT_MOUSEDOWN:
90          // PrintLn("EMSCRIPTEN_EVENT_MOUSEDOWN!");
91          methodID =
92             e->button == 0 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown :
93             e->button == 2 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown :
94                              __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
95          window.MouseMessage(methodID, e->canvasX, e->canvasY, &mods, false, true);
96          if(e->button == 0)
97             mouseButtons |= 1;
98          else if(e->button == 2)
99             mouseButtons |= 2;
100          else
101             mouseButtons |= 4;
102          break;
103       case EMSCRIPTEN_EVENT_MOUSEUP:
104          methodID =
105             e->button == 0 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp :
106             e->button == 2 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp :
107                              __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
108          window.MouseMessage(methodID, e->canvasX, e->canvasY, &mods, false, true);
109          if(e->button == 0)
110             mouseButtons &= ~1;
111          else if(e->button == 2)
112             mouseButtons &= ~2;
113          else
114             mouseButtons &= ~4;
115          break;
116       case EMSCRIPTEN_EVENT_DBLCLICK:
117          methodID =
118             e->button == 0 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick :
119             e->button == 2 ? __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick :
120                              __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
121          window.MouseMessage(methodID, e->canvasX, e->canvasY, &mods, false, true);
122          break;
123    }
124
125 /*
126    printf("%s, screen: (%ld,%ld), client: (%ld,%ld),%s%s%s%s button: %hu, buttons: %hu, movement: (%ld,%ld), canvas: (%ld,%ld)\n",
127       emscripten_event_type_to_string(eventType), e->screenX, e->screenY, e->clientX, e->clientY,
128       e->ctrlKey ? " CTRL" : "", e->shiftKey ? " SHIFT" : "", e->altKey ? " ALT" : "", e->metaKey ? " META" : "",
129       e->button, e->buttons, e->movementX, e->movementY, e->canvasX, e->canvasY);
130 */
131    return 0;
132 }
133
134 static EM_BOOL wheel_callback(int eventType, const EmscriptenWheelEvent *e, void *userData)
135 {
136    Window window = guiApp.desktop;
137    Key key = (e->deltaY < 0 || e->deltaX < 0) ? wheelUp : wheelDown;
138
139    key.alt = e->mouse.altKey ? true : false;
140    key.shift = e->mouse.shiftKey ? true : false;
141    key.ctrl = e->mouse.ctrlKey ? true : false;
142
143    /*
144    printf("%s, screen: (%ld,%ld), client: (%ld,%ld),%s%s%s%s button: %hu, buttons: %hu, canvas: (%ld,%ld), delta:(%g,%g,%g), deltaMode:%lu\n",
145     emscripten_event_type_to_string(eventType), e->mouse.screenX, e->mouse.screenY, e->mouse.clientX, e->mouse.clientY,
146     e->mouse.ctrlKey ? " CTRL" : "", e->mouse.shiftKey ? " SHIFT" : "", e->mouse.altKey ? " ALT" : "", e->mouse.metaKey ? " META" : "",
147     e->mouse.button, e->mouse.buttons, e->mouse.canvasX, e->mouse.canvasY,
148     (float)e->deltaX, (float)e->deltaY, (float)e->deltaZ, e->deltaMode);
149    */
150
151    window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, key, 0);
152
153   return 0;
154 }
155 static bool keyStatus[KeyCode];
156
157 EM_BOOL pointerlockchange_callback(int eventType, const EmscriptenPointerlockChangeEvent *e, void *userData)
158 {
159    if(!e->isActive)
160    {
161       if(guiApp.acquiredWindow)
162       {
163          guiApp.acquiredWindow.acquiredInput = false;
164          guiApp.acquiredWindow = null;
165       }
166    }
167    else
168    {
169       Window w = guiApp.desktop;
170       if(w && w.children.first) w = w.children.first;
171       guiApp.acquiredWindow = w;
172       guiApp.acquiredWindow.acquiredInput = true;
173    }
174 /*
175   printf("%s, isActive: %d, pointerlock element nodeName: \"%s\", id: \"%s\"\n",
176     emscripten_event_type_to_string(eventType), e->isActive, e->nodeName, e->id);
177 */
178    movementX = 0;
179    movementY = 0;
180    return 0;
181 }
182
183 EM_BOOL fullscreenchange_callback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData)
184 {
185    int w = 0, h = 0;
186    double dw = 0, dh = 0;
187    isFullScreen = (bool)e->isFullscreen;
188    *&guiApp.fullScreen = isFullScreen;
189
190    emscripten_get_element_css_size(0, &dw, &dh);
191    w = (int)dw, h = (int)dh;
192    if(w && h)
193    {
194       emscripten_set_canvas_size(w, h);
195       guiApp.desktop.ExternalPosition(0,0, w, h);
196       if(guiApp.desktop.display && guiApp.desktop.display.displaySystem)
197          guiApp.desktop.display.Resize(w, h);
198    }
199    movementX = 0;
200    movementY = 0;
201    return 0;
202 }
203
204 // The event handler functions can return 1 to suppress the event and disable the default action. That calls event.preventDefault();
205 // Returning 0 signals that the event was not consumed by the code, and will allow the event to pass on and bubble up normally.
206 EM_BOOL key_callback(int eventType, const EmscriptenKeyboardEvent *e, void *userData)
207 {
208    Window window = guiApp.desktop;
209    Key key = 0;
210    switch(e->keyCode)
211    {
212       case 8: key = backSpace; break;
213       case 9: key = tab; break;
214       case 13: key = enter; break;
215       case 16: key = shift; break;
216       case 17: key = control; break;
217       case 18: key = alt; break;
218       case 19: key = pause; break;
219       case 20: key = capsLock; break;
220       case 27: key = escape; break;
221       case 32: key = space; break;
222       case 33: key = pageUp; break;
223       case 34: key = pageDown; break;
224       case 35: key = end; break;
225       case 36: key = home; break;
226       case 37: key = left; break;
227       case 38: key = up; break;
228       case 39: key = right; break;
229       case 40: key = down; break;
230       case 44: key = printScreen; break;
231       case 45: key = insert; break;
232       case 46: key = del; break;
233       case 48: key = k0; break;
234       case 49: key = k1; break;
235       case 50: key = k2; break;
236       case 51: key = k3; break;
237       case 52: key = k4; break;
238       case 53: key = k5; break;
239       case 54: key = k6; break;
240       case 55: key = k7; break;
241       case 56: key = k8; break;
242       case 57: key = k9; break;
243       case 65: key = a; break;
244       case 66: key = b; break;
245       case 67: key = c; break;
246       case 68: key = d; break;
247       case 69: key = KeyCode::e; break;
248       case 70: key = f; break;
249       case 71: key = g; break;
250       case 72: key = h; break;
251       case 73: key = i; break;
252       case 74: key = j; break;
253       case 75: key = k; break;
254       case 76: key = l; break;
255       case 77: key = m; break;
256       case 78: key = n; break;
257       case 79: key = o; break;
258       case 80: key = p; break;
259       case 81: key = q; break;
260       case 82: key = r; break;
261       case 83: key = s; break;
262       case 84: key = t; break;
263       case 85: key = u; break;
264       case 86: key = v; break;
265       case 87: key = w; break;
266       case 88: key = x; break;
267       case 89: key = y; break;
268       case 90: key = z; break;
269       // case 91: key = start; break;
270       // case 93: key = context; break;
271       case 112: key = f1; break;
272       case 113: key = f2; break;
273       case 114: key = f3; break;
274       case 115: key = f4; break;
275       case 116: key = f5; break;
276       case 117: key = f6; break;
277       case 118: key = f7; break;
278       case 119: key = f8; break;
279       case 120: key = f9; break;
280       case 121: key = f10; break;
281       case 122: key = f11; break;
282       case 123: key = f12; break;
283       case 144: key = numLock; break;
284       case 125: key = scrollLock; break;
285       case 188: key = comma; break;
286       case 190: key = period; break;
287       case 191: key = slash; break;
288       case 192: key = tilde; break;
289       case 219: key = leftBracket; break;    // also corresponds to the Win Key (Start) in older versions of Opera.
290       case 220: key = backSlash; break;
291       case 221: key = rightBracket; break;
292       case 222: key = quote; break;
293
294       /*case 173: */case 181: key = mute; break;       // FF: 181
295       case 174: case 182: key = volumeDown; break;     // FF: 182
296       case 175: case 183: key = volumeDown; break;     // FF: 183
297       case 186: case 59:  key = semicolon; break;      // FF: 59
298       case 187: case 61:  key = equal; break;          // FF: 61
299       case 189: case 173: key = minus; break;          // FF: 61
300
301       case 96: key = keyPad0; break;
302       //case 45: key = keyPadInsert; break;
303
304       case 97: key = keyPad1; break;
305       //case 35: key = keyPadEnd; break;
306
307       case 98: key = keyPad2; break;
308       //case 40: key = keyPadDown; break;
309
310       case 99: key = keyPad3; break;
311       //case 34: key = keyPadPageDown; break;
312
313       case 100: key = keyPad4; break;
314       //case 37: key = keyPadLeft; break;
315
316       case 101: key = keyPad5; break;
317       case 12: key = keyPad5; break;
318
319       case 102: key = keyPad6; break;
320       //case 39: key = keyPadRight; break;
321
322       case 103: key = keyPad7; break;
323       //case 36: key = keyPadHome; break;
324
325       case 104: key = keyPad8; break;
326       //case 38: key = keyPadUp; break;
327
328       case 105: key = keyPad9; break;
329       //case 33: key = keyPadPageUp; break;
330
331       case 106: key = keyPadStar; break;
332       case 107: key = keyPadPlus; break;
333       case 109: key = keyPadMinus; break;
334
335       case 110: key = keyPadDelete; break;
336       //case 46: key = keyPadDelete; break;
337
338       case 11: key = keyPadSlash; break;
339    }
340
341    key.alt = e->altKey ? true : false;
342    key.shift = e->shiftKey ? true : false;
343    key.ctrl = e->ctrlKey ? true : false;
344
345    /*
346    key.modifiers.left = (mouseButtons & 1) ? true : false;
347    key.modifiers.right = (mouseButtons & 2) ? true : false;
348    key.modifiers.middle = (mouseButtons & 4) ? true : false;
349    */
350
351
352 /*
353      printf("%s, key: \"%s\", code: \"%s\", location: %lu,%s%s%s%s repeat: %d, locale: \"%s\", char: \"%s\", charCode: %lu, keyCode: %lu, which: %lu\n",
354        emscripten_event_type_to_string(eventType), e->key, e->code, e->location,
355        e->ctrlKey ? " CTRL" : "", e->shiftKey ? " SHIFT" : "", e->altKey ? " ALT" : "", e->metaKey ? " META" : "",
356        e->repeat, e->locale, e->charValue, e->charCode, e->keyCode, e->which);
357 */
358    if(key)
359    {
360       switch(eventType)
361       {
362          case EMSCRIPTEN_EVENT_KEYDOWN:
363             //PrintLn("Setting ", key, " to down");
364             keyStatus[key] = true;
365             window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, key, (unichar)e->charCode);
366             break;
367          case EMSCRIPTEN_EVENT_KEYUP:
368             //PrintLn("Setting ", key, " to false");
369             keyStatus[key] = false;
370             window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, key, (unichar)e->charCode);
371             break;
372       }
373    }
374
375   /*
376   if (eventType == EMSCRIPTEN_EVENT_KEYPRESS && (!strcmp(e->key, "f") || e->which == 102)) {
377     EmscriptenFullscreenChangeEvent fsce;
378     EMSCRIPTEN_RESULT ret = emscripten_get_fullscreen_status(&fsce);
379     TEST_RESULT(emscripten_get_fullscreen_status);
380     if (!fsce.isFullscreen) {
381       printf("Requesting fullscreen..\n");
382       ret = emscripten_request_fullscreen(0, 1);
383       TEST_RESULT(emscripten_request_fullscreen);
384     } else {
385       printf("Exiting fullscreen..\n");
386       ret = emscripten_exit_fullscreen();
387       TEST_RESULT(emscripten_exit_fullscreen);
388       ret = emscripten_get_fullscreen_status(&fsce);
389       TEST_RESULT(emscripten_get_fullscreen_status);
390       if (fsce.isFullscreen) {
391         fprintf(stderr, "Fullscreen exit did not work!\n");
392       }
393     }
394   }
395
396   if (eventType == EMSCRIPTEN_EVENT_KEYPRESS && (!strcmp(e->key, "p") || e->which == 112)) {
397     EmscriptenPointerlockChangeEvent plce;
398     EMSCRIPTEN_RESULT ret = emscripten_get_pointerlock_status(&plce);
399     TEST_RESULT(emscripten_get_pointerlock_status);
400     if (!plce.isActive) {
401       printf("Requesting pointer lock..\n");
402       ret = emscripten_request_pointerlock(0, 1);
403       TEST_RESULT(emscripten_request_pointerlock);
404     } else {
405       printf("Exiting pointer lock..\n");
406       ret = emscripten_exit_pointerlock();
407       TEST_RESULT(emscripten_exit_pointerlock);
408       ret = emscripten_get_pointerlock_status(&plce);
409       TEST_RESULT(emscripten_get_pointerlock_status);
410       if (plce.isActive) {
411         fprintf(stderr, "Pointer lock exit did not work!\n");
412       }
413     }
414   }
415   */
416
417   return 0;
418 }
419
420 static EM_BOOL uievent_callback(int eventType, const EmscriptenUiEvent *e, void *userData)
421 {
422    switch(eventType)
423    {
424       case EMSCRIPTEN_EVENT_RESIZE:
425       //case EMSCRIPTEN_EVENT_SCROLL:
426       {
427          int w = 0, h = 0;
428          double dw = 0, dh = 0;
429          emscripten_get_element_css_size(0, &dw, &dh);
430          w = (int)dw, h = (int)dh;
431          if(w && h)
432          {
433             emscripten_set_canvas_size(w, h);
434             guiApp.desktop.ExternalPosition(0,0, w, h);
435             if(guiApp.desktop.display && guiApp.desktop.display.displaySystem)
436                guiApp.desktop.display.Resize(w, h);
437          }
438          //PrintLn("EMSCRIPTEN_EVENT_RESIZE: ", w, " x ", h);
439          break;
440       }
441    }
442    /*
443    printf("%s, detail: %ld, document.body.client size: (%d,%d), window.inner size: (%d,%d), scrollPos: (%d, %d)\n",
444       emscripten_event_type_to_string(eventType), e->detail, e->documentBodyClientWidth, e->documentBodyClientHeight,
445       e->windowInnerWidth, e->windowInnerHeight, e->scrollTop, e->scrollLeft);
446    */
447    return 0;
448 }
449
450 class EmscriptenInterface : Interface
451 {
452    class_property(name) = "Emscripten";
453
454    // --- User Interface System ---
455
456    bool ::Initialize()
457    {
458       emscripten_set_resize_callback(0, 0, 1, uievent_callback);
459       //emscripten_set_scroll_callback(0, 0, 1, uievent_callback);
460       emscripten_set_click_callback(0, 0, 1, mouse_callback);
461       emscripten_set_mousedown_callback(0, 0, 1, mouse_callback);
462       emscripten_set_mouseup_callback(0, 0, 1, mouse_callback);
463       emscripten_set_dblclick_callback(0, 0, 1, mouse_callback);
464       emscripten_set_mousemove_callback(0, 0, 1, mouse_callback);
465       emscripten_set_wheel_callback(0, 0, 1, wheel_callback);
466       emscripten_set_keypress_callback(0, 0, 1, key_callback);
467       emscripten_set_keydown_callback(0, 0, 1, key_callback);
468       emscripten_set_keyup_callback(0, 0, 1, key_callback);
469       emscripten_set_pointerlockchange_callback(0, 0, 1, pointerlockchange_callback);
470       emscripten_set_fullscreenchange_callback(0, 0, 1, fullscreenchange_callback);
471       /*emscripten_set_mouseenter_callback(0, 0, 1, mouse_callback);
472       emscripten_set_mouseleave_callback(0, 0, 1, mouse_callback);*/
473       return true;
474    }
475
476    void ::Terminate()
477    {
478
479    }
480
481    bool ::ProcessInput(bool processAll)
482    {
483
484       return false;
485    }
486
487    void ::Wait()
488    {
489
490    }
491
492    void ::Lock(Window window)
493    {
494
495    }
496
497    void ::Unlock(Window window)
498    {
499
500    }
501
502    void ::SetTimerResolution(uint hertz)
503    {
504
505    }
506
507    const char ** ::GraphicsDrivers(int * numDrivers)
508    {
509       static const char *graphicsDrivers[] = { "OpenGL" };
510       *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
511       return (const char **)graphicsDrivers;
512       return null;
513    }
514
515    void ::EnsureFullScreen(bool * fullScreen)
516    {
517
518    }
519
520    void ::GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate)
521    {
522       *fullScreen = isFullScreen;
523    }
524
525    bool ::ScreenMode(bool fullScreen, Resolution resolution, PixelFormat colorDepth, int refreshRate, bool * textMode)
526    {
527       if(fullScreen)
528          emscripten_request_fullscreen(0, 1);
529       else
530          emscripten_exit_fullscreen();
531       return true;
532    }
533
534
535    // --- Window Creation ---
536
537    void * ::CreateRootWindow(Window window)
538    {
539
540       return (void *)(uintptr)1;
541    }
542
543    void ::DestroyRootWindow(Window window)
544    {
545
546    }
547
548
549    // --- Window manipulation ---
550
551    void ::SetRootWindowCaption(Window window, const char * name)
552    {
553
554    }
555
556    void ::PositionRootWindow(Window window, int x, int y, int w, int h, bool move, bool resize)
557    {
558
559    }
560
561    void ::OffsetWindow(Window window, int * x, int * y)
562    {
563
564    }
565
566    void ::UpdateRootWindow(Window window)
567    {
568
569    }
570
571    void ::SetRootWindowState(Window window, WindowState state, bool visible)
572    {
573
574    }
575
576    void ::ActivateRootWindow(Window window)
577    {
578
579    }
580
581    void ::OrderRootWindow(Window window, bool topMost)
582    {
583
584    }
585
586    void ::SetRootWindowColor(Window window)
587    {
588
589    }
590
591    void ::FlashRootWindow(Window window)
592    {
593
594    }
595
596
597    // --- Mouse-based window movement ---
598
599    void ::StartMoving(Window window, int x, int y, bool fromKeyBoard)
600    {
601
602    }
603
604    void ::StopMoving(Window window)
605    {
606
607    }
608
609
610    // --- Mouse manipulation ---
611
612    void ::GetMousePosition(int *x, int *y)
613    {
614       *x = lastMouse.x;
615       *y = lastMouse.y;
616    }
617
618    void ::SetMousePosition(int x, int y)
619    {
620
621    }
622
623    void ::SetMouseRange(Window window, Box box)
624    {
625
626    }
627
628    void ::SetMouseCapture(Window window)
629    {
630
631    }
632
633
634    // --- Mouse cursor ---
635
636    void ::SetMouseCursor(Window window, SystemCursor cursor)
637    {
638
639    }
640
641
642    // --- Caret manipulation ---
643
644    void ::SetCaret(int caretX, int caretY, int size)
645    {
646
647    }
648
649
650    // --- Clipboard manipulation ---
651
652    void ::ClearClipboard()
653    {
654
655    }
656
657    bool ::AllocateClipboard(ClipBoard clipBoard, uint size)
658    {
659
660       return false;
661    }
662
663    bool ::SaveClipboard(ClipBoard clipBoard)
664    {
665
666       return false;
667    }
668
669    bool ::LoadClipboard(ClipBoard clipBoard)
670    {
671
672       return false;
673    }
674
675    void ::UnloadClipboard(ClipBoard clipBoard)
676    {
677
678    }
679
680
681    // --- State based input ---
682
683    bool ::AcquireInput(Window window, bool state)
684    {
685       if(state)
686          emscripten_request_pointerlock(0, 1);
687       else
688          emscripten_exit_pointerlock();
689
690       movementX = 0;
691       movementY = 0;
692       return true;
693    }
694
695    bool ::GetMouseState(MouseButtons * buttons, int * x, int * y)
696    {
697       if(buttons) *buttons = { left = mouseButtons & 1, right = (mouseButtons & 2) ? true : false, middle = (mouseButtons & 4) ? true : false };
698       if(x) { *x = movementX; movementX = 0; }
699       if(y) { *y = movementY; movementY = 0; }
700
701       return true;
702    }
703
704    bool ::GetJoystickState(int device, Joystick joystick)
705    {
706
707       return false;
708    }
709
710    bool ::GetKeyState(Key key)
711    {
712       return keyStatus[key];
713    }
714
715    bool ::SetIcon(Window window, BitmapResource icon)
716    {
717
718       return false;
719    }
720
721    void ::GetScreenArea(Window window, Box box)
722    {
723    }
724 }
725
726 #endif