summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/os/input_event.cpp34
-rw-r--r--core/os/input_event.h9
-rw-r--r--doc/classes/InputEventMouseMotion.xml8
-rw-r--r--platform/osx/os_osx.mm5
-rw-r--r--platform/windows/os_windows.cpp121
-rw-r--r--platform/windows/os_windows.h68
-rw-r--r--platform/x11/os_x11.cpp75
-rw-r--r--platform/x11/os_x11.h3
8 files changed, 318 insertions, 5 deletions
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 30fca0c155..381ba9d010 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -557,10 +557,31 @@ InputEventMouseButton::InputEventMouseButton() {
////////////////////////////////////////////
+void InputEventMouseMotion::set_tilt(const Vector2 &p_tilt) {
+
+ tilt = p_tilt;
+}
+
+Vector2 InputEventMouseMotion::get_tilt() const {
+
+ return tilt;
+}
+
+void InputEventMouseMotion::set_pressure(float p_pressure) {
+
+ pressure = p_pressure;
+}
+
+float InputEventMouseMotion::get_pressure() const {
+
+ return pressure;
+}
+
void InputEventMouseMotion::set_relative(const Vector2 &p_relative) {
relative = p_relative;
}
+
Vector2 InputEventMouseMotion::get_relative() const {
return relative;
@@ -570,6 +591,7 @@ void InputEventMouseMotion::set_speed(const Vector2 &p_speed) {
speed = p_speed;
}
+
Vector2 InputEventMouseMotion::get_speed() const {
return speed;
@@ -590,6 +612,8 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
mm->set_modifiers_from_event(this);
mm->set_position(l);
+ mm->set_pressure(get_pressure());
+ mm->set_tilt(get_tilt());
mm->set_global_position(g);
mm->set_button_mask(get_button_mask());
@@ -665,17 +689,27 @@ bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
void InputEventMouseMotion::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_tilt", "tilt"), &InputEventMouseMotion::set_tilt);
+ ClassDB::bind_method(D_METHOD("get_tilt"), &InputEventMouseMotion::get_tilt);
+
+ 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_relative", "relative"), &InputEventMouseMotion::set_relative);
ClassDB::bind_method(D_METHOD("get_relative"), &InputEventMouseMotion::get_relative);
ClassDB::bind_method(D_METHOD("set_speed", "speed"), &InputEventMouseMotion::set_speed);
ClassDB::bind_method(D_METHOD("get_speed"), &InputEventMouseMotion::get_speed);
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "pressure"), "set_pressure", "get_pressure");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed");
}
InputEventMouseMotion::InputEventMouseMotion() {
+
+ pressure = 0;
}
////////////////////////////////////////
diff --git a/core/os/input_event.h b/core/os/input_event.h
index 28658e3865..14649502ee 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -351,6 +351,9 @@ public:
class InputEventMouseMotion : public InputEventMouse {
GDCLASS(InputEventMouseMotion, InputEventMouse);
+
+ Vector2 tilt;
+ float pressure;
Vector2 relative;
Vector2 speed;
@@ -358,6 +361,12 @@ protected:
static void _bind_methods();
public:
+ void set_tilt(const Vector2 &p_tilt);
+ Vector2 get_tilt() const;
+
+ void set_pressure(float p_pressure);
+ float get_pressure() 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 fab4cc0fb9..cb89a746bf 100644
--- a/doc/classes/InputEventMouseMotion.xml
+++ b/doc/classes/InputEventMouseMotion.xml
@@ -4,7 +4,7 @@
Input event type for mouse motion events.
</brief_description>
<description>
- Contains mouse motion information. Supports relative, absolute positions and speed. See [method Node._input].
+ Contains mouse and pen motion information. Supports relative, absolute positions and speed. See [method Node._input].
</description>
<tutorials>
<link>https://docs.godotengine.org/en/latest/tutorials/inputs/mouse_and_input_coordinates.html</link>
@@ -18,6 +18,12 @@
<member name="speed" type="Vector2" setter="set_speed" getter="get_speed" default="Vector2( 0, 0 )">
The mouse speed in pixels per second.
</member>
+ <member name="pressure" type="float" setter="set_pressure" getter="get_pressure">
+ Represents the pressure the user puts on the pen. Ranges from [code]0.0[/code] to [code]1.0[/code].
+ </member>
+ <member name="tilt" type="Vector2" setter="set_tilt" getter="get_tilt">
+ Represents the angles of tilt of the pen. Positive X-coordinate value indicates a tilt to the right. Positive Y-coordinate value indicates a tilt toward the user. Ranges from [code]-1.0[/code] to [code]1.0[/code] for both axes.
+ </member>
</members>
<constants>
</constants>
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 15885e1266..ba3ac9862e 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -709,6 +709,11 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
const CGFloat backingScaleFactor = [[event window] backingScaleFactor];
const Vector2 pos = get_mouse_pos([event locationInWindow], backingScaleFactor);
mm->set_position(pos);
+ mm->set_pressure([event pressure]);
+ if ([event subtype] == NSTabletPointEventSubtype) {
+ const NSPoint p = [event tilt];
+ mm->set_tilt(Vector2(p.x, p.y));
+ }
mm->set_global_position(pos);
mm->set_speed(OS_OSX::singleton->input->get_last_mouse_speed());
Vector2 relativeMotion = Vector2();
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 55d667c101..c4cd8e068c 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -70,6 +70,10 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
#define WM_TOUCH 576
#endif
+#ifndef WM_POINTERUPDATE
+#define WM_POINTERUPDATE 0x0245
+#endif
+
typedef struct {
int count;
int screen;
@@ -192,6 +196,9 @@ BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) {
}
}
+GetPointerTypePtr OS_Windows::win8p_GetPointerType = NULL;
+GetPointerPenInfoPtr OS_Windows::win8p_GetPointerPenInfo = NULL;
+
void OS_Windows::initialize_debugging() {
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
@@ -481,6 +488,113 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
delete[] lpb;
} break;
+ case WM_POINTERUPDATE: {
+ if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
+ break;
+ }
+
+ if (!win8p_GetPointerType || !win8p_GetPointerPenInfo) {
+ break;
+ }
+
+ uint32_t pointer_id = LOWORD(wParam);
+ POINTER_INPUT_TYPE pointer_type = PT_POINTER;
+ if (!win8p_GetPointerType(pointer_id, &pointer_type)) {
+ break;
+ }
+
+ if (pointer_type != PT_PEN) {
+ break;
+ }
+
+ POINTER_PEN_INFO pen_info;
+ if (!win8p_GetPointerPenInfo(pointer_id, &pen_info)) {
+ break;
+ }
+
+ if (input->is_emulating_mouse_from_touch()) {
+ // Universal translation enabled; ignore OS translation
+ LPARAM extra = GetMessageExtraInfo();
+ if (IsTouchEvent(extra)) {
+ break;
+ }
+ }
+
+ if (outside) {
+ //mouse enter
+
+ if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
+ main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
+
+ CursorShape c = cursor_shape;
+ cursor_shape = CURSOR_MAX;
+ set_cursor_shape(c);
+ outside = false;
+
+ //Once-Off notification, must call again....
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hWnd;
+ tme.dwHoverTime = HOVER_DEFAULT;
+ TrackMouseEvent(&tme);
+ }
+
+ // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode.
+ if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED)
+ break;
+
+ Ref<InputEventMouseMotion> mm;
+ mm.instance();
+
+ mm->set_pressure(pen_info.pressure ? (float)pen_info.pressure / 1024 : 0);
+ mm->set_tilt(Vector2(pen_info.tiltX ? (float)pen_info.tiltX / 90 : 0, pen_info.tiltY ? (float)pen_info.tiltY / 90 : 0));
+
+ mm->set_control((wParam & MK_CONTROL) != 0);
+ mm->set_shift((wParam & MK_SHIFT) != 0);
+ mm->set_alt(alt_mem);
+
+ mm->set_button_mask(last_button_state);
+
+ mm->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+ mm->set_global_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+
+ if (mouse_mode == MOUSE_MODE_CAPTURED) {
+
+ Point2i c(video_mode.width / 2, video_mode.height / 2);
+ old_x = c.x;
+ old_y = c.y;
+
+ if (mm->get_position() == c) {
+ center = c;
+ return 0;
+ }
+
+ Point2i ncenter = mm->get_position();
+ center = ncenter;
+ POINT pos = { (int)c.x, (int)c.y };
+ ClientToScreen(hWnd, &pos);
+ SetCursorPos(pos.x, pos.y);
+ }
+
+ input->set_mouse_position(mm->get_position());
+ mm->set_speed(input->get_last_mouse_speed());
+
+ if (old_invalid) {
+
+ old_x = mm->get_position().x;
+ old_y = mm->get_position().y;
+ old_invalid = false;
+ }
+
+ mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y)));
+ old_x = mm->get_position().x;
+ old_y = mm->get_position().y;
+ if (window_has_focus && main_loop)
+ input->parse_input_event(mm);
+
+ return 0; //Pointer event handled return 0 to avoid duplicate WM_MOUSEMOVE event
+ } break;
case WM_MOUSEMOVE: {
if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
break;
@@ -3256,6 +3370,13 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
was_maximized = false;
console_visible = IsWindowVisible(GetConsoleWindow());
+ //Note: Functions for pen input, available on Windows 8+
+ HMODULE user32_lib = LoadLibraryW(L"user32.dll");
+ if (user32_lib) {
+ win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
+ win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
+ }
+
hInstance = _hInstance;
pressrc = 0;
old_invalid = true;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index b0e665e574..ce279fb033 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -56,6 +56,71 @@
#include <windows.h>
#include <windowsx.h>
+#ifndef POINTER_STRUCTURES
+
+#define POINTER_STRUCTURES
+
+typedef DWORD POINTER_INPUT_TYPE;
+typedef UINT32 POINTER_FLAGS;
+typedef UINT32 PEN_FLAGS;
+typedef UINT32 PEN_MASK;
+
+enum tagPOINTER_INPUT_TYPE {
+ PT_POINTER = 0x00000001,
+ PT_TOUCH = 0x00000002,
+ PT_PEN = 0x00000003,
+ PT_MOUSE = 0x00000004,
+ PT_TOUCHPAD = 0x00000005
+};
+
+typedef enum tagPOINTER_BUTTON_CHANGE_TYPE {
+ POINTER_CHANGE_NONE,
+ POINTER_CHANGE_FIRSTBUTTON_DOWN,
+ POINTER_CHANGE_FIRSTBUTTON_UP,
+ POINTER_CHANGE_SECONDBUTTON_DOWN,
+ POINTER_CHANGE_SECONDBUTTON_UP,
+ POINTER_CHANGE_THIRDBUTTON_DOWN,
+ POINTER_CHANGE_THIRDBUTTON_UP,
+ POINTER_CHANGE_FOURTHBUTTON_DOWN,
+ POINTER_CHANGE_FOURTHBUTTON_UP,
+ POINTER_CHANGE_FIFTHBUTTON_DOWN,
+ POINTER_CHANGE_FIFTHBUTTON_UP,
+} POINTER_BUTTON_CHANGE_TYPE;
+
+typedef struct tagPOINTER_INFO {
+ POINTER_INPUT_TYPE pointerType;
+ UINT32 pointerId;
+ UINT32 frameId;
+ POINTER_FLAGS pointerFlags;
+ HANDLE sourceDevice;
+ HWND hwndTarget;
+ POINT ptPixelLocation;
+ POINT ptHimetricLocation;
+ POINT ptPixelLocationRaw;
+ POINT ptHimetricLocationRaw;
+ DWORD dwTime;
+ UINT32 historyCount;
+ INT32 InputData;
+ DWORD dwKeyStates;
+ UINT64 PerformanceCount;
+ POINTER_BUTTON_CHANGE_TYPE ButtonChangeType;
+} POINTER_INFO;
+
+typedef struct tagPOINTER_PEN_INFO {
+ POINTER_INFO pointerInfo;
+ PEN_FLAGS penFlags;
+ PEN_MASK penMask;
+ UINT32 pressure;
+ UINT32 rotation;
+ INT32 tiltX;
+ INT32 tiltY;
+} POINTER_PEN_INFO;
+
+#endif
+
+typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type);
+typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info);
+
typedef struct {
BYTE bWidth; // Width, in pixels, of the image
BYTE bHeight; // Height, in pixels, of the image
@@ -77,6 +142,9 @@ typedef struct {
class JoypadWindows;
class OS_Windows : public OS {
+ static GetPointerTypePtr win8p_GetPointerType;
+ static GetPointerPenInfoPtr win8p_GetPointerPenInfo;
+
enum {
KEY_EVENT_BUFFER_SIZE = 512
};
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 694aea7462..c695d657e7 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -83,6 +83,12 @@
#define XINPUT_CLIENT_VERSION_MAJOR 2
#define XINPUT_CLIENT_VERSION_MINOR 2
+#define VALUATOR_ABSX 0
+#define VALUATOR_ABSY 1
+#define VALUATOR_PRESSURE 2
+#define VALUATOR_TILTX 3
+#define VALUATOR_TILTY 4
+
static const double abs_resolution_mult = 10000.0;
static const double abs_resolution_range_mult = 10.0;
@@ -665,6 +671,15 @@ bool OS_X11::refresh_device_info() {
int range_min_y = 0;
int range_max_x = 0;
int range_max_y = 0;
+ int pressure_resolution = 0;
+ int pressure_min = 0;
+ int pressure_max = 0;
+ int tilt_resolution_x = 0;
+ int tilt_resolution_y = 0;
+ int tilt_range_min_x = 0;
+ int tilt_range_min_y = 0;
+ int tilt_range_max_x = 0;
+ int tilt_range_max_y = 0;
for (int j = 0; j < dev->num_classes; j++) {
#ifdef TOUCH_ENABLED
if (dev->classes[j]->type == XITouchClass && ((XITouchClassInfo *)dev->classes[j])->mode == XIDirectTouch) {
@@ -674,16 +689,28 @@ bool OS_X11::refresh_device_info() {
if (dev->classes[j]->type == XIValuatorClass) {
XIValuatorClassInfo *class_info = (XIValuatorClassInfo *)dev->classes[j];
- if (class_info->number == 0 && class_info->mode == XIModeAbsolute) {
+ if (class_info->number == VALUATOR_ABSX && class_info->mode == XIModeAbsolute) {
resolution_x = class_info->resolution;
range_min_x = class_info->min;
range_max_x = class_info->max;
absolute_mode = true;
- } else if (class_info->number == 1 && class_info->mode == XIModeAbsolute) {
+ } else if (class_info->number == VALUATOR_ABSY && class_info->mode == XIModeAbsolute) {
resolution_y = class_info->resolution;
range_min_y = class_info->min;
range_max_y = class_info->max;
absolute_mode = true;
+ } else if (class_info->number == VALUATOR_PRESSURE && class_info->mode == XIModeAbsolute) {
+ pressure_resolution = class_info->resolution;
+ pressure_min = class_info->min;
+ pressure_max = class_info->max;
+ } else if (class_info->number == VALUATOR_TILTX && class_info->mode == XIModeAbsolute) {
+ tilt_resolution_x = class_info->resolution;
+ tilt_range_min_x = class_info->min;
+ tilt_range_max_x = class_info->max;
+ } else if (class_info->number == VALUATOR_TILTY && class_info->mode == XIModeAbsolute) {
+ tilt_resolution_y = class_info->resolution;
+ tilt_range_min_y = class_info->min;
+ tilt_range_max_y = class_info->max;
}
}
}
@@ -703,6 +730,18 @@ bool OS_X11::refresh_device_info() {
xi.absolute_devices[dev->deviceid] = Vector2(abs_resolution_mult / resolution_x, abs_resolution_mult / resolution_y);
print_verbose("XInput: Absolute pointing device: " + String(dev->name));
}
+
+ if (pressure_resolution <= 0) {
+ pressure_resolution = (pressure_max - pressure_min);
+ }
+ if (tilt_resolution_x <= 0) {
+ tilt_resolution_x = (tilt_range_max_x - tilt_range_min_x);
+ }
+ if (tilt_resolution_y <= 0) {
+ tilt_resolution_y = (tilt_range_max_y - tilt_range_min_y);
+ }
+ xi.pressure = 0;
+ xi.pen_devices[dev->deviceid] = Vector3(pressure_resolution, tilt_resolution_x, tilt_resolution_y);
}
XIFreeDeviceInfo(info);
@@ -2095,14 +2134,39 @@ void OS_X11::process_xevents() {
double rel_x = 0.0;
double rel_y = 0.0;
+ double pressure = 0.0;
+ double tilt_x = 0.0;
+ double tilt_y = 0.0;
- if (XIMaskIsSet(raw_event->valuators.mask, 0)) {
+ if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_ABSX)) {
rel_x = *values;
values++;
}
- if (XIMaskIsSet(raw_event->valuators.mask, 1)) {
+ if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_ABSY)) {
rel_y = *values;
+ values++;
+ }
+
+ if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_PRESSURE)) {
+ pressure = *values;
+ values++;
+ }
+
+ if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTX)) {
+ tilt_x = *values;
+ values++;
+ }
+
+ if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTY)) {
+ tilt_y = *values;
+ }
+
+ Map<int, Vector3>::Element *pen_info = xi.pen_devices.find(device_id);
+ if (pen_info) {
+ Vector3 mult = pen_info->value();
+ if (mult.x != 0.0) xi.pressure = pressure / mult.x;
+ if ((mult.y != 0.0) && (mult.z != 0.0)) xi.tilt = Vector2(tilt_x / mult.y, tilt_y / mult.z);
}
// https://bugs.freedesktop.org/show_bug.cgi?id=71609
@@ -2417,6 +2481,9 @@ void OS_X11::process_xevents() {
Ref<InputEventMouseMotion> mm;
mm.instance();
+ mm->set_pressure(xi.pressure);
+ mm->set_tilt(xi.tilt);
+
// Make the absolute position integral so it doesn't look _too_ weird :)
Point2i posi(pos);
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index e6c2effacf..a5576f4402 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -131,9 +131,12 @@ class OS_X11 : public OS_Unix {
int opcode;
Vector<int> touch_devices;
Map<int, Vector2> absolute_devices;
+ Map<int, Vector3> pen_devices;
XIEventMask all_event_mask;
XIEventMask all_master_event_mask;
Map<int, Vector2> state;
+ double pressure;
+ Vector2 tilt;
Vector2 mouse_pos_to_filter;
Vector2 relative_motion;
Vector2 raw_pos;