Add pressure and input device (mouse/stylus/eraser) info to mouse events

This is a first step to implement #610 and #710
This commit is contained in:
David Capello 2016-04-20 15:44:15 -03:00
parent 1c94dda072
commit 955f86fc9e
4 changed files with 122 additions and 13 deletions

View File

@ -41,6 +41,14 @@ namespace she {
TouchMagnify,
};
enum InputDevice {
UnknownDevice,
MouseDevice,
MultitouchDevice, // Multitouch device with finger gestures
StylusDevice, // Pen/stylus device
EraserDevice, // Inverted-stylus device
};
enum MouseButton {
NoneButton,
LeftButton,
@ -57,7 +65,10 @@ namespace she {
m_unicodeChar(0),
m_repeat(0),
m_preciseWheel(false),
m_button(NoneButton) {
m_device(UnknownDevice),
m_button(NoneButton),
m_magnification(0.0),
m_pressure(0.0) {
}
Type type() const { return m_type; }
@ -73,10 +84,13 @@ namespace she {
// We suppose that if we are receiving precise scrolling deltas,
// it means that the user is using a touch-like surface (trackpad,
// magic mouse scrolling, touch wacom tablet, etc.)
// TODO change this with the new InputDevice::MultitouchDevice
bool preciseWheel() const { return m_preciseWheel; }
InputDevice device() const { return m_device; }
MouseButton button() const { return m_button; }
double magnification() const { return m_magnification; }
double pressure() const { return m_pressure; }
void setType(Type type) { m_type = type; }
void setDisplay(Display* display) { m_display = display; }
@ -89,8 +103,10 @@ namespace she {
void setPosition(const gfx::Point& pos) { m_position = pos; }
void setWheelDelta(const gfx::Point& delta) { m_wheelDelta = delta; }
void setPreciseWheel(bool precise) { m_preciseWheel = precise; }
void setDevice(InputDevice device) { m_device = device; }
void setButton(MouseButton button) { m_button = button; }
void setMagnification(double magnification) { m_magnification = magnification; }
void setPressure(double pressure) { m_pressure = pressure; }
private:
Type m_type;
@ -103,8 +119,14 @@ namespace she {
gfx::Point m_position;
gfx::Point m_wheelDelta;
bool m_preciseWheel;
InputDevice m_device;
MouseButton m_button;
// For TouchMagnify event
double m_magnification;
// Pressure of stylus used in mouse-like events
double m_pressure;
};
} // namespace she

View File

@ -19,12 +19,14 @@
typedef UINT (API* WTInfoW_Func)(UINT, UINT, LPVOID);
typedef HCTX (API* WTOpenW_Func)(HWND, LPLOGCONTEXTW, BOOL);
typedef BOOL (API* WTClose_Func)(HCTX);
typedef BOOL (API* WTPacket_Func)(HCTX, UINT, LPVOID);
namespace she {
static WTInfoW_Func WTInfo;
static WTOpenW_Func WTOpen;
static WTClose_Func WTClose;
static WTPacket_Func WTPacket;
PenAPI::PenAPI()
: m_wintabLib(nullptr)
@ -40,18 +42,25 @@ PenAPI::~PenAPI()
m_wintabLib = nullptr;
}
HCTX PenAPI::attachDisplay(HWND hwnd)
HCTX PenAPI::open(HWND hwnd)
{
if (!m_wintabLib && !loadWintab())
return nullptr;
LOGCONTEXTW logctx;
memset(&logctx, 0, sizeof(LOGCONTEXTW));
logctx.lcOptions |= CXO_SYSTEM;
UINT infoRes = WTInfo(WTI_DEFSYSCTX, 0, &logctx);
ASSERT(infoRes == sizeof(LOGCONTEXTW));
ASSERT(logctx.lcOptions & CXO_SYSTEM);
logctx.lcOptions |= CXO_SYSTEM;
logctx.lcOptions =
CXO_SYSTEM |
CXO_MESSAGES |
CXO_CSRMESSAGES;
logctx.lcPktData = PACKETDATA;
logctx.lcPktMode = PACKETMODE;
logctx.lcMoveMask = PACKETDATA;
HCTX ctx = WTOpen(hwnd, &logctx, TRUE);
if (!ctx) {
LOG("Error attaching pen to display\n");
@ -62,7 +71,7 @@ HCTX PenAPI::attachDisplay(HWND hwnd)
return ctx;
}
void PenAPI::detachDisplay(HCTX ctx)
void PenAPI::close(HCTX ctx)
{
if (ctx) {
ASSERT(m_wintabLib);
@ -71,6 +80,11 @@ void PenAPI::detachDisplay(HCTX ctx)
}
}
bool PenAPI::packet(HCTX ctx, UINT serial, LPVOID packet)
{
return (WTPacket(ctx, serial, packet) ? true: false);
}
bool PenAPI::loadWintab()
{
ASSERT(!m_wintabLib);
@ -84,7 +98,8 @@ bool PenAPI::loadWintab()
WTInfo = base::get_dll_proc<WTInfoW_Func>(m_wintabLib, "WTInfoW");
WTOpen = base::get_dll_proc<WTOpenW_Func>(m_wintabLib, "WTOpenW");
WTClose = base::get_dll_proc<WTClose_Func>(m_wintabLib, "WTClose");
if (!WTInfo || !WTOpen || !WTClose) {
WTPacket = base::get_dll_proc<WTPacket_Func>(m_wintabLib, "WTPacket");
if (!WTInfo || !WTOpen || !WTClose || !WTPacket) {
LOG("wintab32.dll does not contain all required functions\n");
return false;
}

View File

@ -13,15 +13,22 @@
#include <windows.h>
#include "wacom/wintab.h"
#define PACKETDATA (PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE)
#define PACKETMODE (PK_BUTTONS)
#include "wacom/pktdef.h"
namespace she {
// Wintab API wrapper
// Read http://www.wacomeng.com/windows/docs/Wintab_v140.htm for more information.
class PenAPI {
public:
PenAPI();
~PenAPI();
HCTX attachDisplay(HWND hwnd);
void detachDisplay(HCTX ctx);
HCTX open(HWND hwnd);
void close(HCTX ctx);
bool packet(HCTX ctx, UINT serial, LPVOID packet);
private:
bool loadWintab();

View File

@ -41,11 +41,13 @@ namespace she {
, m_restoredSize(0, 0)
, m_isCreated(false)
, m_hasMouse(false)
, m_captureMouse(false) {
, m_captureMouse(false)
, m_hpenctx(nullptr)
, m_device(Event::UnknownDevice)
, m_pressure(0.0) {
registerClass();
m_hwnd = createHwnd(this, width, height);
m_hcursor = nullptr;
m_hpenctx = nullptr;
m_scale = scale;
// This flag is used to avoid calling T::resizeImpl() when we
@ -55,13 +57,13 @@ namespace she {
// Attach Wacom context
m_hpenctx = static_cast<WindowSystem*>(she::instance())
->penApi().attachDisplay(m_hwnd);
->penApi().open(m_hwnd);
}
~WinWindow() {
if (m_hpenctx)
static_cast<WindowSystem*>(she::instance())
->penApi().detachDisplay(m_hpenctx);
->penApi().close(m_hpenctx);
}
void queueEvent(Event& ev) {
@ -323,6 +325,11 @@ namespace she {
_TrackMouseEvent(&tme);
}
if (m_device != Event::UnknownDevice) {
ev.setDevice(m_device);
ev.setPressure(m_pressure);
}
ev.setType(Event::MouseMove);
queueEvent(ev);
break;
@ -353,6 +360,12 @@ namespace she {
msg == WM_LBUTTONDOWN ? Event::LeftButton:
msg == WM_RBUTTONDOWN ? Event::RightButton:
msg == WM_MBUTTONDOWN ? Event::MiddleButton: Event::NoneButton);
if (m_device != Event::UnknownDevice) {
ev.setDevice(m_device);
ev.setPressure(m_pressure);
}
queueEvent(ev);
break;
}
@ -370,6 +383,12 @@ namespace she {
msg == WM_LBUTTONUP ? Event::LeftButton:
msg == WM_RBUTTONUP ? Event::RightButton:
msg == WM_MBUTTONUP ? Event::MiddleButton: Event::NoneButton);
if (m_device != Event::UnknownDevice) {
ev.setDevice(m_device);
ev.setPressure(m_pressure);
}
queueEvent(ev);
// Avoid popup menu for scrollbars
@ -585,6 +604,48 @@ namespace she {
return result;
}
case WT_PROXIMITY: {
bool entering_ctx = (LOWORD(lparam) ? true: false);
if (!entering_ctx)
m_device = Event::UnknownDevice;
break;
}
case WT_CSRCHANGE: { // From Wintab 1.1
auto& api = static_cast<WindowSystem*>(she::instance())->penApi();
UINT serial = wparam;
HCTX ctx = (HCTX)lparam;
PACKET packet;
if (api.packet(ctx, serial, &packet)) {
if (packet.pkCursor == 2 || packet.pkCursor == 5)
m_device = Event::EraserDevice;
else
m_device = Event::StylusDevice;
}
else
m_device = Event::UnknownDevice;
}
case WT_PACKET: {
auto& api = static_cast<WindowSystem*>(she::instance())->penApi();
UINT serial = wparam;
HCTX ctx = (HCTX)lparam;
PACKET packet;
if (api.packet(ctx, serial, &packet)) {
m_pressure = packet.pkNormalPressure / 1000.0; // TODO get the maximum value
if (packet.pkCursor == 2 || packet.pkCursor == 5)
m_device = Event::EraserDevice;
else
m_device = Event::StylusDevice;
}
else
m_device = Event::UnknownDevice;
break;
}
}
LRESULT result = FALSE;
@ -679,13 +740,17 @@ namespace she {
mutable HWND m_hwnd;
HCURSOR m_hcursor;
HCTX m_hpenctx; // Wacom Pen context
gfx::Size m_clientSize;
gfx::Size m_restoredSize;
int m_scale;
bool m_isCreated;
bool m_hasMouse;
bool m_captureMouse;
// Wintab API data
HCTX m_hpenctx;
Event::InputDevice m_device;
double m_pressure;
};
} // namespace she