Path: blob/master/platform/web/js/libs/library_godot_display.js
21643 views
/**************************************************************************/1/* library_godot_display.js */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930const GodotDisplayVK = {3132$GodotDisplayVK__deps: ['$GodotRuntime', '$GodotConfig', '$GodotEventListeners', '$GodotInput'],33$GodotDisplayVK__postset: 'GodotOS.atexit(function(resolve, reject) { GodotDisplayVK.clear(); resolve(); });',34$GodotDisplayVK: {35textinput: null,36textarea: null,3738available: function () {39return GodotConfig.virtual_keyboard && 'ontouchstart' in window;40},4142init: function (input_cb) {43function create(what) {44const elem = document.createElement(what);45elem.style.display = 'none';46elem.style.position = 'absolute';47elem.style.zIndex = '-1';48elem.style.background = 'transparent';49elem.style.padding = '0px';50elem.style.margin = '0px';51elem.style.overflow = 'hidden';52elem.style.width = '0px';53elem.style.height = '0px';54elem.style.border = '0px';55elem.style.outline = 'none';56elem.readonly = true;57elem.disabled = true;58GodotEventListeners.add(elem, 'input', function (evt) {59const c_str = GodotRuntime.allocString(elem.value);60input_cb(c_str, elem.selectionEnd);61GodotRuntime.free(c_str);62}, false);63if (what === 'input') {64// Handling the "Enter" key.65const onKey = (pEvent, pEventName) => {66if (pEvent.key !== 'Enter') {67return;68}69GodotInput.onKeyEvent(pEventName === 'keydown', pEvent);70};71GodotEventListeners.add(elem, 'keydown', (pEvent) => onKey(pEvent, 'keydown'), false);72GodotEventListeners.add(elem, 'keyup', (pEvent) => onKey(pEvent, 'keyup'), false);73}74GodotEventListeners.add(elem, 'blur', function (evt) {75elem.style.display = 'none';76elem.readonly = true;77elem.disabled = true;78}, false);79GodotConfig.canvas.insertAdjacentElement('beforebegin', elem);80return elem;81}82GodotDisplayVK.textinput = create('input');83GodotDisplayVK.textarea = create('textarea');84GodotDisplayVK.updateSize();85},86show: function (text, type, start, end) {87if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) {88return;89}90if (GodotDisplayVK.textinput.style.display !== '' || GodotDisplayVK.textarea.style.display !== '') {91GodotDisplayVK.hide();92}93GodotDisplayVK.updateSize();9495let elem = GodotDisplayVK.textinput;96switch (type) {97case 0: // KEYBOARD_TYPE_DEFAULT98elem.type = 'text';99elem.inputmode = '';100break;101case 1: // KEYBOARD_TYPE_MULTILINE102elem = GodotDisplayVK.textarea;103break;104case 2: // KEYBOARD_TYPE_NUMBER105elem.type = 'text';106elem.inputmode = 'numeric';107break;108case 3: // KEYBOARD_TYPE_NUMBER_DECIMAL109elem.type = 'text';110elem.inputmode = 'decimal';111break;112case 4: // KEYBOARD_TYPE_PHONE113elem.type = 'tel';114elem.inputmode = '';115break;116case 5: // KEYBOARD_TYPE_EMAIL_ADDRESS117elem.type = 'email';118elem.inputmode = '';119break;120case 6: // KEYBOARD_TYPE_PASSWORD121elem.type = 'password';122elem.inputmode = '';123break;124case 7: // KEYBOARD_TYPE_URL125elem.type = 'url';126elem.inputmode = '';127break;128default:129elem.type = 'text';130elem.inputmode = '';131break;132}133134elem.readonly = false;135elem.disabled = false;136elem.value = text;137elem.style.display = 'block';138elem.focus();139elem.setSelectionRange(start, end);140},141hide: function () {142if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) {143return;144}145[GodotDisplayVK.textinput, GodotDisplayVK.textarea].forEach(function (elem) {146elem.blur();147elem.style.display = 'none';148elem.value = '';149});150},151updateSize: function () {152if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) {153return;154}155const rect = GodotConfig.canvas.getBoundingClientRect();156function update(elem) {157elem.style.left = `${rect.left}px`;158elem.style.top = `${rect.top}px`;159elem.style.width = `${rect.width}px`;160elem.style.height = `${rect.height}px`;161}162update(GodotDisplayVK.textinput);163update(GodotDisplayVK.textarea);164},165clear: function () {166if (GodotDisplayVK.textinput) {167GodotDisplayVK.textinput.remove();168GodotDisplayVK.textinput = null;169}170if (GodotDisplayVK.textarea) {171GodotDisplayVK.textarea.remove();172GodotDisplayVK.textarea = null;173}174},175},176};177mergeInto(LibraryManager.library, GodotDisplayVK);178179/*180* Display server cursor helper.181* Keeps track of cursor status and custom shapes.182*/183const GodotDisplayCursor = {184$GodotDisplayCursor__deps: ['$GodotOS', '$GodotConfig'],185$GodotDisplayCursor__postset: 'GodotOS.atexit(function(resolve, reject) { GodotDisplayCursor.clear(); resolve(); });',186$GodotDisplayCursor: {187shape: 'default',188visible: true,189cursors: {},190set_style: function (style) {191GodotConfig.canvas.style.cursor = style;192},193set_shape: function (shape) {194GodotDisplayCursor.shape = shape;195let css = shape;196if (shape in GodotDisplayCursor.cursors) {197const c = GodotDisplayCursor.cursors[shape];198css = `url("${c.url}") ${c.x} ${c.y}, default`;199}200if (GodotDisplayCursor.visible) {201GodotDisplayCursor.set_style(css);202}203},204clear: function () {205GodotDisplayCursor.set_style('');206GodotDisplayCursor.shape = 'default';207GodotDisplayCursor.visible = true;208Object.keys(GodotDisplayCursor.cursors).forEach(function (key) {209URL.revokeObjectURL(GodotDisplayCursor.cursors[key]);210delete GodotDisplayCursor.cursors[key];211});212},213lockPointer: function () {214const canvas = GodotConfig.canvas;215if (canvas.requestPointerLock) {216canvas.requestPointerLock();217}218},219releasePointer: function () {220if (document.exitPointerLock) {221document.exitPointerLock();222}223},224isPointerLocked: function () {225return document.pointerLockElement === GodotConfig.canvas;226},227},228};229mergeInto(LibraryManager.library, GodotDisplayCursor);230231const GodotDisplayScreen = {232$GodotDisplayScreen__deps: ['$GodotConfig', '$GodotOS', '$GL', 'emscripten_webgl_get_current_context'],233$GodotDisplayScreen: {234desired_size: [0, 0],235hidpi: true,236getPixelRatio: function () {237return GodotDisplayScreen.hidpi ? window.devicePixelRatio || 1 : 1;238},239isFullscreen: function () {240const elem = document.fullscreenElement || document.mozFullscreenElement241|| document.webkitFullscreenElement || document.msFullscreenElement;242if (elem) {243return elem === GodotConfig.canvas;244}245// But maybe knowing the element is not supported.246return document.fullscreen || document.mozFullScreen247|| document.webkitIsFullscreen;248},249hasFullscreen: function () {250return document.fullscreenEnabled || document.mozFullScreenEnabled251|| document.webkitFullscreenEnabled;252},253requestFullscreen: function () {254if (!GodotDisplayScreen.hasFullscreen()) {255return 1;256}257const canvas = GodotConfig.canvas;258try {259const promise = (canvas.requestFullscreen || canvas.msRequestFullscreen260|| canvas.mozRequestFullScreen || canvas.mozRequestFullscreen261|| canvas.webkitRequestFullscreen262).call(canvas);263// Some browsers (Safari) return undefined.264// For the standard ones, we need to catch it.265if (promise) {266promise.catch(function () {267// nothing to do.268});269}270} catch (e) {271return 1;272}273return 0;274},275exitFullscreen: function () {276if (!GodotDisplayScreen.isFullscreen()) {277return 0;278}279try {280const promise = document.exitFullscreen();281if (promise) {282promise.catch(function () {283// nothing to do.284});285}286} catch (e) {287return 1;288}289return 0;290},291_updateGL: function () {292const gl_context_handle = _emscripten_webgl_get_current_context();293const gl = GL.getContext(gl_context_handle);294if (gl) {295GL.resizeOffscreenFramebuffer(gl);296}297},298updateSize: function () {299const isFullscreen = GodotDisplayScreen.isFullscreen();300const wantsFullWindow = GodotConfig.canvas_resize_policy === 2;301const noResize = GodotConfig.canvas_resize_policy === 0;302const dWidth = GodotDisplayScreen.desired_size[0];303const dHeight = GodotDisplayScreen.desired_size[1];304const canvas = GodotConfig.canvas;305let width = dWidth;306let height = dHeight;307if (noResize) {308// Don't resize canvas, just update GL if needed.309if (canvas.width !== width || canvas.height !== height) {310GodotDisplayScreen.desired_size = [canvas.width, canvas.height];311GodotDisplayScreen._updateGL();312return 1;313}314return 0;315}316const scale = GodotDisplayScreen.getPixelRatio();317if (isFullscreen || wantsFullWindow) {318// We need to match screen size.319width = Math.floor(window.innerWidth * scale);320height = Math.floor(window.innerHeight * scale);321}322const csw = `${Math.floor(width / scale)}px`;323const csh = `${Math.floor(height / scale)}px`;324if (canvas.style.width !== csw || canvas.style.height !== csh || canvas.width !== width || canvas.height !== height) {325// Size doesn't match.326// Resize canvas, set correct CSS pixel size, update GL.327canvas.width = width;328canvas.height = height;329canvas.style.width = csw;330canvas.style.height = csh;331GodotDisplayScreen._updateGL();332return 1;333}334return 0;335},336},337};338mergeInto(LibraryManager.library, GodotDisplayScreen);339340/**341* Display server interface.342*343* Exposes all the functions needed by DisplayServer implementation.344*/345const GodotDisplay = {346$GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotEventListeners', '$GodotDisplayScreen', '$GodotDisplayVK'],347$GodotDisplay: {348window_icon: '',349getDPI: function () {350// devicePixelRatio is given in dppx351// https://drafts.csswg.org/css-values/#resolution352// > due to the 1:96 fixed ratio of CSS *in* to CSS *px*, 1dppx is equivalent to 96dpi.353const dpi = Math.round(window.devicePixelRatio * 96);354return dpi >= 96 ? dpi : 96;355},356},357358godot_js_display_is_swap_ok_cancel__proxy: 'sync',359godot_js_display_is_swap_ok_cancel__sig: 'i',360godot_js_display_is_swap_ok_cancel: function () {361const win = (['Windows', 'Win64', 'Win32', 'WinCE']);362const plat = navigator.platform || '';363if (win.indexOf(plat) !== -1) {364return 1;365}366return 0;367},368369godot_js_tts_is_speaking__proxy: 'sync',370godot_js_tts_is_speaking__sig: 'i',371godot_js_tts_is_speaking: function () {372return window.speechSynthesis.speaking;373},374375godot_js_tts_is_paused__proxy: 'sync',376godot_js_tts_is_paused__sig: 'i',377godot_js_tts_is_paused: function () {378return window.speechSynthesis.paused;379},380381godot_js_tts_get_voices__proxy: 'sync',382godot_js_tts_get_voices__sig: 'vi',383godot_js_tts_get_voices: function (p_callback) {384const func = GodotRuntime.get_func(p_callback);385try {386const arr = [];387const voices = window.speechSynthesis.getVoices();388for (let i = 0; i < voices.length; i++) {389arr.push(`${voices[i].lang};${voices[i].name}`);390}391const c_ptr = GodotRuntime.allocStringArray(arr);392func(arr.length, c_ptr);393GodotRuntime.freeStringArray(c_ptr, arr.length);394} catch (e) {395// Fail graciously.396}397},398399godot_js_tts_speak__proxy: 'sync',400godot_js_tts_speak__sig: 'viiiffii',401godot_js_tts_speak: function (p_text, p_voice, p_volume, p_pitch, p_rate, p_utterance_id, p_callback) {402const func = GodotRuntime.get_func(p_callback);403404function listener_end(evt) {405evt.currentTarget.cb(1 /* TTS_UTTERANCE_ENDED */, evt.currentTarget.id, 0);406}407408function listener_start(evt) {409evt.currentTarget.cb(0 /* TTS_UTTERANCE_STARTED */, evt.currentTarget.id, 0);410}411412function listener_error(evt) {413evt.currentTarget.cb(2 /* TTS_UTTERANCE_CANCELED */, evt.currentTarget.id, 0);414}415416function listener_bound(evt) {417evt.currentTarget.cb(3 /* TTS_UTTERANCE_BOUNDARY */, evt.currentTarget.id, evt.charIndex);418}419420const utterance = new SpeechSynthesisUtterance(GodotRuntime.parseString(p_text));421utterance.rate = p_rate;422utterance.pitch = p_pitch;423utterance.volume = p_volume / 100.0;424utterance.addEventListener('end', listener_end);425utterance.addEventListener('start', listener_start);426utterance.addEventListener('error', listener_error);427utterance.addEventListener('boundary', listener_bound);428utterance.id = p_utterance_id;429utterance.cb = func;430const voice = GodotRuntime.parseString(p_voice);431const voices = window.speechSynthesis.getVoices();432for (let i = 0; i < voices.length; i++) {433if (voices[i].name === voice) {434utterance.voice = voices[i];435break;436}437}438window.speechSynthesis.resume();439window.speechSynthesis.speak(utterance);440},441442godot_js_tts_pause__proxy: 'sync',443godot_js_tts_pause__sig: 'v',444godot_js_tts_pause: function () {445window.speechSynthesis.pause();446},447448godot_js_tts_resume__proxy: 'sync',449godot_js_tts_resume__sig: 'v',450godot_js_tts_resume: function () {451window.speechSynthesis.resume();452},453454godot_js_tts_stop__proxy: 'sync',455godot_js_tts_stop__sig: 'v',456godot_js_tts_stop: function () {457window.speechSynthesis.cancel();458window.speechSynthesis.resume();459},460461godot_js_display_alert__proxy: 'sync',462godot_js_display_alert__sig: 'vi',463godot_js_display_alert: function (p_text) {464window.alert(GodotRuntime.parseString(p_text)); // eslint-disable-line no-alert465},466467godot_js_display_screen_dpi_get__proxy: 'sync',468godot_js_display_screen_dpi_get__sig: 'i',469godot_js_display_screen_dpi_get: function () {470return GodotDisplay.getDPI();471},472473godot_js_display_pixel_ratio_get__proxy: 'sync',474godot_js_display_pixel_ratio_get__sig: 'f',475godot_js_display_pixel_ratio_get: function () {476return GodotDisplayScreen.getPixelRatio();477},478479godot_js_display_fullscreen_request__proxy: 'sync',480godot_js_display_fullscreen_request__sig: 'i',481godot_js_display_fullscreen_request: function () {482return GodotDisplayScreen.requestFullscreen();483},484485godot_js_display_fullscreen_exit__proxy: 'sync',486godot_js_display_fullscreen_exit__sig: 'i',487godot_js_display_fullscreen_exit: function () {488return GodotDisplayScreen.exitFullscreen();489},490491godot_js_display_desired_size_set__proxy: 'sync',492godot_js_display_desired_size_set__sig: 'vii',493godot_js_display_desired_size_set: function (width, height) {494GodotDisplayScreen.desired_size = [width, height];495GodotDisplayScreen.updateSize();496},497498godot_js_display_size_update__proxy: 'sync',499godot_js_display_size_update__sig: 'i',500godot_js_display_size_update: function () {501const updated = GodotDisplayScreen.updateSize();502if (updated) {503GodotDisplayVK.updateSize();504}505return updated;506},507508godot_js_display_screen_size_get__proxy: 'sync',509godot_js_display_screen_size_get__sig: 'vii',510godot_js_display_screen_size_get: function (width, height) {511const scale = GodotDisplayScreen.getPixelRatio();512GodotRuntime.setHeapValue(width, window.screen.width * scale, 'i32');513GodotRuntime.setHeapValue(height, window.screen.height * scale, 'i32');514},515516godot_js_display_window_size_get__proxy: 'sync',517godot_js_display_window_size_get__sig: 'vii',518godot_js_display_window_size_get: function (p_width, p_height) {519GodotRuntime.setHeapValue(p_width, GodotConfig.canvas.width, 'i32');520GodotRuntime.setHeapValue(p_height, GodotConfig.canvas.height, 'i32');521},522523godot_js_display_has_webgl__proxy: 'sync',524godot_js_display_has_webgl__sig: 'ii',525godot_js_display_has_webgl: function (p_version) {526if (p_version !== 1 && p_version !== 2) {527return false;528}529try {530return !!document.createElement('canvas').getContext(p_version === 2 ? 'webgl2' : 'webgl');531} catch (e) { /* Not available */ }532return false;533},534535/*536* Canvas537*/538godot_js_display_canvas_focus__proxy: 'sync',539godot_js_display_canvas_focus__sig: 'v',540godot_js_display_canvas_focus: function () {541GodotConfig.canvas.focus();542},543544godot_js_display_canvas_is_focused__proxy: 'sync',545godot_js_display_canvas_is_focused__sig: 'i',546godot_js_display_canvas_is_focused: function () {547return document.activeElement === GodotConfig.canvas;548},549550/*551* Touchscreen552*/553godot_js_display_touchscreen_is_available__proxy: 'sync',554godot_js_display_touchscreen_is_available__sig: 'i',555godot_js_display_touchscreen_is_available: function () {556return 'ontouchstart' in window;557},558559/*560* Clipboard561*/562godot_js_display_clipboard_set__proxy: 'sync',563godot_js_display_clipboard_set__sig: 'ii',564godot_js_display_clipboard_set: function (p_text) {565const text = GodotRuntime.parseString(p_text);566if (!navigator.clipboard || !navigator.clipboard.writeText) {567return 1;568}569navigator.clipboard.writeText(text).catch(function (e) {570// Setting OS clipboard is only possible from an input callback.571GodotRuntime.error('Setting OS clipboard is only possible from an input callback for the Web platform. Exception:', e);572});573return 0;574},575576godot_js_display_clipboard_get__proxy: 'sync',577godot_js_display_clipboard_get__sig: 'ii',578godot_js_display_clipboard_get: function (callback) {579const func = GodotRuntime.get_func(callback);580try {581navigator.clipboard.readText().then(function (result) {582const ptr = GodotRuntime.allocString(result);583func(ptr);584GodotRuntime.free(ptr);585}).catch(function (e) {586// Fail graciously.587});588} catch (e) {589// Fail graciously.590}591},592593/*594* Window595*/596godot_js_display_window_title_set__proxy: 'sync',597godot_js_display_window_title_set__sig: 'vi',598godot_js_display_window_title_set: function (p_data) {599document.title = GodotRuntime.parseString(p_data);600},601602godot_js_display_window_icon_set__proxy: 'sync',603godot_js_display_window_icon_set__sig: 'vii',604godot_js_display_window_icon_set: function (p_ptr, p_len) {605let link = document.getElementById('-gd-engine-icon');606const old_icon = GodotDisplay.window_icon;607if (p_ptr) {608if (link === null) {609link = document.createElement('link');610link.rel = 'icon';611link.id = '-gd-engine-icon';612document.head.appendChild(link);613}614const png = new Blob([GodotRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { type: 'image/png' });615GodotDisplay.window_icon = URL.createObjectURL(png);616link.href = GodotDisplay.window_icon;617} else {618if (link) {619link.remove();620}621GodotDisplay.window_icon = null;622}623if (old_icon) {624URL.revokeObjectURL(old_icon);625}626},627628/*629* Cursor630*/631godot_js_display_cursor_set_visible__proxy: 'sync',632godot_js_display_cursor_set_visible__sig: 'vi',633godot_js_display_cursor_set_visible: function (p_visible) {634const visible = p_visible !== 0;635if (visible === GodotDisplayCursor.visible) {636return;637}638GodotDisplayCursor.visible = visible;639if (visible) {640GodotDisplayCursor.set_shape(GodotDisplayCursor.shape);641} else {642GodotDisplayCursor.set_style('none');643}644},645646godot_js_display_cursor_is_hidden__proxy: 'sync',647godot_js_display_cursor_is_hidden__sig: 'i',648godot_js_display_cursor_is_hidden: function () {649return !GodotDisplayCursor.visible;650},651652godot_js_display_cursor_set_shape__proxy: 'sync',653godot_js_display_cursor_set_shape__sig: 'vi',654godot_js_display_cursor_set_shape: function (p_string) {655GodotDisplayCursor.set_shape(GodotRuntime.parseString(p_string));656},657658godot_js_display_cursor_set_custom_shape__proxy: 'sync',659godot_js_display_cursor_set_custom_shape__sig: 'viiiii',660godot_js_display_cursor_set_custom_shape: function (p_shape, p_ptr, p_len, p_hotspot_x, p_hotspot_y) {661const shape = GodotRuntime.parseString(p_shape);662const old_shape = GodotDisplayCursor.cursors[shape];663if (p_len > 0) {664const png = new Blob([GodotRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { type: 'image/png' });665const url = URL.createObjectURL(png);666GodotDisplayCursor.cursors[shape] = {667url: url,668x: p_hotspot_x,669y: p_hotspot_y,670};671} else {672delete GodotDisplayCursor.cursors[shape];673}674if (shape === GodotDisplayCursor.shape) {675GodotDisplayCursor.set_shape(GodotDisplayCursor.shape);676}677if (old_shape) {678URL.revokeObjectURL(old_shape.url);679}680},681682godot_js_display_cursor_lock_set__proxy: 'sync',683godot_js_display_cursor_lock_set__sig: 'vi',684godot_js_display_cursor_lock_set: function (p_lock) {685if (p_lock) {686GodotDisplayCursor.lockPointer();687} else {688GodotDisplayCursor.releasePointer();689}690},691692godot_js_display_cursor_is_locked__proxy: 'sync',693godot_js_display_cursor_is_locked__sig: 'i',694godot_js_display_cursor_is_locked: function () {695return GodotDisplayCursor.isPointerLocked() ? 1 : 0;696},697698/*699* Listeners700*/701godot_js_display_fullscreen_cb__proxy: 'sync',702godot_js_display_fullscreen_cb__sig: 'vi',703godot_js_display_fullscreen_cb: function (callback) {704const canvas = GodotConfig.canvas;705const func = GodotRuntime.get_func(callback);706function change_cb(evt) {707if (evt.target === canvas) {708func(GodotDisplayScreen.isFullscreen());709}710}711GodotEventListeners.add(document, 'fullscreenchange', change_cb, false);712GodotEventListeners.add(document, 'mozfullscreenchange', change_cb, false);713GodotEventListeners.add(document, 'webkitfullscreenchange', change_cb, false);714},715716godot_js_display_window_blur_cb__proxy: 'sync',717godot_js_display_window_blur_cb__sig: 'vi',718godot_js_display_window_blur_cb: function (callback) {719const func = GodotRuntime.get_func(callback);720GodotEventListeners.add(window, 'blur', function () {721func();722}, false);723},724725godot_js_display_notification_cb__proxy: 'sync',726godot_js_display_notification_cb__sig: 'viiiii',727godot_js_display_notification_cb: function (callback, p_enter, p_exit, p_in, p_out) {728const canvas = GodotConfig.canvas;729const func = GodotRuntime.get_func(callback);730const notif = [p_enter, p_exit, p_in, p_out];731['mouseover', 'mouseleave', 'focus', 'blur'].forEach(function (evt_name, idx) {732GodotEventListeners.add(canvas, evt_name, function () {733func(notif[idx]);734}, true);735});736},737738godot_js_display_setup_canvas__proxy: 'sync',739godot_js_display_setup_canvas__sig: 'viiii',740godot_js_display_setup_canvas: function (p_width, p_height, p_fullscreen, p_hidpi) {741const canvas = GodotConfig.canvas;742GodotEventListeners.add(canvas, 'contextmenu', function (ev) {743ev.preventDefault();744}, false);745GodotEventListeners.add(canvas, 'webglcontextlost', function (ev) {746alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert747ev.preventDefault();748}, false);749GodotDisplayScreen.hidpi = !!p_hidpi;750switch (GodotConfig.canvas_resize_policy) {751case 0: // None752GodotDisplayScreen.desired_size = [canvas.width, canvas.height];753break;754case 1: // Project755GodotDisplayScreen.desired_size = [p_width, p_height];756break;757default: // Full window758// Ensure we display in the right place, the size will be handled by updateSize759canvas.style.position = 'absolute';760canvas.style.top = 0;761canvas.style.left = 0;762break;763}764GodotDisplayScreen.updateSize();765if (p_fullscreen) {766GodotDisplayScreen.requestFullscreen();767}768},769770/*771* Virtual Keyboard772*/773godot_js_display_vk_show__proxy: 'sync',774godot_js_display_vk_show__sig: 'viiii',775godot_js_display_vk_show: function (p_text, p_type, p_start, p_end) {776const text = GodotRuntime.parseString(p_text);777const start = p_start > 0 ? p_start : 0;778const end = p_end > 0 ? p_end : start;779GodotDisplayVK.show(text, p_type, start, end);780},781782godot_js_display_vk_hide__proxy: 'sync',783godot_js_display_vk_hide__sig: 'v',784godot_js_display_vk_hide: function () {785GodotDisplayVK.hide();786},787788godot_js_display_vk_available__proxy: 'sync',789godot_js_display_vk_available__sig: 'i',790godot_js_display_vk_available: function () {791return GodotDisplayVK.available();792},793794godot_js_display_tts_available__proxy: 'sync',795godot_js_display_tts_available__sig: 'i',796godot_js_display_tts_available: function () {797return 'speechSynthesis' in window;798},799800godot_js_display_vk_cb__proxy: 'sync',801godot_js_display_vk_cb__sig: 'vi',802godot_js_display_vk_cb: function (p_input_cb) {803const input_cb = GodotRuntime.get_func(p_input_cb);804if (GodotDisplayVK.available()) {805GodotDisplayVK.init(input_cb);806}807},808};809810autoAddDeps(GodotDisplay, '$GodotDisplay');811mergeInto(LibraryManager.library, GodotDisplay);812813814