diff options
author | frosch <frosch@openttd.org> | 2015-02-22 23:06:45 +0000 |
---|---|---|
committer | frosch <frosch@openttd.org> | 2015-02-22 23:06:45 +0000 |
commit | 352e528cdab81f1903f13260dedb34d1b113b6e8 (patch) | |
tree | 138854a4db9517f6455825ad79acdfbac9151d9d /src/gfx.cpp | |
parent | fece468d9678fd11ed5435286dd32353c61b1dcc (diff) | |
download | openttd-352e528cdab81f1903f13260dedb34d1b113b6e8.tar.xz |
(svn r27167) -Fix: [SDL, Windows] Right-mouse-button scrolling scrolled/jumped way to far, when OpenTTD lagged during mouse event processing.
Diffstat (limited to 'src/gfx.cpp')
-rw-r--r-- | src/gfx.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/gfx.cpp b/src/gfx.cpp index b10943553..64c7d9186 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1603,6 +1603,53 @@ void SetAnimatedMouseCursor(const AnimCursor *table) SwitchAnimatedCursor(); } +/** + * Update cursor position on mouse movement. + * @param x New X position. + * @param y New Y position. + * @param queued True, if the OS queues mouse warps after pending mouse movement events. + * False, if the warp applies instantaneous. + * @return true, if the OS cursor position should be warped back to this->pos. + */ +bool CursorVars::UpdateCursorPosition(int x, int y, bool queued_warp) +{ + /* Detecting relative mouse movement is somewhat tricky. + * - There may be multiple mouse move events in the video driver queue (esp. when OpenTTD lags a bit). + * - When we request warping the mouse position (return true), a mouse move event is appended at the end of the queue. + * + * So, when this->fix_at is active, we use the following strategy: + * - The first movement triggers the warp to reset the mouse position. + * - Subsequent events have to compute movement relative to the previous event. + * - The relative movement is finished, when we receive the event matching the warp. + */ + + if (x == this->pos.x && y == this->pos.y) { + /* Warp finished. */ + this->queued_warp = false; + } + + this->delta.x = x - (this->queued_warp ? this->last_position.x : this->pos.x); + this->delta.y = y - (this->queued_warp ? this->last_position.y : this->pos.y); + + this->last_position.x = x; + this->last_position.y = y; + + bool need_warp = false; + if (this->fix_at) { + if (!this->queued_warp && (this->delta.x != 0 || this->delta.y != 0)) { + /* Trigger warp. */ + this->queued_warp = queued_warp; + need_warp = true; + } + } else if (this->pos.x != x || this->pos.y != y) { + this->queued_warp = false; // Cancel warping, we are no longer confining the position. + this->dirty = true; + this->pos.x = x; + this->pos.y = y; + } + return need_warp; +} + bool ChangeResInGame(int width, int height) { return (_screen.width == width && _screen.height == height) || VideoDriver::GetInstance()->ChangeResolution(width, height); |