Skip to content

Commit

Permalink
Finally got around testing, debugging, and fixing touch input.
Browse files Browse the repository at this point in the history
This commit completes touch input implementation for Win32. Please give it a spin! :)

Note that this does *not* implement pen support, only touch.
  • Loading branch information
MarioLiebisch committed Dec 25, 2016
1 parent 8f19126 commit ea02814
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 24 deletions.
29 changes: 19 additions & 10 deletions src/SFML/Window/Win32/InputImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
Expand Down Expand Up @@ -35,6 +35,7 @@
#define _WIN32_WINNT 0x0501
#include <SFML/Window/Window.hpp>
#include <SFML/Window/Win32/InputImpl.hpp>
#include <SFML/Window/Win32/WindowImplWin32.hpp>
#include <windows.h>


Expand Down Expand Up @@ -229,26 +230,34 @@ void InputImpl::setMousePosition(const Vector2i& position, const Window& relativ


////////////////////////////////////////////////////////////
bool InputImpl::isTouchDown(unsigned int /*finger*/)
bool InputImpl::isTouchDown(unsigned int finger)
{
// Not applicable
return false;
return WindowImplWin32::isTouchDown(finger);
}


////////////////////////////////////////////////////////////
Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/)
Vector2i InputImpl::getTouchPosition(unsigned int finger)
{
// Not applicable
return Vector2i();
return WindowImplWin32::getTouchPosition(finger);
}


////////////////////////////////////////////////////////////
Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/, const Window& /*relativeTo*/)
Vector2i InputImpl::getTouchPosition(unsigned int finger, const Window& relativeTo)
{
// Not applicable
return Vector2i();
WindowHandle handle = relativeTo.getSystemHandle();
Vector2i pos;

if (handle && WindowImplWin32::isTouchDown(finger))
{
pos = WindowImplWin32::getTouchPosition(finger);
POINT point = { pos.x, pos.y };
ScreenToClient(handle, &point);
pos.x = point.x;
pos.y = point.y;
}
return pos;
}

} // namespace priv
Expand Down
82 changes: 70 additions & 12 deletions src/SFML/Window/Win32/WindowImplWin32.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
Expand Down Expand Up @@ -116,6 +116,9 @@ namespace
{
if (touchIDs[i] == id)
return i;
}
for (int i = 0; i < 10; ++i)
{
if (touchIDs[i] == -1)
{
touchIDs[i] = id;
Expand Down Expand Up @@ -204,7 +207,9 @@ m_keyRepeatEnabled(true),
m_lastSize (0, 0),
m_resizing (false),
m_surrogate (0),
m_mouseInside (false)
m_mouseInside (false),
m_fullscreen (false),
m_cursorGrabbed (false)
{
// Load User32, if necessary (very first window/control only)
if (windowCount + externCount == 0) {
Expand Down Expand Up @@ -240,7 +245,9 @@ m_keyRepeatEnabled(true),
m_lastSize (mode.width, mode.height),
m_resizing (false),
m_surrogate (0),
m_mouseInside (false)
m_mouseInside (false),
m_fullscreen (style & Style::Fullscreen),
m_cursorGrabbed (m_fullscreen)
{
// Load User32, if necessary (very first window/control only)
if (windowCount + externCount == 0) {
Expand Down Expand Up @@ -277,8 +284,7 @@ m_mouseInside (false)
}

// In windowed mode, adjust width and height so that window will have the requested client area
bool fullscreen = (style & Style::Fullscreen) != 0;
if (!fullscreen)
if (!m_fullscreen)
{
RECT rectangle = {0, 0, width, height};
AdjustWindowRect(&rectangle, win32Style, false);
Expand All @@ -294,7 +300,7 @@ m_mouseInside (false)
setSize(Vector2u(mode.width, mode.height));

// Switch to fullscreen if requested
if (fullscreen)
if (m_fullscreen)
switchToFullscreen(mode);

// Try to prepare touch events, if necessary
Expand Down Expand Up @@ -383,6 +389,9 @@ Vector2i WindowImplWin32::getPosition() const
void WindowImplWin32::setPosition(const Vector2i& position)
{
SetWindowPos(m_handle, NULL, position.x, position.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);

if(m_cursorGrabbed)
grabCursor(true);
}


Expand Down Expand Up @@ -469,6 +478,14 @@ void WindowImplWin32::setMouseCursorVisible(bool visible)
}


////////////////////////////////////////////////////////////
void WindowImplWin32::setMouseCursorGrabbed(bool grabbed)
{
m_cursorGrabbed = grabbed;
grabCursor(m_cursorGrabbed);
}


////////////////////////////////////////////////////////////
void WindowImplWin32::setKeyRepeatEnabled(bool enabled)
{
Expand Down Expand Up @@ -591,6 +608,23 @@ void WindowImplWin32::setTracking(bool track)
}


////////////////////////////////////////////////////////////
void WindowImplWin32::grabCursor(bool grabbed)
{
if (grabbed)
{
RECT rect;
GetClientRect(m_handle, &rect);
MapWindowPoints(m_handle, NULL, reinterpret_cast<LPPOINT>(&rect), 2);
ClipCursor(&rect);
}
else
{
ClipCursor(NULL);
}
}


////////////////////////////////////////////////////////////
void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
{
Expand Down Expand Up @@ -642,6 +676,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
event.size.width = m_lastSize.x;
event.size.height = m_lastSize.y;
pushEvent(event);

// Restore/update cursor grabbing
grabCursor(m_cursorGrabbed);
}
break;
}
Expand All @@ -650,6 +687,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
case WM_ENTERSIZEMOVE:
{
m_resizing = true;
grabCursor(false);
break;
}

Expand All @@ -671,6 +709,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
event.size.height = m_lastSize.y;
pushEvent(event);
}

// Restore/update cursor grabbing
grabCursor(m_cursorGrabbed);
break;
}

Expand All @@ -688,6 +729,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Gain focus event
case WM_SETFOCUS:
{
// Restore cursor grabbing
grabCursor(m_cursorGrabbed);

Event event;
event.type = Event::GainedFocus;
pushEvent(event);
Expand All @@ -697,6 +741,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Lost focus event
case WM_KILLFOCUS:
{
// Ungrab the cursor
grabCursor(false);

Event event;
event.type = Event::LostFocus;
pushEvent(event);
Expand Down Expand Up @@ -1025,25 +1072,25 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
event.touch.finger = index;
point.x = TOUCH_COORD_TO_PIXEL(events[i].x);
point.y = TOUCH_COORD_TO_PIXEL(events[i].y);
ScreenToClient(m_handle, &point);
event.touch.x = point.x;
event.touch.y = point.y;

POINT cpoint = point;
ScreenToClient(m_handle, &cpoint);
event.touch.x = cpoint.x;
event.touch.y = cpoint.y;

if (events[i].dwFlags & TOUCHEVENTF_DOWN) {
event.type = Event::TouchBegan;
pushEvent(event);

// Prevent initial move event
touches[index] = point;
err() << "down: " << events[i].dwID << ", x: " << point.x << ", y: " << point.y << std::endl;
}
if (events[i].dwFlags & TOUCHEVENTF_UP) {
event.type = Event::TouchEnded;
pushEvent(event);

// Remove the stored ID
touchIDs[index] = -1;
err() << "up: " << events[i].dwID << ", x: " << point.x << ", y: " << point.y << std::endl;
}
if (events[i].dwFlags & TOUCHEVENTF_MOVE) {
// Only handle real movement
Expand All @@ -1052,7 +1099,6 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
touches[index] = point;
event.type = Event::TouchMoved;
pushEvent(event);
err() << "moved: " << events[i].dwID << ", x: " << point.x << ", y: " << point.y << std::endl;
}
}

Expand Down Expand Up @@ -1261,6 +1307,18 @@ void WindowImplWin32::prepareTouch()
RegisterTouchWindow(m_handle, 0);
}

////////////////////////////////////////////////////////////
bool WindowImplWin32::isTouchDown(unsigned int finger)
{
return touchIDs[finger] != -1;
}

////////////////////////////////////////////////////////////
Vector2i WindowImplWin32::getTouchPosition(unsigned int finger)
{
return Vector2i(touches[finger].x, touches[finger].y);
}

} // namespace priv

} // namespace sf
Expand Down
47 changes: 45 additions & 2 deletions src/SFML/Window/Win32/WindowImplWin32.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
Expand Down Expand Up @@ -145,6 +145,14 @@ class WindowImplWin32 : public WindowImpl
////////////////////////////////////////////////////////////
virtual void setMouseCursorVisible(bool visible);

////////////////////////////////////////////////////////////
/// \brief Grab or release the mouse cursor
///
/// \param grabbed True to enable, false to disable
///
////////////////////////////////////////////////////////////
virtual void setMouseCursorGrabbed(bool grabbed);

////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
Expand All @@ -168,6 +176,26 @@ class WindowImplWin32 : public WindowImpl
////////////////////////////////////////////////////////////
virtual bool hasFocus() const;

////////////////////////////////////////////////////////////
/// \brief Get global touch state for a finger
///
/// \param finger Finger index
///
/// \return True, if the finger is active
///
////////////////////////////////////////////////////////////
static bool isTouchDown(unsigned int finger);

////////////////////////////////////////////////////////////
/// \brief Get global touch coordinates for a finger
///
/// \param finger Finger index
///
/// \return Touch position
///
////////////////////////////////////////////////////////////
static Vector2i getTouchPosition(unsigned int finger);

protected:

////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -216,6 +244,19 @@ class WindowImplWin32 : public WindowImpl
////////////////////////////////////////////////////////////
void setTracking(bool track);

////////////////////////////////////////////////////////////
/// \brief Grab or release the mouse cursor
///
/// This is not to be confused with setMouseCursorGrabbed.
/// Here m_cursorGrabbed is not modified; it is used,
/// for example, to release the cursor when switching to
/// another application.
///
/// \param grabbed True to enable, false to disable
///
////////////////////////////////////////////////////////////
void grabCursor(bool grabbed);

////////////////////////////////////////////////////////////
/// \brief Convert a Win32 virtual key code to a SFML key code
///
Expand Down Expand Up @@ -244,7 +285,7 @@ class WindowImplWin32 : public WindowImpl
/// \brief Helper function to prepare and enable touch handling
///
////////////////////////////////////////////////////////////
void WindowImplWin32::prepareTouch();
void prepareTouch();

////////////////////////////////////////////////////////////
// Member data
Expand All @@ -258,6 +299,8 @@ class WindowImplWin32 : public WindowImpl
bool m_resizing; ///< Is the window being resized?
Uint16 m_surrogate; ///< First half of the surrogate pair, in case we're receiving a Unicode character in two events
bool m_mouseInside; ///< Mouse is inside the window?
bool m_fullscreen; ///< Is the window fullscreen?
bool m_cursorGrabbed; ///< Is the mouse cursor trapped?
};

} // namespace priv
Expand Down

0 comments on commit ea02814

Please sign in to comment.