summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2018-02-24 03:04:30 +0100
committerPedro J. Estébanez <pedrojrulez@gmail.com>2018-04-30 19:03:38 +0200
commitde9d40a9537bafa613dc54f2200b7509ad6fa9e3 (patch)
tree746f887af7e07a5e89878500fc713cd5548409ac
parent3a5b25d5b489ad88c2861c9c37b56469580fbf03 (diff)
Implement universal translation of touch to mouse
Now generating mouse events from touch is optional (on by default) and it's performed by `InputDefault` instead of having each OS abstraction doing it. (*) The translation algorithm waits for a touch index to be pressed and tracks it translating its events to mouse events until it is raised, while ignoring other pointers. Furthermore, to avoid an stuck "touch mouse", since not all platforms may report touches raised when the window is unfocused, it checks if touches are still down by the time it's focused again and if so it resets the state of the emulated mouse. *: In the case of Windows, since it already provides touch-to-mouse translation by itself, "echo" mouse events are filtered out to have it working like the rest. On X11 a little hack has been needed to avoid a case of a spurious mouse motion event that is generated during touch interaction. Plus: Improve/fix tracking of current mouse position. ** Summary of changes to settings: ** - `display/window/handheld/emulate_touchscreen` becomes `input/pointing_devices/emulate_touch_from_mouse` - New setting: `input/pointing_devices/emulate_mouse_from_touch`
-rw-r--r--core/os/input.h3
-rw-r--r--core/os/os.cpp2
-rw-r--r--editor/editor_node.cpp2
-rw-r--r--main/input_default.cpp118
-rw-r--r--main/input_default.h15
-rw-r--r--main/main.cpp15
-rw-r--r--platform/android/os_android.cpp49
-rw-r--r--platform/android/os_android.h1
-rw-r--r--platform/iphone/gl_view.mm9
-rw-r--r--platform/iphone/os_iphone.cpp45
-rw-r--r--platform/iphone/os_iphone.h6
-rw-r--r--platform/javascript/os_javascript.cpp35
-rw-r--r--platform/uwp/app.cpp83
-rw-r--r--platform/uwp/app.h1
-rw-r--r--platform/windows/os_windows.cpp39
-rw-r--r--platform/x11/os_x11.cpp17
-rw-r--r--platform/x11/os_x11.h1
-rw-r--r--scene/main/scene_tree.cpp8
18 files changed, 223 insertions, 226 deletions
diff --git a/core/os/input.h b/core/os/input.h
index fca68f27b7..b0d72a6d59 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -117,7 +117,8 @@ public:
void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
- virtual bool is_emulating_touchscreen() const = 0;
+ virtual bool is_emulating_touch_from_mouse() const = 0;
+ virtual bool is_emulating_mouse_from_touch() const = 0;
virtual CursorShape get_default_cursor_shape() = 0;
virtual void set_default_cursor_shape(CursorShape p_shape) = 0;
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 618a4bbac3..854d554b10 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -411,7 +411,7 @@ Error OS::set_cwd(const String &p_cwd) {
bool OS::has_touchscreen_ui_hint() const {
//return false;
- return Input::get_singleton() && Input::get_singleton()->is_emulating_touchscreen();
+ return Input::get_singleton() && Input::get_singleton()->is_emulating_touch_from_mouse();
}
int OS::get_free_static_memory() const {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index c31bec9a1b..45e58d4f01 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -4886,7 +4886,7 @@ EditorNode::EditorNode() {
if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
//only if no touchscreen ui hint, set emulation
- id->set_emulate_touch(false); //just disable just in case
+ id->set_emulate_touch_from_mouse(false); //just disable just in case
}
id->set_custom_mouse_cursor(RES());
}
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 1c73ecf2d2..4f0915a4f3 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -250,6 +250,11 @@ Vector3 InputDefault::get_gyroscope() const {
void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
+ _parse_input_event_impl(p_event, false);
+}
+
+void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated) {
+
_THREAD_SAFE_METHOD_
Ref<InputEventKey> k = p_event;
@@ -273,25 +278,30 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
mouse_button_mask &= ~(1 << (mb->get_button_index() - 1));
}
- if (main_loop && emulate_touch && mb->get_button_index() == 1) {
+ Point2 pos = mb->get_global_position();
+ if (mouse_pos != pos) {
+ set_mouse_position(pos);
+ }
+
+ if (main_loop && emulate_touch_from_mouse && !p_is_emulated && mb->get_button_index() == 1) {
Ref<InputEventScreenTouch> touch_event;
touch_event.instance();
touch_event->set_pressed(mb->is_pressed());
touch_event->set_position(mb->get_position());
main_loop->input_event(touch_event);
}
-
- Point2 pos = mb->get_global_position();
- if (mouse_pos != pos) {
- set_mouse_position(pos);
- }
}
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
- if (main_loop && emulate_touch && mm->get_button_mask() & 1) {
+ Point2 pos = mm->get_global_position();
+ if (mouse_pos != pos) {
+ set_mouse_position(pos);
+ }
+
+ if (main_loop && emulate_touch_from_mouse && !p_is_emulated && mm->get_button_mask() & 1) {
Ref<InputEventScreenDrag> drag_event;
drag_event.instance();
@@ -303,6 +313,58 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
}
}
+ if (emulate_mouse_from_touch) {
+
+ Ref<InputEventScreenTouch> st = p_event;
+
+ if (st.is_valid()) {
+ bool translate = false;
+ if (st->is_pressed()) {
+ if (mouse_from_touch_index == -1) {
+ translate = true;
+ mouse_from_touch_index = st->get_index();
+ }
+ } else {
+ if (st->get_index() == mouse_from_touch_index) {
+ translate = true;
+ mouse_from_touch_index = -1;
+ }
+ }
+
+ if (translate) {
+ Ref<InputEventMouseButton> button_event;
+ button_event.instance();
+
+ button_event->set_position(st->get_position());
+ button_event->set_global_position(st->get_position());
+ button_event->set_pressed(st->is_pressed());
+ button_event->set_button_index(BUTTON_LEFT);
+ if (st->is_pressed()) {
+ button_event->set_button_mask(mouse_button_mask | (1 << BUTTON_LEFT - 1));
+ } else {
+ button_event->set_button_mask(mouse_button_mask & ~(1 << BUTTON_LEFT - 1));
+ }
+
+ _parse_input_event_impl(button_event, true);
+ }
+ }
+
+ Ref<InputEventScreenDrag> sd = p_event;
+
+ if (sd.is_valid() && sd->get_index() == mouse_from_touch_index) {
+ Ref<InputEventMouseMotion> motion_event;
+ motion_event.instance();
+
+ motion_event->set_position(sd->get_position());
+ motion_event->set_global_position(sd->get_position());
+ motion_event->set_relative(sd->get_relative());
+ motion_event->set_speed(sd->get_speed());
+ motion_event->set_button_mask(mouse_button_mask);
+
+ _parse_input_event_impl(motion_event, true);
+ }
+ }
+
Ref<InputEventJoypadButton> jb = p_event;
if (jb.is_valid()) {
@@ -485,14 +547,44 @@ void InputDefault::action_release(const StringName &p_action) {
action_state[p_action] = action;
}
-void InputDefault::set_emulate_touch(bool p_emulate) {
+void InputDefault::set_emulate_touch_from_mouse(bool p_emulate) {
+
+ emulate_touch_from_mouse = p_emulate;
+}
+
+bool InputDefault::is_emulating_touch_from_mouse() const {
+
+ return emulate_touch_from_mouse;
+}
+
+// Calling this whenever the game window is focused helps unstucking the "touch mouse"
+// if the OS or its abstraction class hasn't properly reported that touch pointers raised
+void InputDefault::ensure_touch_mouse_raised() {
+
+ if (mouse_from_touch_index != -1) {
+ mouse_from_touch_index = -1;
+
+ Ref<InputEventMouseButton> button_event;
+ button_event.instance();
+
+ button_event->set_position(mouse_pos);
+ button_event->set_global_position(mouse_pos);
+ button_event->set_pressed(false);
+ button_event->set_button_index(BUTTON_LEFT);
+ button_event->set_button_mask(mouse_button_mask & ~(1 << BUTTON_LEFT - 1));
+
+ _parse_input_event_impl(button_event, true);
+ }
+}
+
+void InputDefault::set_emulate_mouse_from_touch(bool p_emulate) {
- emulate_touch = p_emulate;
+ emulate_mouse_from_touch = p_emulate;
}
-bool InputDefault::is_emulating_touchscreen() const {
+bool InputDefault::is_emulating_mouse_from_touch() const {
- return emulate_touch;
+ return emulate_mouse_from_touch;
}
Input::CursorShape InputDefault::get_default_cursor_shape() {
@@ -529,7 +621,9 @@ void InputDefault::set_mouse_in_window(bool p_in_window) {
InputDefault::InputDefault() {
mouse_button_mask = 0;
- emulate_touch = false;
+ emulate_touch_from_mouse = false;
+ emulate_mouse_from_touch = false;
+ mouse_from_touch_index = -1;
main_loop = NULL;
hat_map_default[HAT_UP].type = TYPE_BUTTON;
diff --git a/main/input_default.h b/main/input_default.h
index 384b04cf41..827c9dbe2a 100644
--- a/main/input_default.h
+++ b/main/input_default.h
@@ -59,7 +59,10 @@ class InputDefault : public Input {
Map<StringName, Action> action_state;
- bool emulate_touch;
+ bool emulate_touch_from_mouse;
+ bool emulate_mouse_from_touch;
+
+ int mouse_from_touch_index;
struct VibrationInfo {
float weak_magnitude;
@@ -175,6 +178,8 @@ private:
void _axis_event(int p_device, int p_axis, float p_value);
float _handle_deadzone(int p_device, int p_axis, float p_value);
+ void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated);
+
public:
virtual bool is_key_pressed(int p_scancode) const;
virtual bool is_mouse_button_pressed(int p_button) const;
@@ -223,8 +228,12 @@ public:
void iteration(float p_step);
- void set_emulate_touch(bool p_emulate);
- virtual bool is_emulating_touchscreen() const;
+ void set_emulate_touch_from_mouse(bool p_emulate);
+ virtual bool is_emulating_touch_from_mouse() const;
+ void ensure_touch_mouse_raised();
+
+ void set_emulate_mouse_from_touch(bool p_emulate);
+ virtual bool is_emulating_mouse_from_touch() const;
virtual CursorShape get_default_cursor_shape();
virtual void set_default_cursor_shape(CursorShape p_shape);
diff --git a/main/main.cpp b/main/main.cpp
index a59ca3da3b..a22ae944a7 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1141,13 +1141,16 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
GLOBAL_DEF("application/config/icon", String());
ProjectSettings::get_singleton()->set_custom_property_info("application/config/icon", PropertyInfo(Variant::STRING, "application/config/icon", PROPERTY_HINT_FILE, "*.png,*.webp"));
- if (bool(GLOBAL_DEF("display/window/handheld/emulate_touchscreen", false))) {
- if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton() && !(editor || project_manager)) {
- //only if no touchscreen ui hint, set emulation
- InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
- if (id)
- id->set_emulate_touch(true);
+ InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
+ if (id) {
+ if (bool(GLOBAL_DEF("input/pointing_devices/emulate_touch_from_mouse", false)) && !(editor || project_manager)) {
+ if (!OS::get_singleton()->has_touchscreen_ui_hint()) {
+ //only if no touchscreen ui hint, set emulation
+ id->set_emulate_touch_from_mouse(true);
+ }
}
+
+ id->set_emulate_mouse_from_touch(bool(GLOBAL_DEF("input/pointing_devices/emulate_mouse_from_touch", true)));
}
MAIN_PRINT("Main: Load Remaps");
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 5557c1de44..fc41adeb76 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -330,17 +330,6 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
if (touch.size()) {
//end all if exist
- {
- Ref<InputEventMouseButton> ev;
- ev.instance();
- ev->set_button_index(BUTTON_LEFT);
- ev->set_button_mask(BUTTON_MASK_LEFT);
- ev->set_pressed(false);
- ev->set_position(touch[0].pos);
- ev->set_global_position(touch[0].pos);
- input->parse_input_event(ev);
- }
-
for (int i = 0; i < touch.size(); i++) {
Ref<InputEventScreenTouch> ev;
@@ -358,21 +347,6 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
touch[i].pos = p_points[i].pos;
}
- {
- //send mouse
- Ref<InputEventMouseButton> ev;
- ev.instance();
- // ev.type = Ref<InputEvent>::MOUSE_BUTTON;
- ev->set_button_index(BUTTON_LEFT);
- ev->set_button_mask(BUTTON_MASK_LEFT);
- ev->set_pressed(true);
- ev->set_position(touch[0].pos);
- ev->set_global_position(touch[0].pos);
- input->set_mouse_position(Point2(touch[0].pos.x, touch[0].pos.y));
- last_mouse = touch[0].pos;
- input->parse_input_event(ev);
- }
-
//send touch
for (int i = 0; i < touch.size(); i++) {
@@ -387,19 +361,6 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
} break;
case 1: { //motion
- if (p_points.size()) {
- //send mouse, should look for point 0?
- Ref<InputEventMouseMotion> ev;
- ev.instance();
- ev->set_button_mask(BUTTON_MASK_LEFT);
- ev->set_position(p_points[0].pos);
- input->set_mouse_position(Point2(ev->get_position().x, ev->get_position().y));
- ev->set_speed(input->get_last_mouse_speed());
- ev->set_relative(p_points[0].pos - last_mouse);
- last_mouse = p_points[0].pos;
- input->parse_input_event(ev);
- }
-
ERR_FAIL_COND(touch.size() != p_points.size());
for (int i = 0; i < touch.size(); i++) {
@@ -432,16 +393,6 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
if (touch.size()) {
//end all if exist
- Ref<InputEventMouseButton> ev;
- ev.instance();
- ev->set_button_index(BUTTON_LEFT);
- ev->set_button_mask(BUTTON_MASK_LEFT);
- ev->set_pressed(false);
- ev->set_position(touch[0].pos);
- ev->set_global_position(touch[0].pos);
- input->set_mouse_position(Point2(touch[0].pos.x, touch[0].pos.y));
- input->parse_input_event(ev);
-
for (int i = 0; i < touch.size(); i++) {
Ref<InputEventScreenTouch> ev;
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 12181b3688..d2457e538d 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -93,7 +93,6 @@ public:
private:
Vector<TouchPos> touch;
- Point2 last_mouse;
GFXInitFunc gfx_init_func;
void *gfx_init_ud;
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index ff95cf6e5f..478a3125af 100644
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -497,7 +497,7 @@ static void clear_touches() {
int tid = get_touch_id(touch);
ERR_FAIL_COND(tid == -1);
CGPoint touchPoint = [touch locationInView:self];
- OSIPhone::get_singleton()->mouse_button(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1, tid == 0);
+ OSIPhone::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
};
};
}
@@ -514,10 +514,9 @@ static void clear_touches() {
continue;
int tid = get_touch_id(touch);
ERR_FAIL_COND(tid == -1);
- int first = get_first_id(touch);
CGPoint touchPoint = [touch locationInView:self];
CGPoint prev_point = [touch previousLocationInView:self];
- OSIPhone::get_singleton()->mouse_move(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, first == tid);
+ OSIPhone::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor);
};
};
}
@@ -533,9 +532,9 @@ static void clear_touches() {
continue;
int tid = get_touch_id(touch);
ERR_FAIL_COND(tid == -1);
- int rem = remove_touch(touch);
+ remove_touch(touch);
CGPoint touchPoint = [touch locationInView:self];
- OSIPhone::get_singleton()->mouse_button(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false, rem == 0);
+ OSIPhone::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
};
};
}
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index 97ebc19335..f618c80a77 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -190,7 +190,7 @@ void OSIPhone::key(uint32_t p_key, bool p_pressed) {
queue_event(ev);
};
-void OSIPhone::mouse_button(int p_idx, int p_x, int p_y, bool p_pressed, bool p_doubleclick, bool p_use_as_mouse) {
+void OSIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_doubleclick) {
if (!GLOBAL_DEF("debug/disable_touch", false)) {
Ref<InputEventScreenTouch> ev;
@@ -202,28 +202,10 @@ void OSIPhone::mouse_button(int p_idx, int p_x, int p_y, bool p_pressed, bool p_
queue_event(ev);
};
- mouse_list.pressed[p_idx] = p_pressed;
-
- if (p_use_as_mouse) {
-
- Ref<InputEventMouseButton> ev;
- ev.instance();
-
- ev->set_position(Vector2(p_x, p_y));
- ev->set_global_position(Vector2(p_x, p_y));
-
- //mouse_list.pressed[p_idx] = p_pressed;
-
- input->set_mouse_position(ev->get_position());
- ev->set_button_index(BUTTON_LEFT);
- ev->set_doubleclick(p_doubleclick);
- ev->set_pressed(p_pressed);
-
- queue_event(ev);
- };
+ touch_list.pressed[p_idx] = p_pressed;
};
-void OSIPhone::mouse_move(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, bool p_use_as_mouse) {
+void OSIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) {
if (!GLOBAL_DEF("debug/disable_touch", false)) {
@@ -234,21 +216,6 @@ void OSIPhone::mouse_move(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_
ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
queue_event(ev);
};
-
- if (p_use_as_mouse) {
- Ref<InputEventMouseMotion> ev;
- ev.instance();
-
- ev->set_position(Vector2(p_x, p_y));
- ev->set_global_position(Vector2(p_x, p_y));
- ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
-
- input->set_mouse_position(ev->get_position());
- ev->set_speed(input->get_last_mouse_speed());
- ev->set_button_mask(BUTTON_LEFT); // pressed
-
- queue_event(ev);
- };
};
void OSIPhone::queue_event(const Ref<InputEvent> &p_event) {
@@ -262,10 +229,10 @@ void OSIPhone::touches_cancelled() {
for (int i = 0; i < MAX_MOUSE_COUNT; i++) {
- if (mouse_list.pressed[i]) {
+ if (touch_list.pressed[i]) {
// send a mouse_up outside the screen
- mouse_button(i, -1, -1, false, false, false);
+ touch_press(i, -1, -1, false, false);
};
};
};
@@ -376,7 +343,7 @@ Point2 OSIPhone::get_mouse_position() const {
int OSIPhone::get_mouse_button_state() const {
- return mouse_list.pressed[0];
+ return 0;
};
void OSIPhone::set_window_title(const String &p_title){};
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index 00d9efb01a..7d73a6fe5c 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -106,7 +106,7 @@ private:
};
};
- MouseList mouse_list;
+ MouseList touch_list;
Vector3 last_accel;
@@ -127,8 +127,8 @@ public:
uint8_t get_orientations() const;
- void mouse_button(int p_idx, int p_x, int p_y, bool p_pressed, bool p_doubleclick, bool p_use_as_mouse);
- void mouse_move(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, bool p_use_as_mouse);
+ void touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_doubleclick);
+ void touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y);
void touches_cancelled();
void key(uint32_t p_key, bool p_pressed);
void set_virtual_keyboard_height(int p_height);
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index a275fb7929..1b5463e40d 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -285,23 +285,6 @@ static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent *
_input->parse_input_event(ev);
}
-
- if (touch_event->touches[lowest_id_index].isChanged) {
-
- Ref<InputEventMouseButton> ev_mouse;
- ev_mouse.instance();
- ev_mouse->set_button_mask(_input->get_mouse_button_mask());
- dom2godot_mod(touch_event, ev_mouse);
-
- const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index];
- ev_mouse->set_position(Point2(first_touch.canvasX, first_touch.canvasY));
- ev_mouse->set_global_position(ev_mouse->get_position());
-
- ev_mouse->set_button_index(BUTTON_LEFT);
- ev_mouse->set_pressed(event_type == EMSCRIPTEN_EVENT_TOUCHSTART);
-
- _input->parse_input_event(ev_mouse);
- }
return true;
}
@@ -327,24 +310,6 @@ static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *t
_input->parse_input_event(ev);
}
-
- if (touch_event->touches[lowest_id_index].isChanged) {
-
- Ref<InputEventMouseMotion> ev_mouse;
- ev_mouse.instance();
- dom2godot_mod(touch_event, ev_mouse);
- ev_mouse->set_button_mask(_input->get_mouse_button_mask());
-
- const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index];
- ev_mouse->set_position(Point2(first_touch.canvasX, first_touch.canvasY));
- ev_mouse->set_global_position(ev_mouse->get_position());
-
- ev_mouse->set_relative(ev_mouse->get_position() - _input->get_mouse_position());
- _input->set_mouse_position(ev_mouse->get_position());
- ev_mouse->set_speed(_input->get_last_mouse_speed());
-
- _input->parse_input_event(ev_mouse);
- }
return true;
}
diff --git a/platform/uwp/app.cpp b/platform/uwp/app.cpp
index 5ff62b38f9..c18aa36402 100644
--- a/platform/uwp/app.cpp
+++ b/platform/uwp/app.cpp
@@ -85,8 +85,7 @@ App::App() :
mWindowHeight(0),
mEglDisplay(EGL_NO_DISPLAY),
mEglContext(EGL_NO_CONTEXT),
- mEglSurface(EGL_NO_SURFACE),
- number_of_contacts(0) {
+ mEglSurface(EGL_NO_SURFACE) {
}
// The first method called when the IFrameworkView is being created.
@@ -271,48 +270,44 @@ void App::pointer_event(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Cor
last_touch_y[screen_touch->get_index()] = pos.Y;
os->input_event(screen_touch);
- if (number_of_contacts > 1)
- return;
+ } else {
- }; // fallthrought of sorts
-
- Ref<InputEventMouseButton> mouse_button;
- mouse_button.instance();
- mouse_button->set_device(0);
- mouse_button->set_pressed(p_pressed);
- mouse_button->set_button_index(but);
- mouse_button->set_position(Vector2(pos.X, pos.Y));
- mouse_button->set_global_position(Vector2(pos.X, pos.Y));
-
- if (p_is_wheel) {
- if (point->Properties->MouseWheelDelta > 0) {
- mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_UP);
- } else if (point->Properties->MouseWheelDelta < 0) {
- mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_LEFT : BUTTON_WHEEL_DOWN);
+ Ref<InputEventMouseButton> mouse_button;
+ mouse_button.instance();
+ mouse_button->set_device(0);
+ mouse_button->set_pressed(p_pressed);
+ mouse_button->set_button_index(but);
+ mouse_button->set_position(Vector2(pos.X, pos.Y));
+ mouse_button->set_global_position(Vector2(pos.X, pos.Y));
+
+ if (p_is_wheel) {
+ if (point->Properties->MouseWheelDelta > 0) {
+ mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_UP);
+ } else if (point->Properties->MouseWheelDelta < 0) {
+ mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_LEFT : BUTTON_WHEEL_DOWN);
+ }
}
- }
- last_touch_x[31] = pos.X;
- last_touch_y[31] = pos.Y;
+ last_touch_x[31] = pos.X;
+ last_touch_y[31] = pos.Y;
- os->input_event(mouse_button);
-
- if (p_is_wheel) {
- // Send release for mouse wheel
- mouse_button->set_pressed(false);
os->input_event(mouse_button);
+
+ if (p_is_wheel) {
+ // Send release for mouse wheel
+ mouse_button->set_pressed(false);
+ os->input_event(mouse_button);
+ }
}
};
void App::OnPointerPressed(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
- number_of_contacts++;
pointer_event(sender, args, true);
};
void App::OnPointerReleased(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
- number_of_contacts--;
pointer_event(sender, args, false);
};
@@ -351,7 +346,7 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Co
Windows::UI::Input::PointerPoint ^ point = args->CurrentPoint;
Windows::Foundation::Point pos = _get_pixel_position(window, point->Position, os);
- if (point->IsInContact && _is_touch(point)) {
+ if (_is_touch(point)) {
Ref<InputEventScreenDrag> screen_drag;
screen_drag.instance();
@@ -361,25 +356,23 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Co
screen_drag->set_relative(Vector2(screen_drag->get_position().x - last_touch_x[screen_drag->get_index()], screen_drag->get_position().y - last_touch_y[screen_drag->get_index()]));
os->input_event(screen_drag);
- if (number_of_contacts > 1)
- return;
-
- }; // fallthrought of sorts
+ } else {
- // In case the mouse grabbed, MouseMoved will handle this
- if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED)
- return;
+ // In case the mouse grabbed, MouseMoved will handle this
+ if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED)
+ return;
- Ref<InputEventMouseMotion> mouse_motion;
- mouse_motion.instance();
- mouse_motion->set_device(0);
- mouse_motion->set_position(Vector2(pos.X, pos.Y));
- mouse_motion->set_global_position(Vector2(pos.X, pos.Y));
- mouse_motion->set_relative(Vector2(pos.X - last_touch_x[31], pos.Y - last_touch_y[31]));
+ Ref<InputEventMouseMotion> mouse_motion;
+ mouse_motion.instance();
+ mouse_motion->set_device(0);
+ mouse_motion->set_position(Vector2(pos.X, pos.Y));
+ mouse_motion->set_global_position(Vector2(pos.X, pos.Y));
+ mouse_motion->set_relative(Vector2(pos.X - last_touch_x[31], pos.Y - last_touch_y[31]));
- last_mouse_pos = pos;
+ last_mouse_pos = pos;
- os->input_event(mouse_motion);
+ os->input_event(mouse_motion);
+ }
}
void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) {
diff --git a/platform/uwp/app.h b/platform/uwp/app.h
index c23270b8ba..5f69f2cb0e 100644
--- a/platform/uwp/app.h
+++ b/platform/uwp/app.h
@@ -107,7 +107,6 @@ namespace GodotUWP
int last_touch_x[32]; // 20 fingers, index 31 reserved for the mouse
int last_touch_y[32];
- int number_of_contacts;
Windows::Foundation::Point last_mouse_pos;
};
}
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 9c37b65d77..363f54fc7b 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -342,6 +342,14 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
} break;
case WM_MOUSEMOVE: {
+ if (input->is_emulating_mouse_from_touch()) {
+ // Universal translation enabled; ignore OS translation
+ LPARAM extra = GetMessageExtraInfo();
+ if (IsPenEvent(extra)) {
+ break;
+ }
+ }
+
if (outside) {
//mouse enter
@@ -367,18 +375,6 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
// 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;
- /*
- LPARAM extra = GetMessageExtraInfo();
- if (IsPenEvent(extra)) {
-
- int idx = extra & 0x7f;
- _drag_event(idx, uMsg, wParam, lParam);
- if (idx != 0) {
- return 0;
- };
- // fallthrough for mouse event
- };
- */
Ref<InputEventMouseMotion> mm;
mm.instance();
@@ -448,18 +444,13 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/*case WM_XBUTTONDOWN:
case WM_XBUTTONUP: */ {
- /*
- LPARAM extra = GetMessageExtraInfo();
- if (IsPenEvent(extra)) {
-
- int idx = extra & 0x7f;
- _touch_event(idx, uMsg, wParam, lParam);
- if (idx != 0) {
- return 0;
- };
- // fallthrough for mouse event
- };
- */
+ if (input->is_emulating_mouse_from_touch()) {
+ // Universal translation enabled; ignore OS translation
+ LPARAM extra = GetMessageExtraInfo();
+ if (IsPenEvent(extra)) {
+ break;
+ }
+ }
Ref<InputEventMouseButton> mb;
mb.instance();
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 1928800d8c..336068cb1e 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -1690,6 +1690,11 @@ void OS_X11::process_xevents() {
if (touch.state.has(index)) // Defensive
break;
touch.state[index] = pos;
+ if (touch.state.size() == 1) {
+ // X11 may send a motion event when a touch gesture begins, that would result
+ // in a spurious mouse motion event being sent to Godot; remember it to be able to filter it out
+ touch.mouse_pos_to_filter = pos;
+ }
input->parse_input_event(st);
} else {
if (!touch.state.has(index)) // Defensive
@@ -1896,6 +1901,18 @@ void OS_X11::process_xevents() {
// to be able to send relative motion events.
Point2i pos(event.xmotion.x, event.xmotion.y);
+ // Avoidance of spurious mouse motion (see handling of touch)
+ bool filter = false;
+ // Adding some tolerance to match better Point2i to Vector2
+ if (touch.state.size() && Vector2(pos).distance_squared_to(touch.mouse_pos_to_filter) < 2) {
+ filter = true;
+ }
+ // Invalidate to avoid filtering a possible legitimate similar event coming later
+ touch.mouse_pos_to_filter = Vector2(1e10, 1e10);
+ if (filter) {
+ break;
+ }
+
if (mouse_mode == MOUSE_MODE_CAPTURED) {
if (pos == Point2i(current_videomode.width / 2, current_videomode.height / 2)) {
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 610dba0716..0a39da77de 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -127,6 +127,7 @@ class OS_X11 : public OS_Unix {
Vector<int> devices;
XIEventMask event_mask;
Map<int, Vector2> state;
+ Vector2 mouse_pos_to_filter;
} touch;
#endif
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 4419dfe70f..727807dbcd 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -33,6 +33,7 @@
#include "editor/editor_node.h"
#include "io/marshalls.h"
#include "io/resource_loader.h"
+#include "main/input_default.h"
#include "message_queue.h"
#include "node.h"
#include "os/keyboard.h"
@@ -620,6 +621,13 @@ void SceneTree::_notification(int p_notification) {
case NOTIFICATION_WM_FOCUS_IN:
case NOTIFICATION_WM_FOCUS_OUT: {
+ if (p_notification == NOTIFICATION_WM_FOCUS_IN) {
+ InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
+ if (id) {
+ id->ensure_touch_mouse_raised();
+ }
+ }
+
get_root()->propagate_notification(p_notification);
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {