1+ #include < emscripten.h>
12#include " system/display.h"
3+ #include " system/keyboard.h"
4+ #include " system/mouse.h"
25#include " system/ui/gui.h"
36
47#include " sysjs.h"
58
9+ static void (*gProcessCudaEvents )();
10+
611void sys_gui_init () {}
712
813bool sys_gui_open_file_dialog (String &ret, const String &title, const String &filespec, const String &filespecname, const String &home, bool existing) {
@@ -15,24 +20,141 @@ int sys_gui_messagebox(const String &title, const String &text, int buttons) {
1520 return 0 ; // Placeholder return value
1621}
1722
23+ // doProcessCudaEvent actually expects each mouse event to have the full state
24+ // (position and buttons), so keep track of what we sent to when we get updates.
25+ static SystemEvent gLastMouseEvent ;
26+
27+ static void sys_gui_poll_events () {
28+ int lock = EM_ASM_INT_V ({ return workerApi.acquireInputLock (); });
29+ if (!lock) {
30+ return ;
31+ }
32+
33+ int mouseButtonState = EM_ASM_INT_V ({
34+ return workerApi.getInputValue (workerApi.InputBufferAddresses .mouseButtonStateAddr );
35+ });
36+ int mouseButton2State = EM_ASM_INT_V ({
37+ return workerApi.getInputValue (workerApi.InputBufferAddresses .mouseButton2StateAddr );
38+ });
39+ if (mouseButtonState > -1 || mouseButton2State > -1 ) {
40+ SystemEvent ev;
41+ ev.type = sysevMouse;
42+ ev.mouse .type = mouseButtonState == 1 || mouseButton2State == 1 ? sme_buttonPressed : sme_buttonReleased;
43+
44+ if (mouseButtonState != -1 ) {
45+ ev.mouse .button1 = mouseButtonState == 1 ;
46+ gLastMouseEvent .mouse .button1 = ev.mouse .button1 ;
47+ } else {
48+ ev.mouse .button1 = gLastMouseEvent .mouse .button1 ;
49+ }
50+ if (mouseButton2State != -1 ) {
51+ ev.mouse .button2 = mouseButton2State == 1 ;
52+ gLastMouseEvent .mouse .button2 = ev.mouse .button2 ;
53+ } else {
54+ ev.mouse .button2 = gLastMouseEvent .mouse .button2 ;
55+ }
56+ ev.mouse .button3 = false ;
57+
58+ // Make sure we don't generate position updates
59+ ev.mouse .x = gLastMouseEvent .mouse .x ;
60+ ev.mouse .y = gLastMouseEvent .mouse .y ;
61+ ev.mouse .relx = 0 ;
62+ ev.mouse .rely = 0 ;
63+ gMouse ->handleEvent (ev);
64+ }
65+
66+ int hasMousePosition = EM_ASM_INT_V ({
67+ return workerApi.getInputValue (workerApi.InputBufferAddresses .mousePositionFlagAddr );
68+ });
69+ if (hasMousePosition) {
70+ SystemEvent ev;
71+ ev.type = sysevMouse;
72+ ev.mouse .type = sme_motionNotify;
73+ ev.mouse .relx = EM_ASM_INT_V ({
74+ return workerApi.getInputValue (workerApi.InputBufferAddresses .mouseDeltaXAddr );
75+ });
76+ ev.mouse .rely = EM_ASM_INT_V ({
77+ return workerApi.getInputValue (workerApi.InputBufferAddresses .mouseDeltaYAddr );
78+ });
79+ ev.mouse .x = EM_ASM_INT_V ({
80+ return workerApi.getInputValue (workerApi.InputBufferAddresses .mousePositionXAddr );
81+ });
82+ ev.mouse .y = EM_ASM_INT_V ({
83+ return workerApi.getInputValue (workerApi.InputBufferAddresses .mousePositionYAddr );
84+ });
85+
86+ // Make sure we don't generate mouse button updates
87+ ev.mouse .button1 = gLastMouseEvent .mouse .button1 ;
88+ ev.mouse .button2 = gLastMouseEvent .mouse .button2 ;
89+ ev.mouse .button3 = false ;
90+
91+ gMouse ->handleEvent (ev);
92+
93+ gLastMouseEvent .mouse .x = ev.mouse .x ;
94+ gLastMouseEvent .mouse .y = ev.mouse .y ;
95+ }
96+
97+ int hasKeyEvent = EM_ASM_INT_V ({
98+ return workerApi.getInputValue (workerApi.InputBufferAddresses .keyEventFlagAddr );
99+ });
100+ if (hasKeyEvent) {
101+ int keyCode = EM_ASM_INT_V ({
102+ return workerApi.getInputValue (workerApi.InputBufferAddresses .keyCodeAddr );
103+ });
104+
105+ int keyState = EM_ASM_INT_V ({
106+ return workerApi.getInputValue (workerApi.InputBufferAddresses .keyStateAddr );
107+ });
108+
109+ SystemEvent ev;
110+ ev.type = sysevKey;
111+ ev.key .keycode = keyCode;
112+ ev.key .pressed = keyState != 0 ;
113+ gKeyboard ->handleEvent (ev);
114+ }
115+
116+ EM_ASM ({ workerApi.releaseInputLock (); });
117+
118+ // Ensure that period tasks are run (until we have idlewait support).
119+ EM_ASM ({ workerApi.sleep (0 ); });
120+
121+ if (gProcessCudaEvents != nullptr ) {
122+ gProcessCudaEvents ();
123+ }
124+ }
125+
18126void sys_gui_event () {
127+ sys_gui_poll_events ();
19128 static_cast <JSSystemDisplay*>(gDisplay )->blit ();
20129}
21130
22131void sys_gui_cpu_ops_hook (uint ops) {
23- // We get invoked every 0x3ffff (256K ops), but for now blit every
132+ sys_gui_poll_events ();
133+
134+ // We get invoked every 0x3ffff (256K ops), but for now blit every
24135 // 0x7ffff (512K) ops which is roughly 60 Hz on my machine.
25136 // TODO: use realtime click to actually try to hit 60fps.
26137 if ((ops & 0x7ffff ) == 0 ) {
27138 static_cast <JSSystemDisplay*>(gDisplay )->blit ();
28139 }
29140}
30141
142+ void sys_gui_cuda_hook (SystemEventHandler cudaEventHandler, void (*processCudaEvents)()) {
143+ gKeyboard ->attachEventHandler (cudaEventHandler);
144+ gMouse ->attachEventHandler (cudaEventHandler);
145+ gProcessCudaEvents = processCudaEvents;
146+ }
147+
31148void initUI (const char *title, const DisplayCharacteristics &aCharacteristics, int redraw_ms, const KeyboardCharacteristics &keyCharacteristics, bool fullscreen) {
32- gDisplay = allocSystemDisplay (title, aCharacteristics, redraw_ms);
33- // gMouse = allocSystemMouse();
34- // gKeyboard = allocSystemKeyboard();
149+ gDisplay = allocSystemDisplay (title, aCharacteristics, redraw_ms);
150+ gMouse = allocSystemMouse ();
151+ gLastMouseEvent .mouse .button1 = false ;
152+ gLastMouseEvent .mouse .button2 = false ;
153+ gLastMouseEvent .mouse .button3 = false ;
154+ gLastMouseEvent .mouse .x = 0 ;
155+ gLastMouseEvent .mouse .y = 0 ;
35156
157+ gKeyboard = allocSystemKeyboard ();
36158}
37159
38160void doneUI () {
0 commit comments