mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-06 03:39:51 +00:00
Use WM_POINTER on Windows 8 platform
First version. Still touch support is not working as expected. The pen, mouse, and trackpad are working correctly. (Even the eraser tip of the pen is recognized.)
This commit is contained in:
parent
7c4f811fc7
commit
8c9b8910c1
@ -405,8 +405,9 @@ if(WIN32)
|
||||
kernel32 user32 gdi32 comdlg32 ole32 winmm
|
||||
shlwapi psapi wininet comctl32 dbghelp)
|
||||
|
||||
# Windows XP is the minimum supported platform.
|
||||
add_definitions(-D_WIN32_WINNT=0x0501 -DWINVER=0x0501)
|
||||
# Windows Vista is the minimum supported platform but we're defining
|
||||
# Windows 10 to get the all constant/structure definitions.
|
||||
add_definitions(-D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00)
|
||||
|
||||
# We need Unicode support
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
|
@ -122,6 +122,7 @@ if(USE_SKIA_BACKEND)
|
||||
skia/skia_window_win.cpp
|
||||
win/pen.cpp
|
||||
win/vk.cpp
|
||||
win/winapi.cpp
|
||||
win/window.cpp
|
||||
win/window_dde.cpp)
|
||||
elseif(APPLE)
|
||||
|
@ -7,3 +7,4 @@ back-ends:
|
||||
* Previous version were using Allegro 4 (it still uses Allegro 4 on Linux)
|
||||
* Now we use our own implementation on Windows and macOS to handle
|
||||
events, and [Skia](https://skia.org/) to render graphics.
|
||||
* Minimum Windows platform: Windows Vista
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
// Copyright (C) 2012-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#include "she/common/system.h"
|
||||
#include "she/win/pen.h"
|
||||
#include "she/win/winapi.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
@ -21,9 +22,8 @@ public:
|
||||
WindowSystem() { }
|
||||
~WindowSystem() { }
|
||||
|
||||
PenAPI& penApi() {
|
||||
return m_penApi;
|
||||
}
|
||||
WinAPI& winApi() { return m_winApi; }
|
||||
PenAPI& penApi() { return m_penApi; }
|
||||
|
||||
bool isKeyPressed(KeyScancode scancode) override {
|
||||
return win_is_key_pressed(scancode);
|
||||
@ -34,6 +34,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
WinAPI m_winApi;
|
||||
PenAPI m_penApi;
|
||||
};
|
||||
|
||||
|
42
src/she/win/winapi.cpp
Normal file
42
src/she/win/winapi.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/win/winapi.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
#define GET_PROC(dll, name) \
|
||||
name = base::get_dll_proc<name##_Func>(dll, #name)
|
||||
|
||||
WinAPI::WinAPI()
|
||||
: EnableMouseInPointer(nullptr)
|
||||
, IsMouseInPointerEnabled(nullptr)
|
||||
, GetPointerInfo(nullptr)
|
||||
, GetPointerPenInfo(nullptr)
|
||||
, m_user32(nullptr)
|
||||
{
|
||||
m_user32 = base::load_dll("user32.dll");
|
||||
if (m_user32) {
|
||||
GET_PROC(m_user32, EnableMouseInPointer);
|
||||
GET_PROC(m_user32, IsMouseInPointerEnabled);
|
||||
GET_PROC(m_user32, GetPointerInfo);
|
||||
GET_PROC(m_user32, GetPointerPenInfo);
|
||||
}
|
||||
}
|
||||
|
||||
WinAPI::~WinAPI()
|
||||
{
|
||||
if (m_user32) {
|
||||
base::unload_dll(m_user32);
|
||||
m_user32 = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace she
|
39
src/she/win/winapi.h
Normal file
39
src/she/win/winapi.h
Normal file
@ -0,0 +1,39 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_WIN_WINAPI_H_INCLUDED
|
||||
#define SHE_WIN_WINAPI_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/dll.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace she {
|
||||
|
||||
typedef BOOL (WINAPI* EnableMouseInPointer_Func)(BOOL fEnable);
|
||||
typedef BOOL (WINAPI* IsMouseInPointerEnabled_Func)(void);
|
||||
typedef BOOL (WINAPI* GetPointerInfo_Func)(UINT32 pointerId, POINTER_INFO* pointerInfo);
|
||||
typedef BOOL (WINAPI* GetPointerPenInfo_Func)(UINT32 pointerId, POINTER_PEN_INFO* penInfo);
|
||||
|
||||
class WinAPI {
|
||||
public:
|
||||
WinAPI();
|
||||
~WinAPI();
|
||||
|
||||
// These functions are availble only since Windows 8
|
||||
EnableMouseInPointer_Func EnableMouseInPointer;
|
||||
IsMouseInPointerEnabled_Func IsMouseInPointerEnabled;
|
||||
GetPointerInfo_Func GetPointerInfo;
|
||||
GetPointerPenInfo_Func GetPointerPenInfo;
|
||||
|
||||
private:
|
||||
base::dll m_user32;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -25,29 +25,57 @@
|
||||
#include "she/win/vk.h"
|
||||
#include "she/win/window_dde.h"
|
||||
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
#endif
|
||||
|
||||
#define SHE_WND_CLASS_NAME L"Aseprite.Window"
|
||||
|
||||
#define MOUSE_TRACE(...)
|
||||
|
||||
// Gets the window client are in absolute/screen coordinates
|
||||
#define ABS_CLIENT_RC(rc) \
|
||||
RECT rc; \
|
||||
GetClientRect(m_hwnd, &rc); \
|
||||
MapWindowPoints(m_hwnd, NULL, (POINT*)&rc, 2)
|
||||
|
||||
// Not yet ready because if we start receiving WM_POINTERDOWN messages
|
||||
// instead of WM_LBUTTONDBLCLK we lost the automatic double-click
|
||||
// messages.
|
||||
#define USE_EnableMouseInPointer 0
|
||||
|
||||
namespace she {
|
||||
|
||||
WinWindow::WinWindow(int width, int height, int scale)
|
||||
: m_hwnd(nullptr)
|
||||
, m_hcursor(nullptr)
|
||||
, m_clientSize(1, 1)
|
||||
, m_restoredSize(0, 0)
|
||||
, m_scale(scale)
|
||||
, m_isCreated(false)
|
||||
, m_translateDeadKeys(false)
|
||||
, m_hasMouse(false)
|
||||
, m_captureMouse(false)
|
||||
, m_customHcursor(false)
|
||||
, m_usePointerApi(false)
|
||||
, m_ignoreMouseMessages(false)
|
||||
, m_lastPointerId(0)
|
||||
, m_capturePointerId(0)
|
||||
, m_hpenctx(nullptr)
|
||||
, m_pointerType(PointerType::Unknown)
|
||||
, m_pressure(0.0)
|
||||
{
|
||||
m_hcursor = nullptr;
|
||||
m_customHcursor = false;
|
||||
m_scale = scale;
|
||||
auto& winApi = system()->winApi();
|
||||
if (winApi.EnableMouseInPointer &&
|
||||
winApi.IsMouseInPointerEnabled &&
|
||||
winApi.GetPointerInfo &&
|
||||
winApi.GetPointerPenInfo) {
|
||||
#if USE_EnableMouseInPointer == 1
|
||||
if (!winApi.IsMouseInPointerEnabled()) {
|
||||
// Prefer pointer messages (WM_POINTER*) since Windows 8 instead
|
||||
// of mouse messages (WM_MOUSE*)
|
||||
winApi.EnableMouseInPointer(TRUE);
|
||||
m_ignoreMouseMessages = (winApi.IsMouseInPointerEnabled() ? true: false);
|
||||
}
|
||||
#endif
|
||||
m_usePointerApi = true;
|
||||
}
|
||||
|
||||
registerClass();
|
||||
|
||||
@ -127,11 +155,23 @@ void WinWindow::setTitle(const std::string& title)
|
||||
void WinWindow::captureMouse()
|
||||
{
|
||||
m_captureMouse = true;
|
||||
m_capturePointerId = m_lastPointerId;
|
||||
|
||||
if (GetCapture() != m_hwnd) {
|
||||
MOUSE_TRACE("SetCapture\n");
|
||||
SetCapture(m_hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::releaseMouse()
|
||||
{
|
||||
m_captureMouse = false;
|
||||
m_capturePointerId = 0;
|
||||
|
||||
if (GetCapture() == m_hwnd) {
|
||||
MOUSE_TRACE("ReleaseCapture\n");
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::setMousePosition(const gfx::Point& position)
|
||||
@ -436,22 +476,23 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
}
|
||||
break;
|
||||
|
||||
// Mouse and Trackpad Messages
|
||||
|
||||
case WM_MOUSEMOVE: {
|
||||
// Adjust capture
|
||||
if (m_captureMouse) {
|
||||
if (GetCapture() != m_hwnd)
|
||||
SetCapture(m_hwnd);
|
||||
}
|
||||
else {
|
||||
if (GetCapture() == m_hwnd)
|
||||
ReleaseCapture();
|
||||
}
|
||||
// If the pointer API is enable, we use WM_POINTERUPDATE instead
|
||||
// of WM_MOUSEMOVE. This check is here because Windows keeps
|
||||
// sending us WM_MOUSEMOVE messages even when we call
|
||||
// EnableMouseInPointer() (mainly when we use Alt+stylus we
|
||||
// receive WM_MOUSEMOVE with the position of the mouse/trackpad
|
||||
// + WM_POINTERUPDATE with the position of the pen)
|
||||
if (m_ignoreMouseMessages)
|
||||
break;
|
||||
|
||||
Event ev;
|
||||
ev.setModifiers(get_modifiers_from_last_win32_message());
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / m_scale,
|
||||
GET_Y_LPARAM(lparam) / m_scale));
|
||||
mouseEvent(lparam, ev);
|
||||
|
||||
MOUSE_TRACE("MOUSEMOVE xy=%d,%d\n",
|
||||
ev.position().x, ev.position().y);
|
||||
|
||||
if (!m_hasMouse) {
|
||||
m_hasMouse = true;
|
||||
@ -459,6 +500,8 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
ev.setType(Event::MouseEnter);
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("-> Event::MouseEnter\n");
|
||||
|
||||
// Track mouse to receive WM_MOUSELEAVE message.
|
||||
TRACKMOUSEEVENT tme;
|
||||
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
@ -486,6 +529,8 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
ev.setType(Event::MouseLeave);
|
||||
ev.setModifiers(get_modifiers_from_last_win32_message());
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("-> Event::MouseLeave\n");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -494,11 +539,8 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_XBUTTONDOWN: {
|
||||
Event ev;
|
||||
mouseEvent(lparam, ev);
|
||||
ev.setType(Event::MouseDown);
|
||||
ev.setModifiers(get_modifiers_from_last_win32_message());
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / m_scale,
|
||||
GET_Y_LPARAM(lparam) / m_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONDOWN ? Event::LeftButton:
|
||||
msg == WM_RBUTTONDOWN ? Event::RightButton:
|
||||
@ -511,8 +553,11 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
ev.setPointerType(m_pointerType);
|
||||
ev.setPressure(m_pressure);
|
||||
}
|
||||
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("BUTTONDOWN xy=%d,%d button=%d\n",
|
||||
ev.position().x, ev.position().y,
|
||||
ev.button());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -521,11 +566,8 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
case WM_MBUTTONUP:
|
||||
case WM_XBUTTONUP: {
|
||||
Event ev;
|
||||
mouseEvent(lparam, ev);
|
||||
ev.setType(Event::MouseUp);
|
||||
ev.setModifiers(get_modifiers_from_last_win32_message());
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / m_scale,
|
||||
GET_Y_LPARAM(lparam) / m_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONUP ? Event::LeftButton:
|
||||
msg == WM_RBUTTONUP ? Event::RightButton:
|
||||
@ -538,9 +580,12 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
ev.setPointerType(m_pointerType);
|
||||
ev.setPressure(m_pressure);
|
||||
}
|
||||
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("BUTTONUP xy=%d,%d button=%d\n",
|
||||
ev.position().x, ev.position().y,
|
||||
ev.button());
|
||||
|
||||
// Avoid popup menu for scrollbars
|
||||
if (msg == WM_RBUTTONUP)
|
||||
return 0;
|
||||
@ -553,11 +598,8 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
case WM_RBUTTONDBLCLK:
|
||||
case WM_XBUTTONDBLCLK: {
|
||||
Event ev;
|
||||
mouseEvent(lparam, ev);
|
||||
ev.setType(Event::MouseDoubleClick);
|
||||
ev.setModifiers(get_modifiers_from_last_win32_message());
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / m_scale,
|
||||
GET_Y_LPARAM(lparam) / m_scale));
|
||||
ev.setButton(
|
||||
msg == WM_LBUTTONDBLCLK ? Event::LeftButton:
|
||||
msg == WM_RBUTTONDBLCLK ? Event::RightButton:
|
||||
@ -570,8 +612,11 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
ev.setPointerType(m_pointerType);
|
||||
ev.setPressure(m_pressure);
|
||||
}
|
||||
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("BUTTONDBLCLK xy=%d,%d button=%d\n",
|
||||
ev.position().x, ev.position().y,
|
||||
ev.button());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -599,8 +644,11 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
(msg == WM_MOUSEHWHEEL ? z: 0),
|
||||
(msg == WM_MOUSEWHEEL ? -z: 0));
|
||||
ev.setWheelDelta(delta);
|
||||
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("MOUSEWHEEL xy=%d,%d delta=%d,%d\n",
|
||||
ev.position().x, ev.position().y,
|
||||
ev.wheelDelta().x, ev.wheelDelta().y);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -646,11 +694,208 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
ev.setWheelDelta(delta);
|
||||
|
||||
SetScrollPos(m_hwnd, bar, 50, FALSE);
|
||||
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("HVSCROLL xy=%d,%d delta=%d,%d\n",
|
||||
ev.position().x, ev.position().y,
|
||||
ev.wheelDelta().x, ev.wheelDelta().y);
|
||||
break;
|
||||
}
|
||||
|
||||
// Pointer API (since Windows 8.0)
|
||||
|
||||
case WM_POINTERCAPTURECHANGED: {
|
||||
MOUSE_TRACE("POINTERCAPTURECHANGED\n");
|
||||
m_capturePointerId = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_POINTERENTER: {
|
||||
POINTER_INFO pi;
|
||||
Event ev;
|
||||
if (!pointerEvent(wparam, lparam, ev, pi))
|
||||
break;
|
||||
|
||||
// Ignore this message because we have captured other pointerId.
|
||||
if (m_capturePointerId &&
|
||||
m_capturePointerId != pi.pointerId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOUSE_TRACE("POINTERENTER id=%d xy=%d,%d\n",
|
||||
pi.pointerId, ev.position().x, ev.position().y);
|
||||
|
||||
#if USE_EnableMouseInPointer == 0
|
||||
// This is necessary to avoid receiving random WM_MOUSEMOVE from
|
||||
// the mouse position when we use Alt+pen tip.
|
||||
// TODO Remove this line when we enable EnableMouseInPointer(TRUE);
|
||||
m_ignoreMouseMessages = true;
|
||||
#endif
|
||||
|
||||
if (!m_hasMouse) {
|
||||
m_hasMouse = true;
|
||||
|
||||
ev.setType(Event::MouseEnter);
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("-> Event::MouseEnter\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_POINTERLEAVE: {
|
||||
UINT32 pointerId = GET_POINTERID_WPARAM(wparam);
|
||||
|
||||
// Ignore this message because we have captured other pointerId.
|
||||
if (m_capturePointerId &&
|
||||
m_capturePointerId != pointerId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOUSE_TRACE("POINTERLEAVE id=%d\n", pointerId);
|
||||
|
||||
#if USE_EnableMouseInPointer == 0
|
||||
m_ignoreMouseMessages = false;
|
||||
#endif
|
||||
|
||||
if (m_hasMouse) {
|
||||
m_hasMouse = false;
|
||||
|
||||
Event ev;
|
||||
ev.setType(Event::MouseLeave);
|
||||
ev.setModifiers(get_modifiers_from_last_win32_message());
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("-> Event::MouseLeave\n");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_POINTERDOWN: {
|
||||
POINTER_INFO pi;
|
||||
Event ev;
|
||||
if (!pointerEvent(wparam, lparam, ev, pi))
|
||||
break;
|
||||
|
||||
// Ignore this message because we have captured other pointerId.
|
||||
if (m_capturePointerId &&
|
||||
m_capturePointerId != pi.pointerId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ev.setType(Event::MouseDown);
|
||||
ev.setButton(
|
||||
pi.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_DOWN ? Event::LeftButton:
|
||||
pi.ButtonChangeType == POINTER_CHANGE_SECONDBUTTON_DOWN ? Event::RightButton:
|
||||
pi.ButtonChangeType == POINTER_CHANGE_THIRDBUTTON_DOWN ? Event::MiddleButton:
|
||||
pi.ButtonChangeType == POINTER_CHANGE_FOURTHBUTTON_DOWN ? Event::X1Button:
|
||||
pi.ButtonChangeType == POINTER_CHANGE_FIFTHBUTTON_DOWN ? Event::X2Button:
|
||||
Event::NoneButton);
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("POINTERDOWN id=%d xy=%d,%d button=%d\n",
|
||||
pi.pointerId, ev.position().x, ev.position().y,
|
||||
ev.button());
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_POINTERUP: {
|
||||
POINTER_INFO pi;
|
||||
Event ev;
|
||||
if (!pointerEvent(wparam, lparam, ev, pi))
|
||||
break;
|
||||
|
||||
// Ignore this message because we have captured other pointerId.
|
||||
if (m_capturePointerId &&
|
||||
m_capturePointerId != pi.pointerId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ev.setType(Event::MouseUp);
|
||||
ev.setButton(
|
||||
pi.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_UP ? Event::LeftButton:
|
||||
pi.ButtonChangeType == POINTER_CHANGE_SECONDBUTTON_UP ? Event::RightButton:
|
||||
pi.ButtonChangeType == POINTER_CHANGE_THIRDBUTTON_UP ? Event::MiddleButton:
|
||||
pi.ButtonChangeType == POINTER_CHANGE_FOURTHBUTTON_UP ? Event::X1Button:
|
||||
pi.ButtonChangeType == POINTER_CHANGE_FIFTHBUTTON_UP ? Event::X2Button:
|
||||
Event::NoneButton);
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("POINTERUP id=%d xy=%d,%d button=%d\n",
|
||||
pi.pointerId, ev.position().x, ev.position().y,
|
||||
ev.button());
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_POINTERUPDATE: {
|
||||
POINTER_INFO pi;
|
||||
Event ev;
|
||||
if (!pointerEvent(wparam, lparam, ev, pi))
|
||||
break;
|
||||
|
||||
// Ignore this message because we have captured other pointerId.
|
||||
if (m_capturePointerId &&
|
||||
m_capturePointerId != pi.pointerId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!m_hasMouse) {
|
||||
m_hasMouse = true;
|
||||
|
||||
ev.setType(Event::MouseEnter);
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("-> Event::MouseEnter\n");
|
||||
}
|
||||
|
||||
ev.setType(Event::MouseMove);
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("POINTERUPDATE id=%d xy=%d,%d\n",
|
||||
pi.pointerId, ev.position().x, ev.position().y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_POINTERWHEEL:
|
||||
case WM_POINTERHWHEEL: {
|
||||
POINTER_INFO pi;
|
||||
Event ev;
|
||||
if (!pointerEvent(wparam, lparam, ev, pi))
|
||||
break;
|
||||
|
||||
// Ignore this message because we have captured other pointerId.
|
||||
if (m_capturePointerId &&
|
||||
m_capturePointerId != pi.pointerId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ev.setType(Event::MouseWheel);
|
||||
|
||||
int z = GET_WHEEL_DELTA_WPARAM(wparam);
|
||||
if (ABS(z) >= WHEEL_DELTA)
|
||||
z /= WHEEL_DELTA;
|
||||
else {
|
||||
// TODO use floating point numbers or something similar
|
||||
// (so we could use: z /= double(WHEEL_DELTA))
|
||||
z = SGN(z);
|
||||
}
|
||||
|
||||
gfx::Point delta(
|
||||
(msg == WM_POINTERHWHEEL ? z: 0),
|
||||
(msg == WM_POINTERWHEEL ? -z: 0));
|
||||
ev.setWheelDelta(delta);
|
||||
queueEvent(ev);
|
||||
|
||||
MOUSE_TRACE("POINTERWHEEL xy=%d,%d delta=%d,%d\n",
|
||||
ev.position().x, ev.position().y,
|
||||
ev.wheelDelta().x, ev.wheelDelta().y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Keyboard Messages
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYDOWN: {
|
||||
int vk = wparam;
|
||||
@ -749,11 +994,10 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
|
||||
case WM_NCHITTEST: {
|
||||
LRESULT result = CallWindowProc(DefWindowProc, m_hwnd, msg, wparam, lparam);
|
||||
gfx::Point pt(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
|
||||
gfx::Point pt(GET_X_LPARAM(lparam),
|
||||
GET_Y_LPARAM(lparam));
|
||||
|
||||
RECT rc;
|
||||
GetClientRect(m_hwnd, &rc);
|
||||
MapWindowPoints(m_hwnd, NULL, (POINT*)&rc, 2);
|
||||
ABS_CLIENT_RC(rc);
|
||||
gfx::Rect area(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
|
||||
|
||||
//LOG("NCHITTEST: %d %d - %d %d %d %d - %s\n", pt.x, pt.y, area.x, area.y, area.w, area.h, area.contains(pt) ? "true": "false");
|
||||
@ -772,6 +1016,8 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Wintab API Messages
|
||||
|
||||
case WT_PROXIMITY: {
|
||||
bool entering_ctx = (LOWORD(lparam) ? true: false);
|
||||
if (!entering_ctx)
|
||||
@ -836,6 +1082,56 @@ LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
return DefWindowProc(m_hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
void WinWindow::mouseEvent(LPARAM lparam, Event& ev)
|
||||
{
|
||||
ev.setModifiers(get_modifiers_from_last_win32_message());
|
||||
ev.setPosition(gfx::Point(
|
||||
GET_X_LPARAM(lparam) / m_scale,
|
||||
GET_Y_LPARAM(lparam) / m_scale));
|
||||
}
|
||||
|
||||
bool WinWindow::pointerEvent(WPARAM wparam, LPARAM lparam,
|
||||
Event& ev, POINTER_INFO& pi)
|
||||
{
|
||||
if (!m_usePointerApi)
|
||||
return false;
|
||||
|
||||
auto& winApi = system()->winApi();
|
||||
if (!winApi.GetPointerInfo(GET_POINTERID_WPARAM(wparam), &pi))
|
||||
return false;
|
||||
|
||||
ABS_CLIENT_RC(rc);
|
||||
|
||||
ev.setModifiers(get_modifiers_from_last_win32_message());
|
||||
ev.setPosition(gfx::Point((pi.ptPixelLocation.x - rc.left) / m_scale,
|
||||
(pi.ptPixelLocation.y - rc.top) / m_scale));
|
||||
|
||||
switch (pi.pointerType) {
|
||||
case PT_MOUSE: {
|
||||
ev.setPointerType(PointerType::Mouse);
|
||||
break;
|
||||
}
|
||||
case PT_TOUCH:
|
||||
case PT_TOUCHPAD: {
|
||||
ev.setPointerType(PointerType::Multitouch);
|
||||
break;
|
||||
}
|
||||
case PT_PEN: {
|
||||
ev.setPointerType(PointerType::Pen);
|
||||
|
||||
POINTER_PEN_INFO ppi;
|
||||
if (winApi.GetPointerPenInfo(pi.pointerId, &ppi)) {
|
||||
if (ppi.penFlags & PEN_FLAG_ERASER)
|
||||
ev.setPointerType(PointerType::Eraser);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_lastPointerId = pi.pointerId;
|
||||
return true;
|
||||
}
|
||||
|
||||
//static
|
||||
void WinWindow::registerClass()
|
||||
{
|
||||
|
@ -54,6 +54,9 @@ namespace she {
|
||||
private:
|
||||
bool setCursor(HCURSOR hcursor, bool custom);
|
||||
LRESULT wndProc(UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
void mouseEvent(LPARAM lparam, Event& ev);
|
||||
bool pointerEvent(WPARAM wparam, LPARAM lparam,
|
||||
Event& ev, POINTER_INFO& pi);
|
||||
|
||||
virtual void onQueueEvent(Event& ev) { }
|
||||
virtual void onResize(const gfx::Size& sz) { }
|
||||
@ -76,6 +79,12 @@ namespace she {
|
||||
bool m_captureMouse;
|
||||
bool m_customHcursor;
|
||||
|
||||
// Windows 8 pointer API
|
||||
bool m_usePointerApi;
|
||||
bool m_ignoreMouseMessages;
|
||||
UINT32 m_lastPointerId;
|
||||
UINT32 m_capturePointerId;
|
||||
|
||||
// Wintab API data
|
||||
HCTX m_hpenctx;
|
||||
PointerType m_pointerType;
|
||||
|
Loading…
x
Reference in New Issue
Block a user