mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r27167) -Fix: [SDL, Windows] Right-mouse-button scrolling scrolled/jumped way to far, when OpenTTD lagged during mouse event processing.
This commit is contained in:
parent
fece468d96
commit
352e528cda
47
src/gfx.cpp
47
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);
|
||||
|
|
|
@ -138,6 +138,12 @@ struct CursorVars {
|
|||
bool in_window; ///< mouse inside this window, determines drawing logic
|
||||
|
||||
bool vehchain; ///< vehicle chain is dragged
|
||||
|
||||
bool UpdateCursorPosition(int x, int y, bool queued_warp);
|
||||
|
||||
private:
|
||||
bool queued_warp;
|
||||
Point last_position;
|
||||
};
|
||||
|
||||
/** Data about how and where to blit pixels. */
|
||||
|
|
|
@ -388,22 +388,10 @@ static void PollEvent()
|
|||
}
|
||||
|
||||
/* Mouse movement */
|
||||
int dx = mouse_x - _cursor.pos.x;
|
||||
int dy = mouse_y - _cursor.pos.y;
|
||||
if (dx != 0 || dy != 0) {
|
||||
if (_cursor.fix_at) {
|
||||
_cursor.delta.x = dx;
|
||||
_cursor.delta.y = dy;
|
||||
position_mouse(_cursor.pos.x, _cursor.pos.y);
|
||||
} else {
|
||||
_cursor.delta.x = dx;
|
||||
_cursor.delta.y = dy;
|
||||
_cursor.pos.x = mouse_x;
|
||||
_cursor.pos.y = mouse_y;
|
||||
_cursor.dirty = true;
|
||||
}
|
||||
mouse_action = true;
|
||||
if (_cursor.UpdateCursorPosition(mouse_x, mouse_y, false)) {
|
||||
position_mouse(_cursor.pos.x, _cursor.pos.y);
|
||||
}
|
||||
if (_cursor.delta.x != 0 || _cursor.delta.y) mouse_action = true;
|
||||
|
||||
static int prev_mouse_z = 0;
|
||||
if (prev_mouse_z != mouse_z) {
|
||||
|
|
|
@ -362,22 +362,8 @@ static void QZ_DoUnsidedModifiers(unsigned int newMods)
|
|||
|
||||
static void QZ_MouseMovedEvent(int x, int y)
|
||||
{
|
||||
if (_cursor.fix_at) {
|
||||
int dx = x - _cursor.pos.x;
|
||||
int dy = y - _cursor.pos.y;
|
||||
|
||||
if (dx != 0 || dy != 0) {
|
||||
_cursor.delta.x += dx;
|
||||
_cursor.delta.y += dy;
|
||||
|
||||
QZ_WarpCursor(_cursor.pos.x, _cursor.pos.y);
|
||||
}
|
||||
} else {
|
||||
_cursor.delta.x = x - _cursor.pos.x;
|
||||
_cursor.delta.y = y - _cursor.pos.y;
|
||||
_cursor.pos.x = x;
|
||||
_cursor.pos.y = y;
|
||||
_cursor.dirty = true;
|
||||
if (_cursor.UpdateCursorPosition(x, y, false)) {
|
||||
QZ_WarpCursor(_cursor.pos.x, _cursor.pos.y);
|
||||
}
|
||||
HandleMouseEvents();
|
||||
}
|
||||
|
|
|
@ -545,20 +545,8 @@ int VideoDriver_SDL::PollEvent()
|
|||
|
||||
switch (ev.type) {
|
||||
case SDL_MOUSEMOTION:
|
||||
if (_cursor.fix_at) {
|
||||
int dx = ev.motion.x - _cursor.pos.x;
|
||||
int dy = ev.motion.y - _cursor.pos.y;
|
||||
if (dx != 0 || dy != 0) {
|
||||
_cursor.delta.x = dx;
|
||||
_cursor.delta.y = dy;
|
||||
SDL_CALL SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y);
|
||||
}
|
||||
} else {
|
||||
_cursor.delta.x = ev.motion.x - _cursor.pos.x;
|
||||
_cursor.delta.y = ev.motion.y - _cursor.pos.y;
|
||||
_cursor.pos.x = ev.motion.x;
|
||||
_cursor.pos.y = ev.motion.y;
|
||||
_cursor.dirty = true;
|
||||
if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) {
|
||||
SDL_CALL SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y);
|
||||
}
|
||||
HandleMouseEvents();
|
||||
break;
|
||||
|
|
|
@ -747,25 +747,11 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
|
|||
SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc);
|
||||
}
|
||||
|
||||
if (_cursor.fix_at) {
|
||||
int dx = x - _cursor.pos.x;
|
||||
int dy = y - _cursor.pos.y;
|
||||
if (dx != 0 || dy != 0) {
|
||||
_cursor.delta.x = dx;
|
||||
_cursor.delta.y = dy;
|
||||
|
||||
pt.x = _cursor.pos.x;
|
||||
pt.y = _cursor.pos.y;
|
||||
|
||||
ClientToScreen(hwnd, &pt);
|
||||
SetCursorPos(pt.x, pt.y);
|
||||
}
|
||||
} else {
|
||||
_cursor.delta.x = x - _cursor.pos.x;
|
||||
_cursor.delta.y = y - _cursor.pos.y;
|
||||
_cursor.pos.x = x;
|
||||
_cursor.pos.y = y;
|
||||
_cursor.dirty = true;
|
||||
if (_cursor.UpdateCursorPosition(x, y, true)) {
|
||||
pt.x = _cursor.pos.x;
|
||||
pt.y = _cursor.pos.y;
|
||||
ClientToScreen(hwnd, &pt);
|
||||
SetCursorPos(pt.x, pt.y);
|
||||
}
|
||||
MyShowCursor(false);
|
||||
HandleMouseEvents();
|
||||
|
|
Loading…
Reference in New Issue