diff --git a/Bin/Data/Scripts/NinjaSnowWar.as b/Bin/Data/Scripts/NinjaSnowWar.as index ac1e39a6d..497a9b18c 100644 --- a/Bin/Data/Scripts/NinjaSnowWar.as +++ b/Bin/Data/Scripts/NinjaSnowWar.as @@ -53,7 +53,6 @@ uint clientNodeID = 0; int clientScore = 0; bool touchEnabled = false; -float timeSinceLastTouch = 1.0; int touchButtonSize = 96; int touchButtonBorder = 12; int moveTouchID = -1; @@ -89,7 +88,6 @@ void Start() SubscribeToEvent("Kill", "HandleKill"); SubscribeToEvent("ScreenMode", "HandleScreenMode"); SubscribeToEvent("TouchBegin", "HandleTouchBegin"); - SubscribeToEvent("TouchMove", "HandleTouchMove"); SubscribeToEvent("TouchEnd", "HandleTouchEnd"); if (singlePlayer) @@ -404,8 +402,7 @@ void SpawnPlayer(Connection@ connection) void HandleUpdate(StringHash eventType, VariantMap& eventData) { float timeStep = eventData["TimeStep"].GetFloat(); - timeSinceLastTouch += timeStep; - + UpdateControls(); CheckEndAndRestart(); @@ -463,8 +460,6 @@ void HandleTouchBegin(StringHash eventType, VariantMap& eventData) if (!touchEnabled) InitTouchInput(); - timeSinceLastTouch = 0.0; - int touchID = eventData["TouchID"].GetInt(); IntVector2 pos(eventData["X"].GetInt(), eventData["Y"].GetInt()); UIElement@ element = ui.GetElementAt(pos, false); @@ -477,11 +472,6 @@ void HandleTouchBegin(StringHash eventType, VariantMap& eventData) rotateTouchID = touchID; } -void HandleTouchMove(StringHash eventType, VariantMap& eventData) -{ - timeSinceLastTouch = 0.0; -} - void HandleTouchEnd(StringHash eventType, VariantMap& eventData) { int touchID = eventData["TouchID"].GetInt(); @@ -1004,14 +994,10 @@ void UpdateControls() playerControls.Set(CTRL_JUMP, true); } - // Touch is also emulated as mouse. Before using mouse for actions, make sure there has been some time since last touch - if (timeSinceLastTouch > 0.5) - { - if (input.mouseButtonDown[MOUSEB_LEFT] || input.mouseButtonPress[MOUSEB_LEFT]) - playerControls.Set(CTRL_FIRE, true); - if (input.mouseButtonDown[MOUSEB_RIGHT] || input.mouseButtonPress[MOUSEB_RIGHT]) - playerControls.Set(CTRL_JUMP, true); - } + if (input.mouseButtonDown[MOUSEB_LEFT] || input.mouseButtonPress[MOUSEB_LEFT]) + playerControls.Set(CTRL_FIRE, true); + if (input.mouseButtonDown[MOUSEB_RIGHT] || input.mouseButtonPress[MOUSEB_RIGHT]) + playerControls.Set(CTRL_JUMP, true); playerControls.yaw += mouseSensitivity * input.mouseMoveX; playerControls.pitch += mouseSensitivity * input.mouseMoveY; diff --git a/Docs/Reference.dox b/Docs/Reference.dox index 4e36c4328..ed68ca710 100644 --- a/Docs/Reference.dox +++ b/Docs/Reference.dox @@ -1116,8 +1116,6 @@ To get joystick input, the joystick(s) must first be explicitly opened using \re From the input subsystem you can also query whether the application window has input focus, or is minimized. -Note that touch events also create emulated mouse events. This can not be prevented on the Windows platform, so the SDL library also emulates it on other platforms for consistency. Refer to the NinjaSnowWar example on how to prevent unwanted control in case you want to support both mouse and touch. - \page Audio %Audio The Audio subsystem implements an audio output stream. Once it has been initialized, the following operations are supported: diff --git a/Engine/Input/Input.cpp b/Engine/Input/Input.cpp index 0afd3a417..17f5cc784 100644 --- a/Engine/Input/Input.cpp +++ b/Engine/Input/Input.cpp @@ -137,45 +137,42 @@ void Input::Update() // Check for relative mode mouse move if (!mouseVisible_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS)) { - // Make sure the mouse move is not an emulated touch - if (!GetNumTouches()) + IntVector2 mousePosition = GetMousePosition(); + mouseMove_ = mousePosition - lastMousePosition_; + + // Recenter the mouse cursor manually + IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2); + if (mousePosition != center) { - IntVector2 mousePosition = GetMousePosition(); - mouseMove_ = mousePosition - lastMousePosition_; - - // Recenter the mouse cursor manually - IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2); SetMousePosition(center); lastMousePosition_ = center; - - // Send mouse move event if necessary - if (mouseMove_ != IntVector2::ZERO) + } + + // Send mouse move event if necessary + if (mouseMove_ != IntVector2::ZERO) + { + if (suppressNextMouseMove_) { - if (suppressNextMouseMove_) - { - mouseMove_ = IntVector2::ZERO; - suppressNextMouseMove_ = false; - } - else - { - using namespace MouseMove; + mouseMove_ = IntVector2::ZERO; + suppressNextMouseMove_ = false; + } + else + { + using namespace MouseMove; - VariantMap eventData; - if (mouseVisible_) - { - eventData[P_X] = mousePosition.x_; - eventData[P_Y] = mousePosition.y_; - } - eventData[P_DX] = mouseMove_.x_; - eventData[P_DY] = mouseMove_.y_; - eventData[P_BUTTONS] = mouseButtonDown_; - eventData[P_QUALIFIERS] = GetQualifiers(); - SendEvent(E_MOUSEMOVE, eventData); + VariantMap eventData; + if (mouseVisible_) + { + eventData[P_X] = mousePosition.x_; + eventData[P_Y] = mousePosition.y_; } + eventData[P_DX] = mouseMove_.x_; + eventData[P_DY] = mouseMove_.y_; + eventData[P_BUTTONS] = mouseButtonDown_; + eventData[P_QUALIFIERS] = GetQualifiers(); + SendEvent(E_MOUSEMOVE, eventData); } } - else - suppressNextMouseMove_ = true; } } @@ -683,15 +680,19 @@ void Input::HandleSDLEvent(void* sdlEvent) case SDL_FINGERUP: { int touchID = evt.tfinger.fingerId & 0x7ffffff; - touches_.Erase(touchID); + TouchState& state = touches_[touchID]; using namespace TouchEnd; VariantMap eventData; + // Do not trust the position in the finger up event. Instead use the last position stored in the + // touch structure eventData[P_TOUCHID] = touchID; - eventData[P_X] = evt.tfinger.x * graphics_->GetWidth(); - eventData[P_Y] = evt.tfinger.y * graphics_->GetHeight(); + eventData[P_X] = state.position_.x_; + eventData[P_Y] = state.position_.y_; + + touches_.Erase(touchID); SendEvent(E_TOUCHEND, eventData); } break; diff --git a/Engine/Script/APITemplates.h b/Engine/Script/APITemplates.h index dbdc726c7..383471434 100644 --- a/Engine/Script/APITemplates.h +++ b/Engine/Script/APITemplates.h @@ -1047,6 +1047,7 @@ template void RegisterButton(asIScriptEngine* engine, const char* clas engine->RegisterObjectMethod(className, "float get_repeatDelay() const", asMETHOD(T, GetRepeatDelay), asCALL_THISCALL); engine->RegisterObjectMethod(className, "void set_repeatRate(float)", asMETHOD(T, SetRepeatRate), asCALL_THISCALL); engine->RegisterObjectMethod(className, "float get_repeatRate() const", asMETHOD(T, GetRepeatRate), asCALL_THISCALL); + engine->RegisterObjectMethod(className, "bool get_pressed() const", asMETHOD(T, IsPressed), asCALL_THISCALL); } } diff --git a/Engine/UI/Button.cpp b/Engine/UI/Button.cpp index 775a9d930..cd6998d66 100644 --- a/Engine/UI/Button.cpp +++ b/Engine/UI/Button.cpp @@ -97,18 +97,15 @@ void Button::GetBatches(PODVector& batches, PODVector& vertexDat void Button::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor) { BorderImage::OnHover(position, screenPosition, buttons, qualifiers, cursor); - if (pressed_) + if (pressed_ && !(buttons & MOUSEB_LEFT)) { - if (!(buttons & MOUSEB_LEFT)) - { - SetPressed(false); + SetPressed(false); - using namespace Released; + using namespace Released; - VariantMap eventData; - eventData[P_ELEMENT] = (void*)this; - SendEvent(E_RELEASED, eventData); - } + VariantMap eventData; + eventData[P_ELEMENT] = (void*)this; + SendEvent(E_RELEASED, eventData); } } diff --git a/Engine/UI/Button.h b/Engine/UI/Button.h index 37ff69e47..29bcdf836 100644 --- a/Engine/UI/Button.h +++ b/Engine/UI/Button.h @@ -74,7 +74,9 @@ public: float GetRepeatDelay() const { return repeatDelay_; } /// Return repeat rate. float GetRepeatRate() const { return repeatRate_; } - + /// Return whether is currently pressed. + bool IsPressed() const { return pressed_; } + protected: /// Set new pressed state. void SetPressed(bool enable); diff --git a/Engine/UI/UI.cpp b/Engine/UI/UI.cpp index e600f757b..78299ebb2 100644 --- a/Engine/UI/UI.cpp +++ b/Engine/UI/UI.cpp @@ -71,6 +71,7 @@ UI::UI(Context* context) : mouseButtons_(0), qualifiers_(0), initialized_(false), + usingTouchInput_(false), #ifdef WIN32 nonFocusedMouseWheel_(false), // Default MS Windows behaviour #else @@ -89,6 +90,9 @@ UI::UI(Context* context) : SubscribeToEvent(E_MOUSEBUTTONUP, HANDLER(UI, HandleMouseButtonUp)); SubscribeToEvent(E_MOUSEMOVE, HANDLER(UI, HandleMouseMove)); SubscribeToEvent(E_MOUSEWHEEL, HANDLER(UI, HandleMouseWheel)); + SubscribeToEvent(E_TOUCHBEGIN, HANDLER(UI, HandleTouchBegin)); + SubscribeToEvent(E_TOUCHEND, HANDLER(UI, HandleTouchEnd)); + SubscribeToEvent(E_TOUCHMOVE, HANDLER(UI, HandleTouchMove)); SubscribeToEvent(E_KEYDOWN, HANDLER(UI, HandleKeyDown)); SubscribeToEvent(E_CHAR, HANDLER(UI, HandleChar)); @@ -265,7 +269,8 @@ void UI::Update(float timeStep) bool cursorVisible; GetCursorPositionAndVisible(cursorPos, cursorVisible); - if (cursorVisible) + // Mouse hover + if (!usingTouchInput_ && cursorVisible) { WeakPtr element(GetElementAt(cursorPos)); @@ -307,16 +312,14 @@ void UI::Update(float timeStep) // Touch hover Input* input = GetSubsystem(); - if (input) + unsigned numTouches = input->GetNumTouches(); + + for (unsigned i = 0; i < numTouches; ++i) { - unsigned numTouches = input->GetNumTouches(); - for (unsigned i = 0; i < numTouches; ++i) - { - TouchState* touch = input->GetTouch(i); - UIElement* element = GetElementAt(touch->position_); - if (element && element->IsEnabled()) - element->OnHover(element->ScreenToElement(touch->position_), touch->position_, MOUSEB_LEFT, 0, 0); - } + TouchState* touch = input->GetTouch(i); + UIElement* element = GetElementAt(touch->position_); + if (element && element->IsEnabled()) + element->OnHover(element->ScreenToElement(touch->position_), touch->position_, MOUSEB_LEFT, 0, 0); } Update(timeStep, rootElement_); @@ -490,8 +493,7 @@ UIElement* UI::GetFrontElement() const IntVector2 UI::GetCursorPosition() const { - Input* input = GetSubsystem(); - return (input->IsMouseVisible() || !cursor_) ? input->GetMousePosition() : cursor_->GetPosition(); + return cursor_ ? cursor_->GetPosition() : GetSubsystem()->GetMousePosition(); } bool UI::HasModalElement() const @@ -761,18 +763,17 @@ UIElement* UI::GetFocusableElement(UIElement* element) void UI::GetCursorPositionAndVisible(IntVector2& pos, bool& visible) { - Input* input = GetSubsystem(); - - if (input->IsMouseVisible() || !cursor_) - { - pos = input->GetMousePosition(); - visible = input->IsMouseVisible(); - } - else + if (cursor_) { pos = cursor_->GetPosition(); visible = cursor_->IsVisible(); } + else + { + Input* input = GetSubsystem(); + pos = input->GetMousePosition(); + visible = input->IsMouseVisible(); + } } void UI::SetCursorShape(CursorShape shape) @@ -817,6 +818,7 @@ void UI::HandleMouseButtonDown(StringHash eventType, VariantMap& eventData) { mouseButtons_ = eventData[MouseButtonDown::P_BUTTONS].GetInt(); qualifiers_ = eventData[MouseButtonDown::P_QUALIFIERS].GetInt(); + usingTouchInput_ = false; IntVector2 cursorPos; bool cursorVisible; @@ -923,6 +925,7 @@ void UI::HandleMouseMove(StringHash eventType, VariantMap& eventData) mouseButtons_ = eventData[P_BUTTONS].GetInt(); qualifiers_ = eventData[P_QUALIFIERS].GetInt(); + usingTouchInput_ = false; Input* input = GetSubsystem(); const IntVector2& rootSize = rootElement_->GetSize(); @@ -976,6 +979,7 @@ void UI::HandleMouseWheel(StringHash eventType, VariantMap& eventData) mouseButtons_ = eventData[P_BUTTONS].GetInt(); qualifiers_ = eventData[P_QUALIFIERS].GetInt(); int delta = eventData[P_WHEEL].GetInt(); + usingTouchInput_ = false; IntVector2 cursorPos; bool cursorVisible; @@ -1012,6 +1016,119 @@ void UI::HandleMouseWheel(StringHash eventType, VariantMap& eventData) } } +void UI::HandleTouchBegin(StringHash eventType, VariantMap& eventData) +{ + using namespace TouchBegin; + + IntVector2 pos(eventData[P_X].GetInt(), eventData[P_Y].GetInt()); + WeakPtr element(GetElementAt(pos)); + usingTouchInput_ = true; + + if (element) + { + // Handle focusing & bringing to front + SetFocusElement(element); + element->BringToFront(); + + // Handle click + element->OnClick(element->ScreenToElement(pos), pos, MOUSEB_LEFT, 0, 0); + + // Handle start of drag. OnClick() may have caused destruction of the element, so check the pointer again + if (element && !dragElement_ ) + { + dragElement_ = element; + element->OnDragBegin(element->ScreenToElement(pos), pos, MOUSEB_LEFT, 0, 0); + SendDragEvent(E_DRAGBEGIN, element, pos); + } + } + else + { + // If clicked over no element, or a disabled element, lose focus + SetFocusElement(0); + } + + VariantMap clickEventData; + clickEventData[UIMouseClick::P_ELEMENT] = (void*)element.Get(); + clickEventData[UIMouseClick::P_X] = pos.x_; + clickEventData[UIMouseClick::P_Y] = pos.y_; + clickEventData[UIMouseClick::P_BUTTON] = MOUSEB_LEFT; + clickEventData[UIMouseClick::P_BUTTONS] = MOUSEB_LEFT; + clickEventData[UIMouseClick::P_QUALIFIERS] = 0; + SendEvent(E_UIMOUSECLICK, clickEventData); +} + +void UI::HandleTouchEnd(StringHash eventType, VariantMap& eventData) +{ + using namespace TouchEnd; + + IntVector2 pos(eventData[P_X].GetInt(), eventData[P_Y].GetInt()); + + // Transmit hover end to the position where the finger was lifted + UIElement* element = GetElementAt(pos); + if (element && element->IsEnabled()) + element->OnHover(element->ScreenToElement(pos), pos, 0, 0, 0); + + if (dragElement_) + { + if (dragElement_->IsEnabled() && dragElement_->IsVisible()) + { + dragElement_->OnDragEnd(dragElement_->ScreenToElement(pos), pos, cursor_); + SendDragEvent(E_DRAGEND, dragElement_, pos); + + // Drag and drop finish + bool dragSource = dragElement_ && (dragElement_->GetDragDropMode() & DD_SOURCE) != 0; + if (dragSource) + { + WeakPtr target(GetElementAt(pos)); + bool dragTarget = target && (target->GetDragDropMode() & DD_TARGET) != 0; + bool dragDropFinish = dragSource && dragTarget && target != dragElement_; + + if (dragDropFinish) + { + bool accept = target->OnDragDropFinish(dragElement_); + + // OnDragDropFinish() may have caused destruction of the elements, so check the pointers again + if (accept && dragElement_ && target) + { + using namespace DragDropFinish; + + VariantMap eventData; + eventData[P_SOURCE] = (void*)dragElement_.Get(); + eventData[P_TARGET] = (void*)target.Get(); + eventData[P_ACCEPT] = accept; + SendEvent(E_DRAGDROPFINISH, eventData); + } + } + } + } + + dragElement_.Reset(); + } +} + +void UI::HandleTouchMove(StringHash eventType, VariantMap& eventData) +{ + using namespace TouchMove; + + IntVector2 pos(eventData[P_X].GetInt(), eventData[P_Y].GetInt()); + usingTouchInput_ = true; + + if (dragElement_) + { + if (dragElement_->IsEnabled() && dragElement_->IsVisible()) + { + dragElement_->OnDragMove(dragElement_->ScreenToElement(pos), pos, MOUSEB_LEFT, 0, 0); + SendDragEvent(E_DRAGMOVE, dragElement_, pos); + } + else + { + dragElement_->OnDragEnd(dragElement_->ScreenToElement(pos), pos, 0); + SendDragEvent(E_DRAGEND, dragElement_, pos); + dragElement_.Reset(); + } + } +} + void UI::HandleKeyDown(StringHash eventType, VariantMap& eventData) { using namespace KeyDown; diff --git a/Engine/UI/UI.h b/Engine/UI/UI.h index 8192dbc0e..f9b12be90 100644 --- a/Engine/UI/UI.h +++ b/Engine/UI/UI.h @@ -133,6 +133,12 @@ private: void HandleMouseMove(StringHash eventType, VariantMap& eventData); /// Handle mouse wheel event. void HandleMouseWheel(StringHash eventType, VariantMap& eventData); + /// Handle touch begin event. + void HandleTouchBegin(StringHash eventType, VariantMap& eventData); + /// Handle touch end event. + void HandleTouchEnd(StringHash eventType, VariantMap& eventData); + /// Handle touch move event. + void HandleTouchMove(StringHash eventType, VariantMap& eventData); /// Handle keypress event. void HandleKeyDown(StringHash eventType, VariantMap& eventData); /// Handle character event. @@ -188,6 +194,8 @@ private: int qualifiers_; /// Initialized flag. bool initialized_; + /// Touch used flag. + bool usingTouchInput_; /// Flag to switch mouse wheel event to be sent to non-focused element at cursor. bool nonFocusedMouseWheel_; /// Non-modal batch size (used internally for rendering). diff --git a/ThirdParty/SDL/src/video/android/SDL_androidtouch.c b/ThirdParty/SDL/src/video/android/SDL_androidtouch.c index 3265b54eb..926f26b95 100644 --- a/ThirdParty/SDL/src/video/android/SDL_androidtouch.c +++ b/ThirdParty/SDL/src/video/android/SDL_androidtouch.c @@ -18,6 +18,9 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + +// Modified by Lasse Oorni for Urho3D + #include "SDL_config.h" #if SDL_VIDEO_DRIVER_ANDROID @@ -75,11 +78,12 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio if (!leftFingerDown) { Android_GetWindowCoordinates(x, y, &window_x, &window_y); + // Urho3D: do not send emulated mouse events /* send moved event */ - SDL_SendMouseMotion(NULL, SDL_TOUCH_MOUSEID, 0, window_x, window_y); + //SDL_SendMouseMotion(NULL, SDL_TOUCH_MOUSEID, 0, window_x, window_y); /* send mouse down event */ - SDL_SendMouseButton(NULL, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); + //SDL_SendMouseButton(NULL, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); leftFingerDown = fingerId; } @@ -90,7 +94,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio Android_GetWindowCoordinates(x, y, &window_x, &window_y); /* send moved event */ - SDL_SendMouseMotion(NULL, SDL_TOUCH_MOUSEID, 0, window_x, window_y); + //SDL_SendMouseMotion(NULL, SDL_TOUCH_MOUSEID, 0, window_x, window_y); } SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p); break; @@ -98,7 +102,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio case ACTION_POINTER_1_UP: if (fingerId == leftFingerDown) { /* send mouse up */ - SDL_SendMouseButton(NULL, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); + //SDL_SendMouseButton(NULL, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); leftFingerDown = 0; } SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p); diff --git a/ThirdParty/SDL/src/video/uikit/SDL_uikitview.m b/ThirdParty/SDL/src/video/uikit/SDL_uikitview.m index e808962ef..04ccfee0b 100644 --- a/ThirdParty/SDL/src/video/uikit/SDL_uikitview.m +++ b/ThirdParty/SDL/src/video/uikit/SDL_uikitview.m @@ -18,6 +18,9 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + +// Modified by Lasse Oorni for Urho3D + #include "SDL_config.h" #if SDL_VIDEO_DRIVER_UIKIT @@ -88,11 +91,12 @@ if (!leftFingerDown) { CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; + // Urho3D: do not send emulated mouse events /* send moved event */ - SDL_SendMouseMotion(NULL, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); + //SDL_SendMouseMotion(NULL, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); /* send mouse down event */ - SDL_SendMouseButton(NULL, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); + //SDL_SendMouseButton(NULL, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); leftFingerDown = touch; } @@ -128,7 +132,7 @@ while(touch) { if (touch == leftFingerDown) { /* send mouse up */ - SDL_SendMouseButton(NULL, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); + //SDL_SendMouseButton(NULL, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); leftFingerDown = nil; } @@ -171,7 +175,7 @@ CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; /* send moved event */ - SDL_SendMouseMotion(NULL, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); + //SDL_SendMouseMotion(NULL, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); } CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; diff --git a/ThirdParty/SDL/src/video/windows/SDL_windowsevents.c b/ThirdParty/SDL/src/video/windows/SDL_windowsevents.c index ca799ff80..a4aba3c3a 100644 --- a/ThirdParty/SDL/src/video/windows/SDL_windowsevents.c +++ b/ThirdParty/SDL/src/video/windows/SDL_windowsevents.c @@ -18,6 +18,9 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + +// Modified by Lasse Oorni for Urho3D + #include "SDL_config.h" #if SDL_VIDEO_DRIVER_WINDOWS @@ -261,7 +264,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { SDL_WindowData *data; LRESULT returnCode = -1; - + + // Urho3D: detect emulated mouse events + // Note: if we move mouse cursor manually (relative mouse motion with hidden cursor) we may get emulated mouse + // events with zero extra info, so we should only center the cursor when it has actually moved + BOOL emulatedMouse = (GetMessageExtraInfo() & 0xffffff00) == 0xff515700; + /* Send a SDL_SYSWMEVENT if the application wants them */ if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) { SDL_SysWMmsg wmmsg; @@ -382,7 +390,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) break; case WM_MOUSEMOVE: - if( !SDL_GetMouse()->relative_mode ) + if( !emulatedMouse && !SDL_GetMouse()->relative_mode ) SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); /* don't break here, fall through to check the wParam like the button presses */ case WM_LBUTTONUP: @@ -393,7 +401,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: - if( !SDL_GetMouse()->relative_mode ) + if( !emulatedMouse && !SDL_GetMouse()->relative_mode ) WIN_CheckWParamMouseButtons( wParam, data ); break;