mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-05 21:57:20 +00:00
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:
parent
1c94dda072
commit
955f86fc9e
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user