From 193d5c11f394b7bc844ed9a9d0a259d62bb0d651 Mon Sep 17 00:00:00 2001 From: Hansem Ro Date: Sat, 18 Jun 2022 04:27:02 -0700 Subject: [PATCH] [3.x, macOS, Windows, X11] Add stylus inverted/eraser support to InputEventMouseMotion event --- core/os/input_event.cpp | 16 +++++++++++++++- core/os/input_event.h | 4 ++++ doc/classes/InputEventMouseMotion.xml | 4 ++++ platform/osx/os_osx.h | 2 ++ platform/osx/os_osx.mm | 8 +++++++- platform/windows/os_windows.cpp | 17 +++++++++++++---- platform/windows/os_windows.h | 14 ++++++++++++++ platform/x11/os_x11.cpp | 12 ++++++++++-- platform/x11/os_x11.h | 2 ++ 9 files changed, 71 insertions(+), 8 deletions(-) diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index e47ca668499..6f4e83fbf51 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -590,6 +590,14 @@ float InputEventMouseMotion::get_pressure() const { return pressure; } +void InputEventMouseMotion::set_pen_inverted(bool p_inverted) { + pen_inverted = p_inverted; +} + +bool InputEventMouseMotion::get_pen_inverted() const { + return pen_inverted; +} + void InputEventMouseMotion::set_relative(const Vector2 &p_relative) { relative = p_relative; } @@ -621,6 +629,7 @@ Ref InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co mm->set_position(l); mm->set_pressure(get_pressure()); + mm->set_pen_inverted(get_pen_inverted()); mm->set_tilt(get_tilt()); mm->set_global_position(g); @@ -653,7 +662,7 @@ String InputEventMouseMotion::as_text() const { button_mask_string = itos(get_button_mask()); break; } - return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + "), pressure=(" + rtos(get_pressure()) + "), tilt=(" + String(get_tilt()) + ")"; + return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + "), pressure=(" + rtos(get_pressure()) + "), tilt=(" + String(get_tilt()) + "), pen_inverted=(" + rtos(get_pen_inverted()) + ")"; } bool InputEventMouseMotion::accumulate(const Ref &p_event) { @@ -701,6 +710,9 @@ void InputEventMouseMotion::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventMouseMotion::set_pressure); ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventMouseMotion::get_pressure); + ClassDB::bind_method(D_METHOD("set_pen_inverted", "pen_inverted"), &InputEventMouseMotion::set_pen_inverted); + ClassDB::bind_method(D_METHOD("get_pen_inverted"), &InputEventMouseMotion::get_pen_inverted); + ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative); ClassDB::bind_method(D_METHOD("get_relative"), &InputEventMouseMotion::get_relative); @@ -709,12 +721,14 @@ void InputEventMouseMotion::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "pressure"), "set_pressure", "get_pressure"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pen_inverted"), "set_pen_inverted", "get_pen_inverted"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed"); } InputEventMouseMotion::InputEventMouseMotion() { pressure = 0; + pen_inverted = false; } //////////////////////////////////////// diff --git a/core/os/input_event.h b/core/os/input_event.h index 0593d8f10c5..977f389ca98 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -387,6 +387,7 @@ class InputEventMouseMotion : public InputEventMouse { float pressure; Vector2 relative; Vector2 speed; + bool pen_inverted; protected: static void _bind_methods(); @@ -398,6 +399,9 @@ public: void set_pressure(float p_pressure); float get_pressure() const; + void set_pen_inverted(bool p_inverted); + bool get_pen_inverted() const; + void set_relative(const Vector2 &p_relative); Vector2 get_relative() const; diff --git a/doc/classes/InputEventMouseMotion.xml b/doc/classes/InputEventMouseMotion.xml index 84e2ea24f55..58669645fe6 100644 --- a/doc/classes/InputEventMouseMotion.xml +++ b/doc/classes/InputEventMouseMotion.xml @@ -14,6 +14,10 @@ + + Returns [code]true[/code] when using the eraser end of a stylus pen. + [b]Note:[/b] This property is implemented on Linux, macOS and Windows. + Represents the pressure the user puts on the pen. Ranges from [code]0.0[/code] to [code]1.0[/code]. diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 5b02153ce76..af5a879d6eb 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -74,6 +74,8 @@ public: NSTimeInterval last_warp = 0; bool ignore_warp = false; + bool last_pen_inverted = false; + Vector key_event_buffer; int key_event_pos; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 4bae3488402..a7bff06bec5 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -809,9 +809,15 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { const Vector2 pos = get_mouse_pos(mpos); mm->set_position(pos); mm->set_pressure([event pressure]); - if ([event subtype] == NSEventSubtypeTabletPoint) { + NSEventSubtype subtype = [event subtype]; + if (subtype == NSEventSubtypeTabletPoint) { const NSPoint p = [event tilt]; mm->set_tilt(Vector2(p.x, p.y)); + mm->set_pen_inverted(OS_OSX::singleton->last_pen_inverted); + } else if (subtype == NSEventSubtypeTabletProximity) { + // Check if using the eraser end of pen only on proximity event. + OS_OSX::singleton->last_pen_inverted = [event pointingDeviceType] == NSPointingDeviceTypeEraser; + mm->set_pen_inverted(OS_OSX::singleton->last_pen_inverted); } mm->set_global_position(pos); mm->set_speed(OS_OSX::singleton->input->get_last_mouse_speed()); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 46ac93ef8ef..3ec2b5caa04 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -490,6 +490,8 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) last_tilt = Vector2(); } + last_pen_inverted = packet.pkStatus & TPS_INVERT; + POINT coords; GetCursorPos(&coords); ScreenToClient(hWnd, &coords); @@ -504,6 +506,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) mm->set_shift(GetKeyState(VK_SHIFT) < 0); mm->set_alt(alt_mem); + mm->set_pen_inverted(last_pen_inverted); mm->set_pressure(last_pressure); mm->set_tilt(last_tilt); @@ -631,6 +634,8 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) Ref mm; mm.instance(); + mm->set_pen_inverted(pen_info.penFlags & (PEN_FLAG_INVERTED | PEN_FLAG_ERASER)); + if (pen_info.penMask & PEN_MASK_PRESSURE) { mm->set_pressure((float)pen_info.pressure / 1024); } else { @@ -742,14 +747,17 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } else { last_tilt = Vector2(); last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f; + last_pen_inverted = false; } } else { last_tilt = Vector2(); last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f; + last_pen_inverted = false; } mm->set_pressure(last_pressure); mm->set_tilt(last_tilt); + mm->set_pen_inverted(last_pen_inverted); mm->set_button_mask(last_button_state); @@ -1478,8 +1486,8 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int if ((get_current_tablet_driver() == "wintab") && wintab_available) { wintab_WTInfo(WTI_DEFSYSCTX, 0, &wtlc); wtlc.lcOptions |= CXO_MESSAGES; - wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; - wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE; + wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; + wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE; wtlc.lcPktMode = 0; wtlc.lcOutOrgX = 0; wtlc.lcOutExtX = wtlc.lcInExtX; @@ -1507,6 +1515,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int last_pressure = 0; last_pressure_update = 0; last_tilt = Vector2(); + last_pen_inverted = false; #if defined(OPENGL_ENABLED) @@ -3823,8 +3832,8 @@ void OS_Windows::set_current_tablet_driver(const String &p_driver) { if ((p_driver == "wintab") && wintab_available) { wintab_WTInfo(WTI_DEFSYSCTX, 0, &wtlc); wtlc.lcOptions |= CXO_MESSAGES; - wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; - wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE; + wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; + wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE; wtlc.lcPktMode = 0; wtlc.lcOutOrgX = 0; wtlc.lcOutExtX = wtlc.lcInExtX; diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 549b9f0e1f9..1b26c2c7f34 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -71,10 +71,13 @@ #define DVC_ROTATION 18 #define CXO_MESSAGES 0x0004 +#define PK_STATUS 0x0002 #define PK_NORMAL_PRESSURE 0x0400 #define PK_TANGENT_PRESSURE 0x0800 #define PK_ORIENTATION 0x1000 +#define TPS_INVERT 0x0010 /* 1.1 */ + typedef struct tagLOGCONTEXTW { WCHAR lcName[40]; UINT lcOptions; @@ -126,6 +129,7 @@ typedef struct tagORIENTATION { } ORIENTATION; typedef struct tagPACKET { + int pkStatus; int pkNormalPressure; int pkTangentPressure; ORIENTATION pkOrientation; @@ -147,6 +151,14 @@ typedef UINT32 POINTER_FLAGS; typedef UINT32 PEN_FLAGS; typedef UINT32 PEN_MASK; +#ifndef PEN_FLAG_INVERTED +#define PEN_FLAG_INVERTED 0x00000002 +#endif + +#ifndef PEN_FLAG_ERASER +#define PEN_FLAG_ERASER 0x00000004 +#endif + #ifndef PEN_MASK_PRESSURE #define PEN_MASK_PRESSURE 0x00000001 #endif @@ -272,11 +284,13 @@ class OS_Windows : public OS { int min_pressure; int max_pressure; bool tilt_supported; + bool pen_inverted = false; bool block_mm = false; int last_pressure_update; float last_pressure; Vector2 last_tilt; + bool last_pen_inverted = false; enum { KEY_EVENT_BUFFER_SIZE = 512 diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 9a27989b778..6cee4acd4f0 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -660,6 +660,7 @@ bool OS_X11::refresh_device_info() { xi.absolute_devices.clear(); xi.touch_devices.clear(); + xi.pen_inverted_devices.clear(); int dev_count; XIDeviceInfo *info = XIQueryDevice(x11_display, XIAllDevices, &dev_count); @@ -669,7 +670,7 @@ bool OS_X11::refresh_device_info() { if (!dev->enabled) { continue; } - if (!(dev->use == XIMasterPointer || dev->use == XIFloatingSlave)) { + if (!(dev->use == XISlavePointer || dev->use == XIFloatingSlave)) { continue; } @@ -738,6 +739,7 @@ bool OS_X11::refresh_device_info() { xi.pen_pressure_range[dev->deviceid] = Vector2(pressure_min, pressure_max); xi.pen_tilt_x_range[dev->deviceid] = Vector2(tilt_x_min, tilt_x_max); xi.pen_tilt_y_range[dev->deviceid] = Vector2(tilt_y_min, tilt_y_max); + xi.pen_inverted_devices[dev->deviceid] = (bool)strstr(dev->name, "eraser"); } XIFreeDeviceInfo(info); @@ -2513,7 +2515,7 @@ void OS_X11::process_xevents() { } break; case XI_RawMotion: { XIRawEvent *raw_event = (XIRawEvent *)event_data; - int device_id = raw_event->deviceid; + int device_id = raw_event->sourceid; // Determine the axis used (called valuators in XInput for some forsaken reason) // Mask is a bitmask indicating which axes are involved. @@ -2579,6 +2581,11 @@ void OS_X11::process_xevents() { values++; } + Map::Element *pen_inverted = xi.pen_inverted_devices.find(device_id); + if (pen_inverted) { + xi.pen_inverted = pen_inverted->value(); + } + // https://bugs.freedesktop.org/show_bug.cgi?id=71609 // http://lists.libsdl.org/pipermail/commits-libsdl.org/2015-June/000282.html if (raw_event->time == xi.last_relative_time && rel_x == xi.relative_motion.x && rel_y == xi.relative_motion.y) { @@ -2922,6 +2929,7 @@ void OS_X11::process_xevents() { } else { mm->set_pressure((get_mouse_button_state() & (1 << (BUTTON_LEFT - 1))) ? 1.0f : 0.0f); } + mm->set_pen_inverted(xi.pen_inverted); mm->set_tilt(xi.tilt); // Make the absolute position integral so it doesn't look _too_ weird :) diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 35507e6d2ec..2445f1f5573 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -133,11 +133,13 @@ class OS_X11 : public OS_Unix { Map pen_pressure_range; Map pen_tilt_x_range; Map pen_tilt_y_range; + Map pen_inverted_devices; XIEventMask all_event_mask; XIEventMask all_master_event_mask; Map state; double pressure; bool pressure_supported; + bool pen_inverted; Vector2 tilt; Vector2 mouse_pos_to_filter; Vector2 relative_motion;