Merge pull request #18082 from RandomShaper/improve-gui-touch-3.0

Implement universal translation of touch to mouse (3.0)
This commit is contained in:
Hein-Pieter van Braam 2018-05-13 21:30:37 +02:00 committed by GitHub
commit 5917063192
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 210 additions and 214 deletions

View File

@ -118,6 +118,7 @@ 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_mouse_from_touch() const = 0;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) = 0;
virtual void set_mouse_in_window(bool p_in_window) = 0;

View File

@ -249,6 +249,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;
@ -272,25 +277,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 && !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 && !p_is_emulated && mm->get_button_mask() & 1) {
Ref<InputEventScreenDrag> drag_event;
drag_event.instance();
@ -302,6 +312,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()) {
@ -498,6 +560,36 @@ bool InputDefault::is_emulating_touchscreen() const {
return emulate_touch;
}
// 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_mouse_from_touch = p_emulate;
}
bool InputDefault::is_emulating_mouse_from_touch() const {
return emulate_mouse_from_touch;
}
void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (Engine::get_singleton()->is_editor_hint())
return;
@ -815,6 +907,8 @@ InputDefault::InputDefault() {
mouse_button_mask = 0;
emulate_touch = false;
emulate_mouse_from_touch = false;
mouse_from_touch_index = -1;
main_loop = NULL;
hat_map_default[HAT_UP].type = TYPE_BUTTON;

View File

@ -60,6 +60,9 @@ class InputDefault : public Input {
Map<StringName, Action> action_state;
bool emulate_touch;
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;
@ -225,6 +230,10 @@ public:
void set_emulate_touch(bool p_emulate);
virtual bool is_emulating_touchscreen() const;
void ensure_touch_mouse_raised();
void set_emulate_mouse_from_touch(bool p_emulate);
virtual bool is_emulating_mouse_from_touch() const;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = Input::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
virtual void set_mouse_in_window(bool p_in_window);

View File

@ -1157,15 +1157,18 @@ 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) {
//only if no touchscreen ui hint, set emulation
InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
if (id)
if (id) {
if (bool(GLOBAL_DEF("display/window/handheld/emulate_touchscreen", false)) && !editor) {
if (!OS::get_singleton()->has_touchscreen_ui_hint()) {
//only if no touchscreen ui hint, set emulation
id->set_emulate_touch(true);
}
}
id->set_emulate_mouse_from_touch(bool(GLOBAL_DEF("display/window/handheld/emulate_mouse_from_touch", true)));
}
MAIN_PRINT("Main: Load Remaps");
MAIN_PRINT("Main: Load Scene Types");

View File

@ -332,17 +332,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;
@ -360,21 +349,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++) {
@ -389,19 +363,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++) {
@ -434,16 +395,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;

View File

@ -93,7 +93,6 @@ public:
private:
Vector<TouchPos> touch;
Point2 last_mouse;
GFXInitFunc gfx_init_func;
void *gfx_init_ud;

View File

@ -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);
};
};
}

View File

@ -191,7 +191,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;
@ -203,28 +203,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)) {
@ -235,21 +217,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) {
@ -263,10 +230,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);
};
};
};
@ -377,7 +344,7 @@ Point2 OSIPhone::get_mouse_position() const {
int OSIPhone::get_mouse_button_state() const {
return mouse_list.pressed[0];
return false;
};
void OSIPhone::set_window_title(const String &p_title){};

View File

@ -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);
@ -151,7 +151,6 @@ public:
virtual void set_mouse_grab(bool p_grab);
virtual bool is_mouse_grab_enabled() const;
virtual Point2 get_mouse_position() const;
virtual int get_mouse_button_state() const;
virtual void set_window_title(const String &p_title);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");

View File

@ -277,23 +277,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;
}
@ -319,24 +302,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;
}

View File

@ -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,10 +270,7 @@ 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;
}; // fallthrought of sorts
} else {
Ref<InputEventMouseButton> mouse_button;
mouse_button.instance();
@ -302,17 +298,16 @@ void App::pointer_event(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Cor
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,10 +356,7 @@ 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)
@ -381,6 +373,7 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Co
os->input_event(mouse_motion);
}
}
void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) {

View File

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

View File

@ -361,6 +361,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
@ -386,18 +394,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();
@ -467,18 +463,13 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/*case WM_XBUTTONDOWN:
case WM_XBUTTONUP: */ {
/*
if (input->is_emulating_mouse_from_touch()) {
// Universal translation enabled; ignore OS translation
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
};
*/
break;
}
}
Ref<InputEventMouseButton> mb;
mb.instance();

View File

@ -1680,6 +1680,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
@ -1886,6 +1891,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)) {

View File

@ -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

View File

@ -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: {