emscripten-core / emscripten-core/emscripten

Module.canvas.exitPointerLock is not a function [ONLY if compiling with SIDE_MODULE=2]

Open
#18,541 14 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.