Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x, macOS, Windows, X11] Add stylus inverted/eraser support to InputEventMouseMotion event #62723

Merged
merged 1 commit into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[3.x, macOS, Windows, X11] Add stylus inverted/eraser support to Inpu…
…tEventMouseMotion event
  • Loading branch information
hansemro committed Jul 4, 2022
commit 193d5c11f394b7bc844ed9a9d0a259d62bb0d651
16 changes: 15 additions & 1 deletion core/os/input_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -621,6 +629,7 @@ Ref<InputEvent> 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);

Expand Down Expand Up @@ -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<InputEvent> &p_event) {
Expand Down Expand Up @@ -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);

Expand All @@ -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;
}

////////////////////////////////////////
Expand Down
4 changes: 4 additions & 0 deletions core/os/input_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ class InputEventMouseMotion : public InputEventMouse {
float pressure;
Vector2 relative;
Vector2 speed;
bool pen_inverted;

protected:
static void _bind_methods();
Expand All @@ -398,6 +399,9 @@ class InputEventMouseMotion : public InputEventMouse {
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;

Expand Down
4 changes: 4 additions & 0 deletions doc/classes/InputEventMouseMotion.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
<methods>
</methods>
<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>
Expand Down
2 changes: 2 additions & 0 deletions platform/osx/os_osx.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ class OS_OSX : public OS_Unix {
NSTimeInterval last_warp = 0;
bool ignore_warp = false;

bool last_pen_inverted = false;

Vector<KeyEvent> key_event_buffer;
int key_event_pos;

Expand Down
8 changes: 7 additions & 1 deletion platform/osx/os_osx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -809,9 +809,15 @@ - (void)mouseMoved:(NSEvent *)event {
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());
Expand Down
17 changes: 13 additions & 4 deletions platform/windows/os_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -631,6 +634,8 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Ref<InputEventMouseMotion> 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 {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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;
Expand Down
14 changes: 14 additions & 0 deletions platform/windows/os_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -126,6 +129,7 @@ typedef struct tagORIENTATION {
} ORIENTATION;

typedef struct tagPACKET {
int pkStatus;
int pkNormalPressure;
int pkTangentPressure;
ORIENTATION pkOrientation;
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
12 changes: 10 additions & 2 deletions platform/x11/os_x11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -2579,6 +2581,11 @@ void OS_X11::process_xevents() {
values++;
}

Map<int, bool>::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) {
Expand Down Expand Up @@ -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 :)
Expand Down
2 changes: 2 additions & 0 deletions platform/x11/os_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,13 @@ class OS_X11 : public OS_Unix {
Map<int, Vector2> pen_pressure_range;
Map<int, Vector2> pen_tilt_x_range;
Map<int, Vector2> pen_tilt_y_range;
Map<int, bool> pen_inverted_devices;
XIEventMask all_event_mask;
XIEventMask all_master_event_mask;
Map<int, Vector2> state;
double pressure;
bool pressure_supported;
bool pen_inverted;
Vector2 tilt;
Vector2 mouse_pos_to_filter;
Vector2 relative_motion;
Expand Down