emscripten-core / emscripten-core/emscripten
Module.canvas.exitPointerLock is not a function [ONLY if compiling with SIDE_MODULE=2]
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
**Version of emscripten/emsdk:**
```
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.29-git
clang version 16.0.0 (https://github.com/llvm/llvm-project.git 947d529e4194e0567cfbbea99127066f76c87269)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /usr/local/Cellar/emscripten/3.1.29/libexec/llvm/bin
```
**Failing full example below :**
It basically `git clone` ImGui, and compiles the necessary files unmodified, to launch the "Demo Window".
```
#!/bin/bash
set -ex
[ -d imgui/ ] || git clone --branch v1.89.2 https://github.com/ocornut/imgui.git
files_imgui="imgui/imgui.cpp imgui/imgui_draw.cpp imgui/imgui_demo.cpp imgui/imgui_widgets.cpp imgui/imgui_tables.cpp"
files_backends="imgui/backends/imgui_impl_sdl.cpp imgui/backends/imgui_impl_opengl3.cpp"
file_main="imgui/examples/example_emscripten_opengl3/main.cpp"
read -d '' -a flags_all < (web1.js:1985:33)
at 500b98b2:0x17ac
at _ImGui_ImplSDL2_NewFrame (web1.js:2311:45)
at main_loop(void*) (web1.wasm:0x6d32)
[...]
```
What's weird about it it that there is not much changes needed to make it works ;
There is 3 particular curious behaviours that I observed ;
### 1) `SDL_ShowCursor` is the only thing preventing the WHOLE `ImGui` to works :
```
--- a/backends/imgui_impl_sdl.cpp
+++ b/backends/imgui_impl_sdl.cpp
@@ -481,7 +481,7 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
{
// Show OS mouse cursor
SDL_SetCursor(bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
- SDL_ShowCursor(SDL_TRUE);
+// SDL_ShowCursor(SDL_TRUE);
}
}
```
Commenting the above line make it works. (or changing it to SDL_FALSE);
### 2) Moving the SAME "code execution" of *ONLY* `SDL_ShowCursor` to the "main module" also works ;
I mean : this is the "call path" :
```
main.cpp (main module) calls ImGui_ImplSDL2_NewFrame()
`- which calls ImGui_ImplSDL2_UpdateMouseCursor() at its tail (discards the UpdateGamepads below to simplify)
`- which calls SDL_ShowCursor(SDL_TRUE) at its tail
```
If you just do 2 things :
- comment out the `SDL_ShowCursor(SDL_TRUE)` inside the "side module" (backends/imgui_impl_sdl.cpp)
- add `SDL_ShowCursor(SDL_TRUE)` inside the "main module" just after the call to ImGui_ImplSDL2_NewFrame()
you would agree that the "code path execution" is the same.
(we just moved a call to `SDL_ShowCursor `, from the tail of the side module, to the tail of the function calling the side module)
Weirdly, it makes it works.
**This is my biggest concern**, of course as I shown it _is_ work-around-able, but I wonder WHY moving a call from the "side module" to the "main module" makes it works.
Please note that I tried to enforce the `SDL_ShowCursor` function to not be "stripped / excluded" from the binary, by adding **IN ALL CASES** a call to it from the "main module", just before calling the "side module"'s `ImGui_ImplSDL2_NewFrame()` ;
I also tried to add a new function to the "side module", which just call `SDL_ShowCursor`, which I used to figure out the effect of calling `SDL_ShowCursor` from the "main module" vs/ with a slight indirection going through the "side module".
The observations holds : the call to `SDL_ShowCursor(SDL_TRUE)` from the "main module" passes okay, but if we call a one-liner function from the "side module" doing only this call, it does not work anymore.
So that's my observation : all things equal, calling `SDL_ShowCursor(SDL_TRUE)` from the "main module" works okay, and calling it (instead, or again, does not matter) from the "side module" **JUST AFTER** does not work.
So that's a little like "doing this thing from the main module works, doing the same thing from the side module does not work".
### 3) Slight difference in behaviour between `MAIN_MODULE=1` and `=2` ;
Possibly observable only on my macOS platform, due to high DPI stuff.
I told you that for `MAIN_MODULE=1` to `=2`, to make it work, I just weirdly had to either :
- comment out the call to `SDL_ShowCursor()`
- or move this call to the "main module".
Well, I lied. I mean, it made `ImGui` mostly works, except that a bug of resolution / high dpi appears.
(the mouse coordinates are not where ImGui think it really is). This fix it :
```
--- a/examples/example_emscripten_opengl3/main.cpp
+++ b/examples/example_emscripten_opengl3/main.cpp
@@ -48,7 +48,7 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, ¤t);
- SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE /*| SDL_WINDOW_ALLOW_HIGHDPI*/);
g_Window = SDL_CreateWindow("Dear ImGui Emscripten example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
g_GLContext = SDL_GL_CreateContext(g_Window);
if (!g_GLContext)
```
Of course it fixes it, I just commented some things related to HIGHDPI (without even knowing what I did)
What's weird me out there, is that there is some behaviour differences between `MAIN_MODULE=1` and `=2.
Baring any linking or symbol problem, I would then have expected all behaviour to be the same ?
It tickles some curiosity, and maybe be a symptom of a bug.
Kind Regards,
Contributor guide
Assessment
This issue has not been assessed yet.