diff options
author | Hansem Ro <hansemro@outlook.com> | 2022-06-19 02:58:24 -0700 |
---|---|---|
committer | Hansem Ro <hansemro@outlook.com> | 2022-07-04 10:36:53 -0700 |
commit | 6dcc9d11319ddb59089fb54551f852249081e027 (patch) | |
tree | ea7e0cb977967dc95ef860d5e5d9237db87b265c | |
parent | d572d3d2abf07ace216fd31f7ace97e4bfc76cc5 (diff) |
[macOS, Windows, X11] Add stylus inverted/eraser support to
InputEventMouseMotion event
-rw-r--r-- | core/input/input_event.cpp | 19 | ||||
-rw-r--r-- | core/input/input_event.h | 4 | ||||
-rw-r--r-- | doc/classes/InputEventMouseMotion.xml | 4 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.cpp | 12 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.h | 2 | ||||
-rw-r--r-- | platform/osx/godot_content_view.h | 1 | ||||
-rw-r--r-- | platform/osx/godot_content_view.mm | 9 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 15 | ||||
-rw-r--r-- | platform/windows/display_server_windows.h | 14 |
9 files changed, 70 insertions, 10 deletions
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 32e025417e..3c104c2c86 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -741,6 +741,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; } @@ -768,6 +776,7 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co mm->set_position(p_xform.xform(get_position() + p_local_ofs)); mm->set_pressure(get_pressure()); + mm->set_pen_inverted(get_pen_inverted()); mm->set_tilt(get_tilt()); mm->set_global_position(get_global_position()); @@ -805,9 +814,9 @@ String InputEventMouseMotion::to_string() { break; } - // Work around the fact vformat can only take 5 substitutions but 6 need to be passed. - String mask_and_position = vformat("button_mask=%s, position=(%s)", button_mask_string, String(get_position())); - return vformat("InputEventMouseMotion: %s, relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s)", mask_and_position, String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt())); + // Work around the fact vformat can only take 5 substitutions but 7 need to be passed. + String mask_and_position_and_relative = vformat("button_mask=%s, position=(%s), relative=(%s)", button_mask_string, String(get_position()), String(get_relative())); + return vformat("InputEventMouseMotion: %s, velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%d)", mask_and_position_and_relative, String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted()); } bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) { @@ -859,6 +868,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); @@ -867,6 +879,7 @@ void InputEventMouseMotion::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pen_inverted"), "set_pen_inverted", "get_pen_inverted"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity"); } diff --git a/core/input/input_event.h b/core/input/input_event.h index 114db46623..59a2df497c 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -272,6 +272,7 @@ class InputEventMouseMotion : public InputEventMouse { float pressure = 0; Vector2 relative; Vector2 velocity; + bool pen_inverted = false; protected: static void _bind_methods(); @@ -283,6 +284,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 ad74204d82..83aad587a5 100644 --- a/doc/classes/InputEventMouseMotion.xml +++ b/doc/classes/InputEventMouseMotion.xml @@ -12,6 +12,10 @@ <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> <members> + <member name="pen_inverted" type="bool" setter="set_pen_inverted" getter="get_pen_inverted" default="false"> + 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. + </member> <member name="pressure" type="float" setter="set_pressure" getter="get_pressure" default="0.0"> Represents the pressure the user puts on the pen. Ranges from [code]0.0[/code] to [code]1.0[/code]. </member> diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 4aec111022..dc70e7c0c7 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -196,6 +196,7 @@ bool DisplayServerX11::_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); @@ -205,7 +206,7 @@ bool DisplayServerX11::_refresh_device_info() { if (!dev->enabled) { continue; } - if (!(dev->use == XIMasterPointer || dev->use == XIFloatingSlave)) { + if (!(dev->use == XISlavePointer || dev->use == XIFloatingSlave)) { continue; } @@ -274,6 +275,7 @@ bool DisplayServerX11::_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); @@ -3438,7 +3440,7 @@ void DisplayServerX11::process_events() { } 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. @@ -3504,6 +3506,11 @@ void DisplayServerX11::process_events() { values++; } + HashMap<int, bool>::Iterator 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) { @@ -3936,6 +3943,7 @@ void DisplayServerX11::process_events() { mm->set_pressure(bool(mouse_get_button_state() & MouseButton::MASK_LEFT) ? 1.0f : 0.0f); } mm->set_tilt(xi.tilt); + mm->set_pen_inverted(xi.pen_inverted); _get_key_modifier_state(event.xmotion.state, mm); mm->set_button_mask((MouseButton)mouse_get_button_state()); diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 4beeddd3a8..57f6fe80da 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -201,10 +201,12 @@ class DisplayServerX11 : public DisplayServer { HashMap<int, Vector2> pen_pressure_range; HashMap<int, Vector2> pen_tilt_x_range; HashMap<int, Vector2> pen_tilt_y_range; + HashMap<int, bool> pen_inverted_devices; XIEventMask all_event_mask; HashMap<int, Vector2> state; double pressure; bool pressure_supported; + bool pen_inverted; Vector2 tilt; Vector2 mouse_pos_to_filter; Vector2 relative_motion; diff --git a/platform/osx/godot_content_view.h b/platform/osx/godot_content_view.h index 7942d716dc..353305aec1 100644 --- a/platform/osx/godot_content_view.h +++ b/platform/osx/godot_content_view.h @@ -52,6 +52,7 @@ bool ime_input_event_in_progress; bool mouse_down_control; bool ignore_momentum_scroll; + bool last_pen_inverted; } - (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor; diff --git a/platform/osx/godot_content_view.mm b/platform/osx/godot_content_view.mm index e96f0a8098..018b90e629 100644 --- a/platform/osx/godot_content_view.mm +++ b/platform/osx/godot_content_view.mm @@ -42,6 +42,7 @@ ime_input_event_in_progress = false; mouse_down_control = false; ignore_momentum_scroll = false; + last_pen_inverted = false; [self updateTrackingAreas]; if (@available(macOS 10.13, *)) { @@ -377,9 +378,15 @@ ds->update_mouse_pos(wd, mpos); mm->set_position(wd.mouse_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(last_pen_inverted); + } else if (subtype == NSEventSubtypeTabletProximity) { + // Check if using the eraser end of pen only on proximity event. + last_pen_inverted = [event pointingDeviceType] == NSPointingDeviceTypeEraser; + mm->set_pen_inverted(last_pen_inverted); } mm->set_global_position(wd.mouse_pos); mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity()); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 998b0882b3..03d0d0e0bd 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -2490,6 +2490,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA windows[window_id].last_tilt = Vector2(); } + windows[window_id].last_pen_inverted = packet.pkStatus & TPS_INVERT; + POINT coords; GetCursorPos(&coords); ScreenToClient(windows[window_id].hWnd, &coords); @@ -2508,6 +2510,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_pressure(windows[window_id].last_pressure); mm->set_tilt(windows[window_id].last_tilt); + mm->set_pen_inverted(windows[window_id].last_pen_inverted); mm->set_button_mask(last_button_state); @@ -2640,6 +2643,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA if ((pen_info.penMask & PEN_MASK_TILT_X) && (pen_info.penMask & PEN_MASK_TILT_Y)) { mm->set_tilt(Vector2((float)pen_info.tiltX / 90, (float)pen_info.tiltY / 90)); } + mm->set_pen_inverted(pen_info.penFlags & (PEN_FLAG_INVERTED | PEN_FLAG_ERASER)); mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0); mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0); @@ -2742,14 +2746,17 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } else { windows[window_id].last_tilt = Vector2(); windows[window_id].last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f; + windows[window_id].last_pen_inverted = false; } } else { windows[window_id].last_tilt = Vector2(); windows[window_id].last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f; + windows[window_id].last_pen_inverted = false; } mm->set_pressure(windows[window_id].last_pressure); mm->set_tilt(windows[window_id].last_tilt); + mm->set_pen_inverted(windows[window_id].last_pen_inverted); mm->set_button_mask(last_button_state); @@ -3360,8 +3367,8 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const if ((p_new_driver == "wintab") && wintab_available) { wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc); wd.wtlc.lcOptions |= CXO_MESSAGES; - wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; - wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE; + wd.wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; + wd.wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE; wd.wtlc.lcPktMode = 0; wd.wtlc.lcOutOrgX = 0; wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX; @@ -3484,8 +3491,8 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, if ((tablet_get_current_driver() == "wintab") && wintab_available) { wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc); wd.wtlc.lcOptions |= CXO_MESSAGES; - wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; - wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE; + wd.wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; + wd.wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE; wd.wtlc.lcPktMode = 0; wd.wtlc.lcOutOrgX = 0; wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX; diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index fc89517774..0429bed3a0 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -82,10 +82,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; @@ -137,6 +140,7 @@ typedef struct tagORIENTATION { } ORIENTATION; typedef struct tagPACKET { + int pkStatus; int pkNormalPressure; int pkTangentPressure; ORIENTATION pkOrientation; @@ -158,6 +162,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 @@ -357,11 +369,13 @@ class DisplayServerWindows : public DisplayServer { 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; HBITMAP hBitmap; //DIB section for layered window uint8_t *dib_data = nullptr; |