Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/lib/libglut.js
4150 views
1
/**
2
* @license
3
* Copyright 2012 The Emscripten Authors
4
* SPDX-License-Identifier: MIT
5
*/
6
7
var LibraryGLUT = {
8
$GLUT__deps: ['$Browser', '$getFullscreenElement', 'glutPostRedisplay'],
9
$GLUT: {
10
initTime: null,
11
idleFunc: null,
12
displayFunc: null,
13
keyboardFunc: null,
14
keyboardUpFunc: null,
15
specialFunc: null,
16
specialUpFunc: null,
17
reshapeFunc: null,
18
motionFunc: null,
19
passiveMotionFunc: null,
20
mouseFunc: null,
21
buttons: 0,
22
modifiers: 0,
23
initWindowWidth: 256,
24
initWindowHeight: 256,
25
initDisplayMode: 0x0000 /*GLUT_RGBA*/ | 0x0002 /*GLUT_DOUBLE*/ | 0x0010 /*GLUT_DEPTH*/,
26
// Set when going fullscreen
27
windowX: 0,
28
windowY: 0,
29
windowWidth: 0,
30
windowHeight: 0,
31
requestedAnimationFrame: false,
32
33
saveModifiers: (event) => {
34
GLUT.modifiers = 0;
35
if (event['shiftKey'])
36
GLUT.modifiers += 1; /* GLUT_ACTIVE_SHIFT */
37
if (event['ctrlKey'])
38
GLUT.modifiers += 2; /* GLUT_ACTIVE_CTRL */
39
if (event['altKey'])
40
GLUT.modifiers += 4; /* GLUT_ACTIVE_ALT */
41
},
42
43
onMousemove: (event) => {
44
/* Send motion event only if the motion changed, prevents
45
* spamming our app with uncessary callback call. It does happen in
46
* Chrome on Windows.
47
*/
48
var lastX = Browser.mouseX;
49
var lastY = Browser.mouseY;
50
Browser.calculateMouseEvent(event);
51
var newX = Browser.mouseX;
52
var newY = Browser.mouseY;
53
if (newX == lastX && newY == lastY) return;
54
55
if (GLUT.buttons == 0 && event.target == Browser.getCanvas() && GLUT.passiveMotionFunc) {
56
event.preventDefault();
57
GLUT.saveModifiers(event);
58
{{{ makeDynCall('vii', 'GLUT.passiveMotionFunc') }}}(lastX, lastY);
59
} else if (GLUT.buttons != 0 && GLUT.motionFunc) {
60
event.preventDefault();
61
GLUT.saveModifiers(event);
62
{{{ makeDynCall('vii', 'GLUT.motionFunc') }}}(lastX, lastY);
63
}
64
},
65
66
getSpecialKey: (keycode) => {
67
var key = null;
68
switch (keycode) {
69
case 8: key = 120 /* backspace */; break;
70
case 46: key = 111 /* delete */; break;
71
72
case 0x70 /*DOM_VK_F1*/: key = 1 /* GLUT_KEY_F1 */; break;
73
case 0x71 /*DOM_VK_F2*/: key = 2 /* GLUT_KEY_F2 */; break;
74
case 0x72 /*DOM_VK_F3*/: key = 3 /* GLUT_KEY_F3 */; break;
75
case 0x73 /*DOM_VK_F4*/: key = 4 /* GLUT_KEY_F4 */; break;
76
case 0x74 /*DOM_VK_F5*/: key = 5 /* GLUT_KEY_F5 */; break;
77
case 0x75 /*DOM_VK_F6*/: key = 6 /* GLUT_KEY_F6 */; break;
78
case 0x76 /*DOM_VK_F7*/: key = 7 /* GLUT_KEY_F7 */; break;
79
case 0x77 /*DOM_VK_F8*/: key = 8 /* GLUT_KEY_F8 */; break;
80
case 0x78 /*DOM_VK_F9*/: key = 9 /* GLUT_KEY_F9 */; break;
81
case 0x79 /*DOM_VK_F10*/: key = 10 /* GLUT_KEY_F10 */; break;
82
case 0x7a /*DOM_VK_F11*/: key = 11 /* GLUT_KEY_F11 */; break;
83
case 0x7b /*DOM_VK_F12*/: key = 12 /* GLUT_KEY_F12 */; break;
84
case 0x25 /*DOM_VK_LEFT*/: key = 100 /* GLUT_KEY_LEFT */; break;
85
case 0x26 /*DOM_VK_UP*/: key = 101 /* GLUT_KEY_UP */; break;
86
case 0x27 /*DOM_VK_RIGHT*/: key = 102 /* GLUT_KEY_RIGHT */; break;
87
case 0x28 /*DOM_VK_DOWN*/: key = 103 /* GLUT_KEY_DOWN */; break;
88
case 0x21 /*DOM_VK_PAGE_UP*/: key = 104 /* GLUT_KEY_PAGE_UP */; break;
89
case 0x22 /*DOM_VK_PAGE_DOWN*/: key = 105 /* GLUT_KEY_PAGE_DOWN */; break;
90
case 0x24 /*DOM_VK_HOME*/: key = 106 /* GLUT_KEY_HOME */; break;
91
case 0x23 /*DOM_VK_END*/: key = 107 /* GLUT_KEY_END */; break;
92
case 0x2d /*DOM_VK_INSERT*/: key = 108 /* GLUT_KEY_INSERT */; break;
93
94
case 16 /*DOM_VK_SHIFT*/:
95
case 0x05 /*DOM_VK_LEFT_SHIFT*/:
96
key = 112 /* GLUT_KEY_SHIFT_L */;
97
break;
98
case 0x06 /*DOM_VK_RIGHT_SHIFT*/:
99
key = 113 /* GLUT_KEY_SHIFT_R */;
100
break;
101
102
case 17 /*DOM_VK_CONTROL*/:
103
case 0x03 /*DOM_VK_LEFT_CONTROL*/:
104
key = 114 /* GLUT_KEY_CONTROL_L */;
105
break;
106
case 0x04 /*DOM_VK_RIGHT_CONTROL*/:
107
key = 115 /* GLUT_KEY_CONTROL_R */;
108
break;
109
110
case 18 /*DOM_VK_ALT*/:
111
case 0x02 /*DOM_VK_LEFT_ALT*/:
112
key = 116 /* GLUT_KEY_ALT_L */;
113
break;
114
case 0x01 /*DOM_VK_RIGHT_ALT*/:
115
key = 117 /* GLUT_KEY_ALT_R */;
116
break;
117
};
118
return key;
119
},
120
121
getASCIIKey: (event) => {
122
if (event['ctrlKey'] || event['altKey'] || event['metaKey']) return null;
123
124
var keycode = event['keyCode'];
125
126
/* The exact list is soooo hard to find in a canonical place! */
127
128
if (48 <= keycode && keycode <= 57)
129
return keycode; // numeric TODO handle shift?
130
if (65 <= keycode && keycode <= 90)
131
return event['shiftKey'] ? keycode : keycode + 32;
132
if (96 <= keycode && keycode <= 105)
133
return keycode - 48; // numpad numbers
134
if (106 <= keycode && keycode <= 111)
135
return keycode - 106 + 42; // *,+-./ TODO handle shift?
136
137
switch (keycode) {
138
case 9: // tab key
139
case 13: // return key
140
case 27: // escape
141
case 32: // space
142
case 61: // equal
143
return keycode;
144
}
145
146
var s = event['shiftKey'];
147
switch (keycode) {
148
case 186: return s ? 58 : 59; // colon / semi-colon
149
case 187: return s ? 43 : 61; // add / equal (these two may be wrong)
150
case 188: return s ? 60 : 44; // less-than / comma
151
case 189: return s ? 95 : 45; // dash
152
case 190: return s ? 62 : 46; // greater-than / period
153
case 191: return s ? 63 : 47; // forward slash
154
case 219: return s ? 123 : 91; // open bracket
155
case 220: return s ? 124 : 47; // back slash
156
case 221: return s ? 125 : 93; // close bracket
157
case 222: return s ? 34 : 39; // single quote
158
}
159
160
return null;
161
},
162
163
onKeydown: (event) => {
164
if (GLUT.specialFunc || GLUT.keyboardFunc) {
165
var key = GLUT.getSpecialKey(event['keyCode']);
166
if (key !== null) {
167
if (GLUT.specialFunc) {
168
event.preventDefault();
169
GLUT.saveModifiers(event);
170
{{{ makeDynCall('viii', 'GLUT.specialFunc') }}}(key, Browser.mouseX, Browser.mouseY);
171
}
172
} else {
173
key = GLUT.getASCIIKey(event);
174
if (key !== null && GLUT.keyboardFunc) {
175
event.preventDefault();
176
GLUT.saveModifiers(event);
177
{{{ makeDynCall('viii', 'GLUT.keyboardFunc') }}}(key, Browser.mouseX, Browser.mouseY);
178
}
179
}
180
}
181
},
182
183
onKeyup: (event) => {
184
if (GLUT.specialUpFunc || GLUT.keyboardUpFunc) {
185
var key = GLUT.getSpecialKey(event['keyCode']);
186
if (key !== null) {
187
if (GLUT.specialUpFunc) {
188
event.preventDefault ();
189
GLUT.saveModifiers(event);
190
{{{ makeDynCall('viii', 'GLUT.specialUpFunc') }}}(key, Browser.mouseX, Browser.mouseY);
191
}
192
} else {
193
key = GLUT.getASCIIKey(event);
194
if (key !== null && GLUT.keyboardUpFunc) {
195
event.preventDefault ();
196
GLUT.saveModifiers(event);
197
{{{ makeDynCall('viii', 'GLUT.keyboardUpFunc') }}}(key, Browser.mouseX, Browser.mouseY);
198
}
199
}
200
}
201
},
202
203
touchHandler: (event) => {
204
if (event.target != Browser.getCanvas()) {
205
return;
206
}
207
208
var touches = event.changedTouches,
209
main = touches[0],
210
type = "";
211
212
switch (event.type) {
213
case "touchstart": type = "mousedown"; break;
214
case "touchmove": type = "mousemove"; break;
215
case "touchend": type = "mouseup"; break;
216
default: return;
217
}
218
219
var simulatedEvent = document.createEvent("MouseEvent");
220
simulatedEvent.initMouseEvent(type, true, true, window, 1,
221
main.screenX, main.screenY,
222
main.clientX, main.clientY, false,
223
false, false, false, 0/*main*/, null);
224
225
main.target.dispatchEvent(simulatedEvent);
226
event.preventDefault();
227
},
228
229
onMouseButtonDown: (event) => {
230
Browser.calculateMouseEvent(event);
231
232
GLUT.buttons |= (1 << event['button']);
233
234
if (event.target == Browser.getCanvas() && GLUT.mouseFunc) {
235
try {
236
event.target.setCapture();
237
} catch (e) {}
238
event.preventDefault();
239
GLUT.saveModifiers(event);
240
{{{ makeDynCall('viiii', 'GLUT.mouseFunc') }}}(event['button'], 0/*GLUT_DOWN*/, Browser.mouseX, Browser.mouseY);
241
}
242
},
243
244
onMouseButtonUp: (event) => {
245
Browser.calculateMouseEvent(event);
246
247
GLUT.buttons &= ~(1 << event['button']);
248
249
if (GLUT.mouseFunc) {
250
event.preventDefault();
251
GLUT.saveModifiers(event);
252
{{{ makeDynCall('viiii', 'GLUT.mouseFunc') }}}(event['button'], 1/*GLUT_UP*/, Browser.mouseX, Browser.mouseY);
253
}
254
},
255
256
onMouseWheel: (event) => {
257
Browser.calculateMouseEvent(event);
258
259
// cross-browser wheel delta
260
var e = window.event || event; // old IE support
261
// Note the minus sign that flips browser wheel direction (positive direction scrolls page down) to native wheel direction (positive direction is mouse wheel up)
262
var delta = -Browser.getMouseWheelDelta(event);
263
delta = (delta == 0) ? 0 : (delta > 0 ? Math.max(delta, 1) : Math.min(delta, -1)); // Quantize to integer so that minimum scroll is at least +/- 1.
264
265
var button = 3; // wheel up
266
if (delta < 0) {
267
button = 4; // wheel down
268
}
269
270
if (GLUT.mouseFunc) {
271
event.preventDefault();
272
GLUT.saveModifiers(event);
273
{{{ makeDynCall('viiii', 'GLUT.mouseFunc') }}}(button, 0/*GLUT_DOWN*/, Browser.mouseX, Browser.mouseY);
274
}
275
},
276
277
// TODO add fullscreen API ala:
278
// http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/
279
onFullscreenEventChange: (event) => {
280
var width;
281
var height;
282
if (getFullscreenElement()) {
283
width = screen["width"];
284
height = screen["height"];
285
} else {
286
width = GLUT.windowWidth;
287
height = GLUT.windowHeight;
288
// TODO set position
289
document.removeEventListener('fullscreenchange', GLUT.onFullscreenEventChange, true);
290
document.removeEventListener('mozfullscreenchange', GLUT.onFullscreenEventChange, true);
291
document.removeEventListener('webkitfullscreenchange', GLUT.onFullscreenEventChange, true);
292
}
293
Browser.setCanvasSize(width, height, true); // N.B. GLUT.reshapeFunc is also registered as a canvas resize callback.
294
// Just call it once here.
295
/* Can't call _glutReshapeWindow as that requests cancelling fullscreen. */
296
if (GLUT.reshapeFunc) {
297
// out("GLUT.reshapeFunc (from FS): " + width + ", " + height);
298
{{{ makeDynCall('vii', 'GLUT.reshapeFunc') }}}(width, height);
299
}
300
_glutPostRedisplay();
301
},
302
303
// Resize callback stage 1: update canvas by setCanvasSize, which notifies resizeListeners including GLUT.reshapeFunc
304
onResize: () => {
305
// Update canvas size to clientWidth and clientHeight, which include CSS scaling
306
var canvas = Browser.getCanvas();
307
Browser.setCanvasSize(canvas.clientWidth, canvas.clientHeight, /*noUpdates*/false);
308
}
309
},
310
311
glutGetModifiers__proxy: 'sync',
312
glutGetModifiers: () => GLUT.modifiers,
313
314
glutInit__deps: ['$Browser', '$addOnExit'],
315
glutInit__proxy: 'sync',
316
glutInit: (argcp, argv) => {
317
// Ignore arguments
318
GLUT.initTime = Date.now();
319
320
var isTouchDevice = 'ontouchstart' in document.documentElement;
321
if (isTouchDevice) {
322
// onMouseButtonDown, onMouseButtonUp and onMousemove handlers
323
// depend on Browser.mouseX / Browser.mouseY fields. Those fields
324
// don't get updated by touch events. So register a touchHandler
325
// function that translates the touch events to mouse events.
326
327
// GLUT doesn't support touch, mouse only, so from touch events we
328
// are only looking at single finger touches to emulate left click,
329
// so we can use workaround and convert all touch events in mouse
330
// events. See touchHandler.
331
window.addEventListener('touchmove', GLUT.touchHandler, true);
332
window.addEventListener('touchstart', GLUT.touchHandler, true);
333
window.addEventListener('touchend', GLUT.touchHandler, true);
334
}
335
336
window.addEventListener('keydown', GLUT.onKeydown, true);
337
window.addEventListener('keyup', GLUT.onKeyup, true);
338
window.addEventListener('mousemove', GLUT.onMousemove, true);
339
window.addEventListener('mousedown', GLUT.onMouseButtonDown, true);
340
window.addEventListener('mouseup', GLUT.onMouseButtonUp, true);
341
// IE9, Chrome, Safari, Opera
342
window.addEventListener('mousewheel', GLUT.onMouseWheel, true);
343
// Firefox
344
window.addEventListener('DOMMouseScroll', GLUT.onMouseWheel, true);
345
346
// Resize callback stage 1: update canvas which notifies resizeListeners
347
window.addEventListener('resize', GLUT.onResize, true);
348
349
// Resize callback stage 2: updateResizeListeners notifies reshapeFunc
350
Browser.resizeListeners.push((width, height) => {
351
if (GLUT.reshapeFunc) {
352
{{{ makeDynCall('vii', 'GLUT.reshapeFunc') }}}(width, height);
353
}
354
});
355
356
addOnExit(() => {
357
if (isTouchDevice) {
358
window.removeEventListener('touchmove', GLUT.touchHandler, true);
359
window.removeEventListener('touchstart', GLUT.touchHandler, true);
360
window.removeEventListener('touchend', GLUT.touchHandler, true);
361
}
362
363
window.removeEventListener('keydown', GLUT.onKeydown, true);
364
window.removeEventListener('keyup', GLUT.onKeyup, true);
365
window.removeEventListener('mousemove', GLUT.onMousemove, true);
366
window.removeEventListener('mousedown', GLUT.onMouseButtonDown, true);
367
window.removeEventListener('mouseup', GLUT.onMouseButtonUp, true);
368
// IE9, Chrome, Safari, Opera
369
window.removeEventListener('mousewheel', GLUT.onMouseWheel, true);
370
// Firefox
371
window.removeEventListener('DOMMouseScroll', GLUT.onMouseWheel, true);
372
373
window.removeEventListener('resize', GLUT.onResize, true);
374
375
var canvas = Browser.getCanvas();
376
canvas.width = canvas.height = 1;
377
});
378
},
379
380
glutInitWindowSize__proxy: 'sync',
381
glutInitWindowSize: (width, height) => {
382
Browser.setCanvasSize( GLUT.initWindowWidth = width,
383
GLUT.initWindowHeight = height );
384
},
385
386
glutInitWindowPosition__proxy: 'sync',
387
// Ignore for now
388
glutInitWindowPosition: (x, y) => {},
389
390
glutGet: (type) => {
391
switch (type) {
392
case 100: /* GLUT_WINDOW_X */
393
return 0; /* TODO */
394
case 101: /* GLUT_WINDOW_Y */
395
return 0; /* TODO */
396
case 102: /* GLUT_WINDOW_WIDTH */
397
return Browser.getCanvas().width;
398
case 103: /* GLUT_WINDOW_HEIGHT */
399
return Browser.getCanvas().height;
400
case 200: /* GLUT_SCREEN_WIDTH */
401
return Browser.getCanvas().width;
402
case 201: /* GLUT_SCREEN_HEIGHT */
403
return Browser.getCanvas().height;
404
case 500: /* GLUT_INIT_WINDOW_X */
405
return 0; /* TODO */
406
case 501: /* GLUT_INIT_WINDOW_Y */
407
return 0; /* TODO */
408
case 502: /* GLUT_INIT_WINDOW_WIDTH */
409
return GLUT.initWindowWidth;
410
case 503: /* GLUT_INIT_WINDOW_HEIGHT */
411
return GLUT.initWindowHeight;
412
case 700: /* GLUT_ELAPSED_TIME */
413
var now = Date.now();
414
return now - GLUT.initTime;
415
case 0x0069: /* GLUT_WINDOW_STENCIL_SIZE */
416
return GLctx.getContextAttributes().stencil ? 8 : 0;
417
case 0x006A: /* GLUT_WINDOW_DEPTH_SIZE */
418
return GLctx.getContextAttributes().depth ? 8 : 0;
419
case 0x006E: /* GLUT_WINDOW_ALPHA_SIZE */
420
return GLctx.getContextAttributes().alpha ? 8 : 0;
421
case 0x0078: /* GLUT_WINDOW_NUM_SAMPLES */
422
return GLctx.getContextAttributes().antialias ? 1 : 0;
423
424
default:
425
throw "glutGet(" + type + ") not implemented yet";
426
}
427
},
428
429
glutIdleFunc__proxy: 'sync',
430
glutIdleFunc__deps: ['$safeSetTimeout'],
431
glutIdleFunc: (func) => {
432
function callback() {
433
if (GLUT.idleFunc) {
434
{{{ makeDynCall('v', 'GLUT.idleFunc') }}}();
435
safeSetTimeout(callback, 4); // HTML spec specifies a 4ms minimum delay on the main thread; workers might get more, but we standardize here
436
}
437
}
438
if (!GLUT.idleFunc) {
439
safeSetTimeout(callback, 0);
440
}
441
GLUT.idleFunc = func;
442
},
443
444
glutTimerFunc__proxy: 'sync',
445
glutTimerFunc__deps: ['$safeSetTimeout'],
446
glutTimerFunc: (msec, func, value) =>
447
safeSetTimeout(() => {{{ makeDynCall('vi', 'func') }}}(value), msec),
448
449
glutDisplayFunc__proxy: 'sync',
450
glutDisplayFunc: (func) => {
451
GLUT.displayFunc = func;
452
},
453
454
glutKeyboardFunc__proxy: 'sync',
455
glutKeyboardFunc: (func) => {
456
GLUT.keyboardFunc = func;
457
},
458
459
glutKeyboardUpFunc__proxy: 'sync',
460
glutKeyboardUpFunc: (func) => {
461
GLUT.keyboardUpFunc = func;
462
},
463
464
glutSpecialFunc__proxy: 'sync',
465
glutSpecialFunc: (func) => {
466
GLUT.specialFunc = func;
467
},
468
469
glutSpecialUpFunc__proxy: 'sync',
470
glutSpecialUpFunc: (func) => {
471
GLUT.specialUpFunc = func;
472
},
473
474
glutReshapeFunc__proxy: 'sync',
475
glutReshapeFunc: (func) => {
476
GLUT.reshapeFunc = func;
477
},
478
479
glutMotionFunc__proxy: 'sync',
480
glutMotionFunc: (func) => {
481
GLUT.motionFunc = func;
482
},
483
484
glutPassiveMotionFunc__proxy: 'sync',
485
glutPassiveMotionFunc: (func) => {
486
GLUT.passiveMotionFunc = func;
487
},
488
489
glutMouseFunc__proxy: 'sync',
490
glutMouseFunc: (func) => {
491
GLUT.mouseFunc = func;
492
},
493
494
glutSetCursor__proxy: 'sync',
495
glutSetCursor: (cursor) => {
496
var cursorStyle = 'auto';
497
switch (cursor) {
498
case 0x0000: /* GLUT_CURSOR_RIGHT_ARROW */
499
// No equivalent css cursor style, fallback to 'auto'
500
break;
501
case 0x0001: /* GLUT_CURSOR_LEFT_ARROW */
502
// No equivalent css cursor style, fallback to 'auto'
503
break;
504
case 0x0002: /* GLUT_CURSOR_INFO */
505
cursorStyle = 'pointer';
506
break;
507
case 0x0003: /* GLUT_CURSOR_DESTROY */
508
// No equivalent css cursor style, fallback to 'auto'
509
break;
510
case 0x0004: /* GLUT_CURSOR_HELP */
511
cursorStyle = 'help';
512
break;
513
case 0x0005: /* GLUT_CURSOR_CYCLE */
514
// No equivalent css cursor style, fallback to 'auto'
515
break;
516
case 0x0006: /* GLUT_CURSOR_SPRAY */
517
// No equivalent css cursor style, fallback to 'auto'
518
break;
519
case 0x0007: /* GLUT_CURSOR_WAIT */
520
cursorStyle = 'wait';
521
break;
522
case 0x0008: /* GLUT_CURSOR_TEXT */
523
cursorStyle = 'text';
524
break;
525
case 0x0009: /* GLUT_CURSOR_CROSSHAIR */
526
case 0x0066: /* GLUT_CURSOR_FULL_CROSSHAIR */
527
cursorStyle = 'crosshair';
528
break;
529
case 0x000A: /* GLUT_CURSOR_UP_DOWN */
530
cursorStyle = 'ns-resize';
531
break;
532
case 0x000B: /* GLUT_CURSOR_LEFT_RIGHT */
533
cursorStyle = 'ew-resize';
534
break;
535
case 0x000C: /* GLUT_CURSOR_TOP_SIDE */
536
cursorStyle = 'n-resize';
537
break;
538
case 0x000D: /* GLUT_CURSOR_BOTTOM_SIDE */
539
cursorStyle = 's-resize';
540
break;
541
case 0x000E: /* GLUT_CURSOR_LEFT_SIDE */
542
cursorStyle = 'w-resize';
543
break;
544
case 0x000F: /* GLUT_CURSOR_RIGHT_SIDE */
545
cursorStyle = 'e-resize';
546
break;
547
case 0x0010: /* GLUT_CURSOR_TOP_LEFT_CORNER */
548
cursorStyle = 'nw-resize';
549
break;
550
case 0x0011: /* GLUT_CURSOR_TOP_RIGHT_CORNER */
551
cursorStyle = 'ne-resize';
552
break;
553
case 0x0012: /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */
554
cursorStyle = 'se-resize';
555
break;
556
case 0x0013: /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */
557
cursorStyle = 'sw-resize';
558
break;
559
case 0x0064: /* GLUT_CURSOR_INHERIT */
560
break;
561
case 0x0065: /* GLUT_CURSOR_NONE */
562
cursorStyle = 'none';
563
break;
564
default:
565
throw "glutSetCursor: Unknown cursor type: " + cursor;
566
}
567
Browser.getCanvas().style.cursor = cursorStyle;
568
},
569
570
glutCreateWindow__proxy: 'sync',
571
glutCreateWindow__deps: ['$Browser'],
572
glutCreateWindow: (name) => {
573
var contextAttributes = {
574
antialias: ((GLUT.initDisplayMode & 0x0080 /*GLUT_MULTISAMPLE*/) != 0),
575
depth: ((GLUT.initDisplayMode & 0x0010 /*GLUT_DEPTH*/) != 0),
576
stencil: ((GLUT.initDisplayMode & 0x0020 /*GLUT_STENCIL*/) != 0),
577
alpha: ((GLUT.initDisplayMode & 0x0008 /*GLUT_ALPHA*/) != 0)
578
};
579
#if OFFSCREEN_FRAMEBUFFER
580
// TODO: Make glutCreateWindow explicitly aware of whether it is being proxied or not, and set these to true only when proxying is being performed.
581
GL.enableOffscreenFramebufferAttributes(contextAttributes);
582
#endif
583
if (!Browser.createContext(Browser.getCanvas(), /*useWebGL=*/true, /*setInModule=*/true, contextAttributes)) {
584
return 0; // failure
585
}
586
return 1; // a new GLUT window ID for the created context
587
},
588
589
glutDestroyWindow__proxy: 'sync',
590
glutDestroyWindow__deps: ['$Browser'],
591
glutDestroyWindow: (name) => {
592
delete Module['ctx'];
593
return 1;
594
},
595
596
glutReshapeWindow__proxy: 'sync',
597
glutReshapeWindow__deps: ['$GLUT', 'glutPostRedisplay'],
598
glutReshapeWindow: (width, height) => {
599
Browser.exitFullscreen();
600
Browser.setCanvasSize(width, height, true); // N.B. GLUT.reshapeFunc is also registered as a canvas resize callback.
601
// Just call it once here.
602
if (GLUT.reshapeFunc) {
603
{{{ makeDynCall('vii', 'GLUT.reshapeFunc') }}}(width, height);
604
}
605
_glutPostRedisplay();
606
},
607
608
glutPositionWindow__proxy: 'sync',
609
glutPositionWindow__deps: ['$GLUT', 'glutPostRedisplay'],
610
glutPositionWindow: (x, y) => {
611
Browser.exitFullscreen();
612
/* TODO */
613
_glutPostRedisplay();
614
},
615
616
glutFullScreen__proxy: 'sync',
617
glutFullScreen__deps: ['$GLUT'],
618
glutFullScreen: () => {
619
GLUT.windowX = 0; // TODO
620
GLUT.windowY = 0; // TODO
621
var canvas = Browser.getCanvas();
622
GLUT.windowWidth = canvas.width;
623
GLUT.windowHeight = canvas.height;
624
document.addEventListener('fullscreenchange', GLUT.onFullscreenEventChange, true);
625
document.addEventListener('mozfullscreenchange', GLUT.onFullscreenEventChange, true);
626
document.addEventListener('webkitfullscreenchange', GLUT.onFullscreenEventChange, true);
627
Browser.requestFullscreen(/*lockPointer=*/false, /*resizeCanvas=*/false);
628
},
629
630
glutInitDisplayMode__proxy: 'sync',
631
glutInitDisplayMode: (mode) => GLUT.initDisplayMode = mode,
632
633
glutSwapBuffers__proxy: 'sync',
634
glutSwapBuffers: () => {},
635
636
glutPostRedisplay__proxy: 'sync',
637
glutPostRedisplay__deps: ['$MainLoop'],
638
glutPostRedisplay: () => {
639
if (GLUT.displayFunc && !GLUT.requestedAnimationFrame) {
640
GLUT.requestedAnimationFrame = true;
641
MainLoop.requestAnimationFrame(() => {
642
GLUT.requestedAnimationFrame = false;
643
MainLoop.runIter(() => {{{ makeDynCall('v', 'GLUT.displayFunc') }}}());
644
});
645
}
646
},
647
648
glutMainLoop__proxy: 'sync',
649
glutMainLoop__deps: ['$GLUT', 'glutPostRedisplay'],
650
glutMainLoop: () => {
651
// Do an initial resize, since there's no window resize event on startup
652
GLUT.onResize();
653
_glutPostRedisplay();
654
throw 'unwind';
655
},
656
657
};
658
659
autoAddDeps(LibraryGLUT, '$GLUT');
660
addToLibrary(LibraryGLUT);
661
662