summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gfx.cpp24
-rw-r--r--src/gfx_type.h1
-rw-r--r--src/video/sdl2_v.cpp35
3 files changed, 59 insertions, 1 deletions
diff --git a/src/gfx.cpp b/src/gfx.cpp
index 6039946fc..8027dad26 100644
--- a/src/gfx.cpp
+++ b/src/gfx.cpp
@@ -1785,6 +1785,30 @@ void SetAnimatedMouseCursor(const AnimCursor *table)
}
/**
+ * Update cursor position on mouse movement for relative modes.
+ * @param delta_x How much change in the X position.
+ * @param delta_y How much change in the Y position.
+ */
+void CursorVars::UpdateCursorPositionRelative(int delta_x, int delta_y)
+{
+ if (this->fix_at) {
+ this->delta.x = delta_x;
+ this->delta.y = delta_y;
+ } else {
+ int last_position_x = this->pos.x;
+ int last_position_y = this->pos.y;
+
+ this->pos.x = Clamp(this->pos.x + delta_x, 0, _cur_resolution.width - 1);
+ this->pos.y = Clamp(this->pos.y + delta_y, 0, _cur_resolution.height - 1);
+
+ this->delta.x = last_position_x - this->pos.x;
+ this->delta.y = last_position_y - this->pos.y;
+
+ this->dirty = true;
+ }
+}
+
+/**
* Update cursor position on mouse movement.
* @param x New X position.
* @param y New Y position.
diff --git a/src/gfx_type.h b/src/gfx_type.h
index 452bc2c7e..ab802c45e 100644
--- a/src/gfx_type.h
+++ b/src/gfx_type.h
@@ -143,6 +143,7 @@ struct CursorVars {
/* Drag data */
bool vehchain; ///< vehicle chain is dragged
+ void UpdateCursorPositionRelative(int delta_x, int delta_y);
bool UpdateCursorPosition(int x, int y, bool queued_warp);
private:
diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp
index 68b0aa983..852f7298d 100644
--- a/src/video/sdl2_v.cpp
+++ b/src/video/sdl2_v.cpp
@@ -51,6 +51,11 @@ static volatile bool _draw_continue;
static Palette _local_palette;
static SDL_Palette *_sdl_palette;
+#ifdef __EMSCRIPTEN__
+/** Whether we just had a window-enter event. */
+static bool _cursor_new_in_window = false;
+#endif
+
#define MAX_DIRTY_RECTS 100
static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS];
static int _num_dirty_rects;
@@ -350,6 +355,9 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
bool VideoDriver_SDL::ClaimMousePointer()
{
SDL_ShowCursor(0);
+#ifdef __EMSCRIPTEN__
+ SDL_SetRelativeMouseMode(SDL_TRUE);
+#endif
return true;
}
@@ -509,9 +517,27 @@ int VideoDriver_SDL::PollEvent()
switch (ev.type) {
case SDL_MOUSEMOTION:
+#ifdef __EMSCRIPTEN__
+ if (_cursor_new_in_window) {
+ /* The cursor just moved into the window; this means we don't
+ * know the absolutely position yet to move relative from.
+ * Before this time, SDL didn't know it either, and this is
+ * why we postpone it till now. Update the absolute position
+ * for this once, and work relative after. */
+ _cursor.pos.x = ev.motion.x;
+ _cursor.pos.y = ev.motion.y;
+ _cursor.dirty = true;
+
+ _cursor_new_in_window = false;
+ SDL_SetRelativeMouseMode(SDL_TRUE);
+ } else {
+ _cursor.UpdateCursorPositionRelative(ev.motion.xrel, ev.motion.yrel);
+ }
+#else
if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) {
SDL_WarpMouseInWindow(_sdl_window, _cursor.pos.x, _cursor.pos.y);
}
+#endif
HandleMouseEvents();
break;
@@ -615,6 +641,12 @@ int VideoDriver_SDL::PollEvent()
} else if (ev.window.event == SDL_WINDOWEVENT_ENTER) {
// mouse entered the window, enable cursor
_cursor.in_window = true;
+#ifdef __EMSCRIPTEN__
+ /* Disable relative mouse mode for the first mouse motion,
+ * so we can pick up the absolutely position again. */
+ _cursor_new_in_window = true;
+ SDL_SetRelativeMouseMode(SDL_FALSE);
+#endif
} else if (ev.window.event == SDL_WINDOWEVENT_LEAVE) {
// mouse left the window, undraw cursor
UndrawMouseCursor();
@@ -631,7 +663,8 @@ const char *VideoDriver_SDL::Start(const StringList &parm)
/* Explicitly disable hardware acceleration. Enabling this causes
* UpdateWindowSurface() to update the window's texture instead of
* its surface. */
- SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION , "0");
+ SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION, "0");
+ SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
/* Just on the offchance the audio subsystem started before the video system,
* check whether any part of SDL has been initialised before getting here.