mirror of https://github.com/libsdl-org/SDL.git
emscripten: simulate mouse autocapture.
This is just enough to delay MOUSE_LEAVE events until a drag ending outside the canvas is released, and make sure the MOUSE_UP event has the canvas's SDL_WindowID, which it wouldn't when mouse focus is was lost by this point. Fixes #10033.
This commit is contained in:
parent
f79083d9bb
commit
307e6f2ca6
|
|
@ -314,8 +314,11 @@ static EM_BOOL Emscripten_HandleMouseButton(int eventType, const EmscriptenMouse
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
SDL_assert(mouse != NULL);
|
||||||
|
|
||||||
if (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN) {
|
if (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN) {
|
||||||
if (SDL_GetMouse()->relative_mode && !window_data->has_pointer_lock) {
|
if (mouse->relative_mode && !window_data->has_pointer_lock) {
|
||||||
emscripten_request_pointerlock(window_data->canvas_id, 0); // try to regrab lost pointer lock.
|
emscripten_request_pointerlock(window_data->canvas_id, 0); // try to regrab lost pointer lock.
|
||||||
}
|
}
|
||||||
sdl_button_state = true;
|
sdl_button_state = true;
|
||||||
|
|
@ -323,13 +326,30 @@ static EM_BOOL Emscripten_HandleMouseButton(int eventType, const EmscriptenMouse
|
||||||
sdl_button_state = false;
|
sdl_button_state = false;
|
||||||
prevent_default = SDL_EventEnabled(SDL_EVENT_MOUSE_BUTTON_UP);
|
prevent_default = SDL_EventEnabled(SDL_EVENT_MOUSE_BUTTON_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SendMouseButton(0, window_data->window, SDL_DEFAULT_MOUSE_ID, sdl_button, sdl_button_state);
|
SDL_SendMouseButton(0, window_data->window, SDL_DEFAULT_MOUSE_ID, sdl_button, sdl_button_state);
|
||||||
|
|
||||||
// Do not consume the event if the mouse is outside of the canvas.
|
// We have an imaginary mouse capture, because we need SDL to not drop our imaginary mouse focus when we leave the canvas.
|
||||||
emscripten_get_element_css_size(window_data->canvas_id, &css_w, &css_h);
|
if (mouse->auto_capture) {
|
||||||
if (mouseEvent->targetX < 0 || mouseEvent->targetX >= css_w ||
|
if (SDL_GetMouseState(NULL, NULL) != 0) {
|
||||||
mouseEvent->targetY < 0 || mouseEvent->targetY >= css_h) {
|
window_data->window->flags |= SDL_WINDOW_MOUSE_CAPTURE;
|
||||||
return 0;
|
} else {
|
||||||
|
window_data->window->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((eventType == EMSCRIPTEN_EVENT_MOUSEUP) && window_data->mouse_focus_loss_pending) {
|
||||||
|
window_data->mouse_focus_loss_pending = (window_data->window->flags & SDL_WINDOW_MOUSE_CAPTURE) != 0;
|
||||||
|
if (!window_data->mouse_focus_loss_pending) {
|
||||||
|
SDL_SetMouseFocus(NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Do not consume the event if the mouse is outside of the canvas.
|
||||||
|
emscripten_get_element_css_size(window_data->canvas_id, &css_w, &css_h);
|
||||||
|
if (mouseEvent->targetX < 0 || mouseEvent->targetX >= css_w ||
|
||||||
|
mouseEvent->targetY < 0 || mouseEvent->targetY >= css_h) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return prevent_default;
|
return prevent_default;
|
||||||
|
|
@ -352,8 +372,16 @@ static EM_BOOL Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseE
|
||||||
SDL_SendMouseMotion(0, window_data->window, SDL_GLOBAL_MOUSE_ID, isPointerLocked, mx, my);
|
SDL_SendMouseMotion(0, window_data->window, SDL_GLOBAL_MOUSE_ID, isPointerLocked, mx, my);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetMouseFocus(eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? window_data->window : NULL);
|
const bool isenter = (eventType == EMSCRIPTEN_EVENT_MOUSEENTER);
|
||||||
return SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION);
|
if (isenter && window_data->mouse_focus_loss_pending) {
|
||||||
|
window_data->mouse_focus_loss_pending = false; // just drop the state, but don't send the enter event.
|
||||||
|
} else if (!isenter && (window_data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||||
|
window_data->mouse_focus_loss_pending = true; // waiting on a mouse button to let go before we send the mouse focus update.
|
||||||
|
} else {
|
||||||
|
SDL_SetMouseFocus(isenter ? window_data->window : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION); // !!! FIXME: should this be MOUSE_MOTION or something else?
|
||||||
}
|
}
|
||||||
|
|
||||||
static EM_BOOL Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
|
static EM_BOOL Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ struct SDL_WindowData
|
||||||
bool fullscreen_resize;
|
bool fullscreen_resize;
|
||||||
|
|
||||||
bool has_pointer_lock;
|
bool has_pointer_lock;
|
||||||
|
|
||||||
|
bool mouse_focus_loss_pending;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Emscripten_ShouldSetSwapInterval(int interval);
|
bool Emscripten_ShouldSetSwapInterval(int interval);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue