From e17cc520d60a4918b40eca42d1e0f7e7666712a9 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Fri, 27 Feb 2015 21:27:55 +0100 Subject: [PATCH] Implemented support for horizontal mouse wheel scrolling as well as high-precision scrolling on Windows and OS X. --- include/SFML/Window/Event.hpp | 99 +++++++++++++++-------- src/SFML/Window/OSX/SFOpenGLView.mm | 2 +- src/SFML/Window/OSX/WindowImplCocoa.hpp | 5 +- src/SFML/Window/OSX/WindowImplCocoa.mm | 18 ++++- src/SFML/Window/Unix/WindowImplX11.cpp | 17 ++++ src/SFML/Window/Win32/WindowImplWin32.cpp | 43 ++++++++-- 6 files changed, 139 insertions(+), 45 deletions(-) diff --git a/include/SFML/Window/Event.hpp b/include/SFML/Window/Event.hpp index 60be6b5e4..9138b04e2 100644 --- a/include/SFML/Window/Event.hpp +++ b/include/SFML/Window/Event.hpp @@ -102,6 +102,9 @@ public: //////////////////////////////////////////////////////////// /// \brief Mouse wheel events parameters (MouseWheelMoved) /// + /// \deprecated This event is deprecated and potentially inaccurate. + /// Use MouseWheelVerticalEvent instead. + /// //////////////////////////////////////////////////////////// struct MouseWheelEvent { @@ -110,6 +113,28 @@ public: int y; ///< Y position of the mouse pointer, relative to the top of the owner window }; + //////////////////////////////////////////////////////////// + /// \brief Mouse wheel horizontal events parameters (MouseWheelHorizontalMoved) + /// + //////////////////////////////////////////////////////////// + struct MouseWheelHorizontalEvent + { + float delta; ///< Number of ticks the wheel has moved (positive is left, negative is right) + int x; ///< X position of the mouse pointer, relative to the left of the owner window + int y; ///< Y position of the mouse pointer, relative to the top of the owner window + }; + + //////////////////////////////////////////////////////////// + /// \brief Mouse wheel vertical events parameters (MouseWheelVerticalMoved) + /// + //////////////////////////////////////////////////////////// + struct MouseWheelVerticalEvent + { + float delta; ///< Number of ticks the wheel has moved (positive is up, negative is down) + int x; ///< X position of the mouse pointer, relative to the left of the owner window + int y; ///< Y position of the mouse pointer, relative to the top of the owner window + }; + //////////////////////////////////////////////////////////// /// \brief Joystick connection events parameters /// (JoystickConnected, JoystickDisconnected) @@ -152,7 +177,7 @@ public: int x; ///< X position of the touch, relative to the left of the owner window int y; ///< Y position of the touch, relative to the top of the owner window }; - + //////////////////////////////////////////////////////////// /// \brief Sensor event parameters (SensorChanged) /// @@ -171,30 +196,32 @@ public: //////////////////////////////////////////////////////////// enum EventType { - Closed, ///< The window requested to be closed (no data) - Resized, ///< The window was resized (data in event.size) - LostFocus, ///< The window lost the focus (no data) - GainedFocus, ///< The window gained the focus (no data) - TextEntered, ///< A character was entered (data in event.text) - KeyPressed, ///< A key was pressed (data in event.key) - KeyReleased, ///< A key was released (data in event.key) - MouseWheelMoved, ///< The mouse wheel was scrolled (data in event.mouseWheel) - MouseButtonPressed, ///< A mouse button was pressed (data in event.mouseButton) - MouseButtonReleased, ///< A mouse button was released (data in event.mouseButton) - MouseMoved, ///< The mouse cursor moved (data in event.mouseMove) - MouseEntered, ///< The mouse cursor entered the area of the window (no data) - MouseLeft, ///< The mouse cursor left the area of the window (no data) - JoystickButtonPressed, ///< A joystick button was pressed (data in event.joystickButton) - JoystickButtonReleased, ///< A joystick button was released (data in event.joystickButton) - JoystickMoved, ///< The joystick moved along an axis (data in event.joystickMove) - JoystickConnected, ///< A joystick was connected (data in event.joystickConnect) - JoystickDisconnected, ///< A joystick was disconnected (data in event.joystickConnect) - TouchBegan, ///< A touch event began (data in event.touch) - TouchMoved, ///< A touch moved (data in event.touch) - TouchEnded, ///< A touch event ended (data in event.touch) - SensorChanged, ///< A sensor value changed (data in event.sensor) + Closed, ///< The window requested to be closed (no data) + Resized, ///< The window was resized (data in event.size) + LostFocus, ///< The window lost the focus (no data) + GainedFocus, ///< The window gained the focus (no data) + TextEntered, ///< A character was entered (data in event.text) + KeyPressed, ///< A key was pressed (data in event.key) + KeyReleased, ///< A key was released (data in event.key) + MouseWheelMoved, ///< The mouse wheel was scrolled (data in event.mouseWheel) (deprecated) + MouseWheelHorizontalMoved, ///< The mouse wheel was tilted horizontally (data in event.mouseWheelHorizontal) + MouseWheelVerticalMoved, ///< The mouse wheel was scrolled vertically (data in event.mouseWheelVertical) + MouseButtonPressed, ///< A mouse button was pressed (data in event.mouseButton) + MouseButtonReleased, ///< A mouse button was released (data in event.mouseButton) + MouseMoved, ///< The mouse cursor moved (data in event.mouseMove) + MouseEntered, ///< The mouse cursor entered the area of the window (no data) + MouseLeft, ///< The mouse cursor left the area of the window (no data) + JoystickButtonPressed, ///< A joystick button was pressed (data in event.joystickButton) + JoystickButtonReleased, ///< A joystick button was released (data in event.joystickButton) + JoystickMoved, ///< The joystick moved along an axis (data in event.joystickMove) + JoystickConnected, ///< A joystick was connected (data in event.joystickConnect) + JoystickDisconnected, ///< A joystick was disconnected (data in event.joystickConnect) + TouchBegan, ///< A touch event began (data in event.touch) + TouchMoved, ///< A touch moved (data in event.touch) + TouchEnded, ///< A touch event ended (data in event.touch) + SensorChanged, ///< A sensor value changed (data in event.sensor) - Count ///< Keep last -- the total number of event types + Count ///< Keep last -- the total number of event types }; //////////////////////////////////////////////////////////// @@ -204,17 +231,19 @@ public: union { - SizeEvent size; ///< Size event parameters (Event::Resized) - KeyEvent key; ///< Key event parameters (Event::KeyPressed, Event::KeyReleased) - TextEvent text; ///< Text event parameters (Event::TextEntered) - MouseMoveEvent mouseMove; ///< Mouse move event parameters (Event::MouseMoved) - MouseButtonEvent mouseButton; ///< Mouse button event parameters (Event::MouseButtonPressed, Event::MouseButtonReleased) - MouseWheelEvent mouseWheel; ///< Mouse wheel event parameters (Event::MouseWheelMoved) - JoystickMoveEvent joystickMove; ///< Joystick move event parameters (Event::JoystickMoved) - JoystickButtonEvent joystickButton; ///< Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased) - JoystickConnectEvent joystickConnect; ///< Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected) - TouchEvent touch; ///< Touch events parameters (Event::TouchBegan, Event::TouchMoved, Event::TouchEnded) - SensorEvent sensor; ///< Sensor event parameters (Event::SensorChanged) + SizeEvent size; ///< Size event parameters (Event::Resized) + KeyEvent key; ///< Key event parameters (Event::KeyPressed, Event::KeyReleased) + TextEvent text; ///< Text event parameters (Event::TextEntered) + MouseMoveEvent mouseMove; ///< Mouse move event parameters (Event::MouseMoved) + MouseButtonEvent mouseButton; ///< Mouse button event parameters (Event::MouseButtonPressed, Event::MouseButtonReleased) + MouseWheelEvent mouseWheel; ///< Mouse wheel event parameters (Event::MouseWheelMoved) (deprecated) + MouseWheelHorizontalEvent mouseWheelHorizontal; ///< Mouse wheel horizontal event parameters (Event::MouseWheelHorizontalMoved) + MouseWheelVerticalEvent mouseWheelVertical; ///< Mouse wheel vertical event parameters (Event::MouseWheelVerticalMoved) + JoystickMoveEvent joystickMove; ///< Joystick move event parameters (Event::JoystickMoved) + JoystickButtonEvent joystickButton; ///< Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased) + JoystickConnectEvent joystickConnect; ///< Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected) + TouchEvent touch; ///< Touch events parameters (Event::TouchBegan, Event::TouchMoved, Event::TouchEnded) + SensorEvent sensor; ///< Sensor event parameters (Event::SensorChanged) }; }; diff --git a/src/SFML/Window/OSX/SFOpenGLView.mm b/src/SFML/Window/OSX/SFOpenGLView.mm index 348746f73..137b7b0a7 100644 --- a/src/SFML/Window/OSX/SFOpenGLView.mm +++ b/src/SFML/Window/OSX/SFOpenGLView.mm @@ -474,7 +474,7 @@ BOOL isValidTextUnicode(NSEvent* event); if (m_requester != 0) { NSPoint loc = [self cursorPositionFromEvent:theEvent]; - m_requester->mouseWheelScrolledAt([theEvent deltaY], loc.x, loc.y); + m_requester->mouseWheelScrolledAt([theEvent deltaX], [theEvent deltaY], loc.x, loc.y); } // Transmit to non-SFML responder diff --git a/src/SFML/Window/OSX/WindowImplCocoa.hpp b/src/SFML/Window/OSX/WindowImplCocoa.hpp index 600b6fa84..486bf783a 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.hpp +++ b/src/SFML/Window/OSX/WindowImplCocoa.hpp @@ -164,12 +164,13 @@ public: /// /// Send the event to SFML WindowImpl class. /// - /// \param delta scrolling delta + /// \param deltaX horizontal scrolling delta + /// \param deltaY vertical scrolling delta /// \param x mouse x position /// \param y mouse y position /// //////////////////////////////////////////////////////////// - void mouseWheelScrolledAt(float delta, int x, int y); + void mouseWheelScrolledAt(float deltaX, float deltaY, int x, int y); //////////////////////////////////////////////////////////// /// \brief Mouse In Event - called by the cocoa view object diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm index 44fffa72a..9fe17b288 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.mm +++ b/src/SFML/Window/OSX/WindowImplCocoa.mm @@ -370,15 +370,29 @@ void WindowImplCocoa::mouseMovedAt(int x, int y) } //////////////////////////////////////////////////////////// -void WindowImplCocoa::mouseWheelScrolledAt(float delta, int x, int y) +void WindowImplCocoa::mouseWheelScrolledAt(float deltaX, float deltaY, int x, int y) { Event event; + event.type = Event::MouseWheelMoved; - event.mouseWheel.delta = delta; + event.mouseWheel.delta = deltaY; event.mouseWheel.x = x; event.mouseWheel.y = y; scaleOutXY(event.mouseWheel, m_delegate); + pushEvent(event); + event.type = Event::MouseWheelVerticalMoved; + event.mouseWheelVertical.delta = deltaY; + event.mouseWheelVertical.x = x; + event.mouseWheelVertical.y = y; + scaleOutXY(event.mouseWheelVertical, m_delegate); + pushEvent(event); + + event.type = Event::MouseWheelHorizontalMoved; + event.mouseWheelHorizontal.delta = deltaX; + event.mouseWheelHorizontal.x = x; + event.mouseWheelHorizontal.y = y; + scaleOutXY(event.mouseWheelHorizontal, m_delegate); pushEvent(event); } diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index da838e3ff..3be18a97b 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -1154,6 +1154,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) xcb_button_press_event_t* e = reinterpret_cast(windowEvent); // XXX: Why button 8 and 9? + // Because 4 and 5 are the vertical wheel and 6 and 7 are horizontal wheel ;) xcb_button_t button = e->detail; if ((button == XCB_BUTTON_INDEX_1) || (button == XCB_BUTTON_INDEX_2) || @@ -1207,11 +1208,27 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) else if ((button == XCB_BUTTON_INDEX_4) || (button == XCB_BUTTON_INDEX_5)) { Event event; + event.type = Event::MouseWheelMoved; event.mouseWheel.delta = button == XCB_BUTTON_INDEX_4 ? 1 : -1; event.mouseWheel.x = e->event_x; event.mouseWheel.y = e->event_y; pushEvent(event); + + event.type = Event::MouseWheelVerticalMoved; + event.mouseWheelVertical.delta = button == XCB_BUTTON_INDEX_4 ? 1 : -1; + event.mouseWheelVertical.x = e->event_x; + event.mouseWheelVertical.y = e->event_y; + pushEvent(event); + } + else if ((button == 6) || (button == 7)) + { + Event event; + event.type = Event::MouseWheelHorizontalMoved; + event.mouseWheelHorizontal.delta = button == 6 ? 1 : -1; + event.mouseWheelHorizontal.x = e->event_x; + event.mouseWheelHorizontal.y = e->event_y; + pushEvent(event); } break; } diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index d39dfede2..903cc0b27 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -48,6 +48,9 @@ #ifndef XBUTTON2 #define XBUTTON2 0x0002 #endif +#ifndef WM_MOUSEHWHEEL + #define WM_MOUSEHWHEEL 0x020E +#endif #ifndef MAPVK_VK_TO_VSC #define MAPVK_VK_TO_VSC (0) #endif @@ -373,7 +376,7 @@ void WindowImplWin32::requestFocus() // Allow focus stealing only within the same process; compare PIDs of current and foreground window DWORD thisPid = GetWindowThreadProcessId(m_handle, NULL); DWORD foregroundPid = GetWindowThreadProcessId(GetForegroundWindow(), NULL); - + if (thisPid == foregroundPid) { // The window requesting focus belongs to the same process as the current window: steal focus @@ -671,11 +674,41 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) position.y = static_cast(HIWORD(lParam)); ScreenToClient(m_handle, &position); + Int16 delta = static_cast(HIWORD(wParam)); + Event event; - event.type = Event::MouseWheelMoved; - event.mouseWheel.delta = static_cast(HIWORD(wParam)) / 120; - event.mouseWheel.x = position.x; - event.mouseWheel.y = position.y; + + event.type = Event::MouseWheelMoved; + event.mouseWheel.delta = delta / 120; + event.mouseWheel.x = position.x; + event.mouseWheel.y = position.y; + pushEvent(event); + + event.type = Event::MouseWheelVerticalMoved; + event.mouseWheelVertical.delta = static_cast(delta) / 120.f; + event.mouseWheelVertical.x = position.x; + event.mouseWheelVertical.y = position.y; + pushEvent(event); + + break; + } + + // Mouse wheel event + case WM_MOUSEHWHEEL: + { + // Mouse position is in screen coordinates, convert it to window coordinates + POINT position; + position.x = static_cast(LOWORD(lParam)); + position.y = static_cast(HIWORD(lParam)); + ScreenToClient(m_handle, &position); + + Int16 delta = static_cast(HIWORD(wParam)); + + Event event; + event.type = Event::MouseWheelHorizontalMoved; + event.mouseWheelHorizontal.delta = -static_cast(delta) / 120.f; + event.mouseWheelHorizontal.x = position.x; + event.mouseWheelHorizontal.y = position.y; pushEvent(event); break; }