Skip to content

Commit

Permalink
Merge pull request #62212 from hansemro/eraser-detect-4
Browse files Browse the repository at this point in the history
Add inversion/eraser-end property for tablet pens
  • Loading branch information
akien-mga authored Jul 4, 2022
2 parents b4644e2 + 6dcc9d1 commit 344b427
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 10 deletions.
19 changes: 16 additions & 3 deletions core/input/input_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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());

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

Expand All @@ -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");
}
Expand Down
4 changes: 4 additions & 0 deletions core/input/input_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ class InputEventMouseMotion : public InputEventMouse {
float pressure = 0;
Vector2 relative;
Vector2 velocity;
bool pen_inverted = false;

protected:
static void _bind_methods();
Expand All @@ -283,6 +284,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 @@ -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>
Expand Down
12 changes: 10 additions & 2 deletions platform/linuxbsd/display_server_x11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -3484,7 +3486,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.
Expand Down Expand Up @@ -3550,6 +3552,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) {
Expand Down Expand Up @@ -3984,6 +3991,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());
Expand Down
2 changes: 2 additions & 0 deletions platform/linuxbsd/display_server_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions platform/osx/godot_content_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 8 additions & 1 deletion platform/osx/godot_content_view.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ - (id)init {
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, *)) {
Expand Down Expand Up @@ -377,9 +378,15 @@ - (void)mouseMoved:(NSEvent *)event {
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());
Expand Down
15 changes: 11 additions & 4 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);

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

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

typedef struct tagPACKET {
int pkStatus;
int pkNormalPressure;
int pkTangentPressure;
ORIENTATION pkOrientation;
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 344b427

Please sign in to comment.