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.
This commit is contained in:
parent
74e72c995d
commit
e10a2e5999
|
@ -118,6 +118,7 @@ public:
|
||||||
void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
|
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_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_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;
|
virtual void set_mouse_in_window(bool p_in_window) = 0;
|
||||||
|
|
|
@ -249,6 +249,11 @@ Vector3 InputDefault::get_gyroscope() const {
|
||||||
|
|
||||||
void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
|
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_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
Ref<InputEventKey> k = p_event;
|
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));
|
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;
|
Ref<InputEventScreenTouch> touch_event;
|
||||||
touch_event.instance();
|
touch_event.instance();
|
||||||
touch_event->set_pressed(mb->is_pressed());
|
touch_event->set_pressed(mb->is_pressed());
|
||||||
touch_event->set_position(mb->get_position());
|
touch_event->set_position(mb->get_position());
|
||||||
main_loop->input_event(touch_event);
|
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;
|
Ref<InputEventMouseMotion> mm = p_event;
|
||||||
|
|
||||||
if (mm.is_valid()) {
|
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;
|
Ref<InputEventScreenDrag> drag_event;
|
||||||
drag_event.instance();
|
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;
|
Ref<InputEventJoypadButton> jb = p_event;
|
||||||
|
|
||||||
if (jb.is_valid()) {
|
if (jb.is_valid()) {
|
||||||
|
@ -498,6 +560,36 @@ bool InputDefault::is_emulating_touchscreen() const {
|
||||||
return emulate_touch;
|
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) {
|
void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||||
if (Engine::get_singleton()->is_editor_hint())
|
if (Engine::get_singleton()->is_editor_hint())
|
||||||
return;
|
return;
|
||||||
|
@ -815,6 +907,8 @@ InputDefault::InputDefault() {
|
||||||
|
|
||||||
mouse_button_mask = 0;
|
mouse_button_mask = 0;
|
||||||
emulate_touch = false;
|
emulate_touch = false;
|
||||||
|
emulate_mouse_from_touch = false;
|
||||||
|
mouse_from_touch_index = -1;
|
||||||
main_loop = NULL;
|
main_loop = NULL;
|
||||||
|
|
||||||
hat_map_default[HAT_UP].type = TYPE_BUTTON;
|
hat_map_default[HAT_UP].type = TYPE_BUTTON;
|
||||||
|
|
|
@ -60,6 +60,9 @@ class InputDefault : public Input {
|
||||||
Map<StringName, Action> action_state;
|
Map<StringName, Action> action_state;
|
||||||
|
|
||||||
bool emulate_touch;
|
bool emulate_touch;
|
||||||
|
bool emulate_mouse_from_touch;
|
||||||
|
|
||||||
|
int mouse_from_touch_index;
|
||||||
|
|
||||||
struct VibrationInfo {
|
struct VibrationInfo {
|
||||||
float weak_magnitude;
|
float weak_magnitude;
|
||||||
|
@ -175,6 +178,8 @@ private:
|
||||||
void _axis_event(int p_device, int p_axis, float p_value);
|
void _axis_event(int p_device, int p_axis, float p_value);
|
||||||
float _handle_deadzone(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:
|
public:
|
||||||
virtual bool is_key_pressed(int p_scancode) const;
|
virtual bool is_key_pressed(int p_scancode) const;
|
||||||
virtual bool is_mouse_button_pressed(int p_button) const;
|
virtual bool is_mouse_button_pressed(int p_button) const;
|
||||||
|
@ -225,6 +230,10 @@ public:
|
||||||
|
|
||||||
void set_emulate_touch(bool p_emulate);
|
void set_emulate_touch(bool p_emulate);
|
||||||
virtual bool is_emulating_touchscreen() const;
|
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_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);
|
virtual void set_mouse_in_window(bool p_in_window);
|
||||||
|
|
|
@ -1143,13 +1143,16 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||||
GLOBAL_DEF("application/config/icon", String());
|
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"));
|
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))) {
|
InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
|
||||||
if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton() && !editor) {
|
if (id) {
|
||||||
//only if no touchscreen ui hint, set emulation
|
if (bool(GLOBAL_DEF("display/window/handheld/emulate_touchscreen", false)) && !editor) {
|
||||||
InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
|
if (!OS::get_singleton()->has_touchscreen_ui_hint()) {
|
||||||
if (id)
|
//only if no touchscreen ui hint, set emulation
|
||||||
id->set_emulate_touch(true);
|
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 Remaps");
|
||||||
|
|
|
@ -332,17 +332,6 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
|
||||||
|
|
||||||
if (touch.size()) {
|
if (touch.size()) {
|
||||||
//end all if exist
|
//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++) {
|
for (int i = 0; i < touch.size(); i++) {
|
||||||
|
|
||||||
Ref<InputEventScreenTouch> ev;
|
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;
|
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
|
//send touch
|
||||||
for (int i = 0; i < touch.size(); i++) {
|
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;
|
} break;
|
||||||
case 1: { //motion
|
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());
|
ERR_FAIL_COND(touch.size() != p_points.size());
|
||||||
|
|
||||||
for (int i = 0; i < touch.size(); i++) {
|
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()) {
|
if (touch.size()) {
|
||||||
//end all if exist
|
//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++) {
|
for (int i = 0; i < touch.size(); i++) {
|
||||||
|
|
||||||
Ref<InputEventScreenTouch> ev;
|
Ref<InputEventScreenTouch> ev;
|
||||||
|
|
|
@ -93,7 +93,6 @@ public:
|
||||||
private:
|
private:
|
||||||
Vector<TouchPos> touch;
|
Vector<TouchPos> touch;
|
||||||
|
|
||||||
Point2 last_mouse;
|
|
||||||
GFXInitFunc gfx_init_func;
|
GFXInitFunc gfx_init_func;
|
||||||
void *gfx_init_ud;
|
void *gfx_init_ud;
|
||||||
|
|
||||||
|
|
|
@ -489,7 +489,7 @@ static void clear_touches() {
|
||||||
int tid = get_touch_id(touch);
|
int tid = get_touch_id(touch);
|
||||||
ERR_FAIL_COND(tid == -1);
|
ERR_FAIL_COND(tid == -1);
|
||||||
CGPoint touchPoint = [touch locationInView:self];
|
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);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -506,10 +506,9 @@ static void clear_touches() {
|
||||||
continue;
|
continue;
|
||||||
int tid = get_touch_id(touch);
|
int tid = get_touch_id(touch);
|
||||||
ERR_FAIL_COND(tid == -1);
|
ERR_FAIL_COND(tid == -1);
|
||||||
int first = get_first_id(touch);
|
|
||||||
CGPoint touchPoint = [touch locationInView:self];
|
CGPoint touchPoint = [touch locationInView:self];
|
||||||
CGPoint prev_point = [touch previousLocationInView: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);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -525,9 +524,9 @@ static void clear_touches() {
|
||||||
continue;
|
continue;
|
||||||
int tid = get_touch_id(touch);
|
int tid = get_touch_id(touch);
|
||||||
ERR_FAIL_COND(tid == -1);
|
ERR_FAIL_COND(tid == -1);
|
||||||
int rem = remove_touch(touch);
|
remove_touch(touch);
|
||||||
CGPoint touchPoint = [touch locationInView:self];
|
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);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,7 @@ void OSIPhone::key(uint32_t p_key, bool p_pressed) {
|
||||||
queue_event(ev);
|
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)) {
|
if (!GLOBAL_DEF("debug/disable_touch", false)) {
|
||||||
Ref<InputEventScreenTouch> ev;
|
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);
|
queue_event(ev);
|
||||||
};
|
};
|
||||||
|
|
||||||
mouse_list.pressed[p_idx] = p_pressed;
|
touch_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);
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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)) {
|
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));
|
ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
|
||||||
queue_event(ev);
|
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) {
|
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++) {
|
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
|
// 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 {
|
int OSIPhone::get_mouse_button_state() const {
|
||||||
|
|
||||||
return mouse_list.pressed[0];
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
void OSIPhone::set_window_title(const String &p_title){};
|
void OSIPhone::set_window_title(const String &p_title){};
|
||||||
|
|
|
@ -106,7 +106,7 @@ private:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
MouseList mouse_list;
|
MouseList touch_list;
|
||||||
|
|
||||||
Vector3 last_accel;
|
Vector3 last_accel;
|
||||||
|
|
||||||
|
@ -127,8 +127,8 @@ public:
|
||||||
|
|
||||||
uint8_t get_orientations() const;
|
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 touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_doubleclick);
|
||||||
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_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y);
|
||||||
void touches_cancelled();
|
void touches_cancelled();
|
||||||
void key(uint32_t p_key, bool p_pressed);
|
void key(uint32_t p_key, bool p_pressed);
|
||||||
void set_virtual_keyboard_height(int p_height);
|
void set_virtual_keyboard_height(int p_height);
|
||||||
|
@ -151,7 +151,6 @@ public:
|
||||||
virtual void set_mouse_grab(bool p_grab);
|
virtual void set_mouse_grab(bool p_grab);
|
||||||
virtual bool is_mouse_grab_enabled() const;
|
virtual bool is_mouse_grab_enabled() const;
|
||||||
virtual Point2 get_mouse_position() 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 set_window_title(const String &p_title);
|
||||||
|
|
||||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||||
|
|
|
@ -277,23 +277,6 @@ static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent *
|
||||||
|
|
||||||
_input->parse_input_event(ev);
|
_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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,24 +302,6 @@ static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *t
|
||||||
|
|
||||||
_input->parse_input_event(ev);
|
_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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,8 +85,7 @@ App::App() :
|
||||||
mWindowHeight(0),
|
mWindowHeight(0),
|
||||||
mEglDisplay(EGL_NO_DISPLAY),
|
mEglDisplay(EGL_NO_DISPLAY),
|
||||||
mEglContext(EGL_NO_CONTEXT),
|
mEglContext(EGL_NO_CONTEXT),
|
||||||
mEglSurface(EGL_NO_SURFACE),
|
mEglSurface(EGL_NO_SURFACE) {
|
||||||
number_of_contacts(0) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first method called when the IFrameworkView is being created.
|
// 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;
|
last_touch_y[screen_touch->get_index()] = pos.Y;
|
||||||
|
|
||||||
os->input_event(screen_touch);
|
os->input_event(screen_touch);
|
||||||
if (number_of_contacts > 1)
|
} else {
|
||||||
return;
|
|
||||||
|
|
||||||
}; // 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));
|
||||||
|
|
||||||
Ref<InputEventMouseButton> mouse_button;
|
if (p_is_wheel) {
|
||||||
mouse_button.instance();
|
if (point->Properties->MouseWheelDelta > 0) {
|
||||||
mouse_button->set_device(0);
|
mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_UP);
|
||||||
mouse_button->set_pressed(p_pressed);
|
} else if (point->Properties->MouseWheelDelta < 0) {
|
||||||
mouse_button->set_button_index(but);
|
mouse_button->set_button_index(point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_LEFT : BUTTON_WHEEL_DOWN);
|
||||||
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_x[31] = pos.X;
|
||||||
last_touch_y[31] = pos.Y;
|
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);
|
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) {
|
void App::OnPointerPressed(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
|
||||||
|
|
||||||
number_of_contacts++;
|
|
||||||
pointer_event(sender, args, true);
|
pointer_event(sender, args, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
void App::OnPointerReleased(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
|
void App::OnPointerReleased(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args) {
|
||||||
|
|
||||||
number_of_contacts--;
|
|
||||||
pointer_event(sender, args, false);
|
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::UI::Input::PointerPoint ^ point = args->CurrentPoint;
|
||||||
Windows::Foundation::Point pos = _get_pixel_position(window, point->Position, os);
|
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;
|
Ref<InputEventScreenDrag> screen_drag;
|
||||||
screen_drag.instance();
|
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()]));
|
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);
|
os->input_event(screen_drag);
|
||||||
if (number_of_contacts > 1)
|
} else {
|
||||||
|
|
||||||
|
// In case the mouse grabbed, MouseMoved will handle this
|
||||||
|
if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}; // fallthrought of sorts
|
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]));
|
||||||
|
|
||||||
// In case the mouse grabbed, MouseMoved will handle this
|
last_mouse_pos = pos;
|
||||||
if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Ref<InputEventMouseMotion> mouse_motion;
|
os->input_event(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;
|
|
||||||
|
|
||||||
os->input_event(mouse_motion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) {
|
void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) {
|
||||||
|
|
|
@ -107,7 +107,6 @@ namespace GodotUWP
|
||||||
|
|
||||||
int last_touch_x[32]; // 20 fingers, index 31 reserved for the mouse
|
int last_touch_x[32]; // 20 fingers, index 31 reserved for the mouse
|
||||||
int last_touch_y[32];
|
int last_touch_y[32];
|
||||||
int number_of_contacts;
|
|
||||||
Windows::Foundation::Point last_mouse_pos;
|
Windows::Foundation::Point last_mouse_pos;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,6 +361,14 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
} break;
|
} break;
|
||||||
case WM_MOUSEMOVE: {
|
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) {
|
if (outside) {
|
||||||
//mouse enter
|
//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.
|
// Don't calculate relative mouse movement if we don't have focus in CAPTURED mode.
|
||||||
if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED)
|
if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED)
|
||||||
break;
|
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;
|
Ref<InputEventMouseMotion> mm;
|
||||||
mm.instance();
|
mm.instance();
|
||||||
|
@ -467,18 +463,13 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
/*case WM_XBUTTONDOWN:
|
/*case WM_XBUTTONDOWN:
|
||||||
case WM_XBUTTONUP: */ {
|
case WM_XBUTTONUP: */ {
|
||||||
|
|
||||||
/*
|
if (input->is_emulating_mouse_from_touch()) {
|
||||||
LPARAM extra = GetMessageExtraInfo();
|
// Universal translation enabled; ignore OS translation
|
||||||
if (IsPenEvent(extra)) {
|
LPARAM extra = GetMessageExtraInfo();
|
||||||
|
if (IsPenEvent(extra)) {
|
||||||
int idx = extra & 0x7f;
|
break;
|
||||||
_touch_event(idx, uMsg, wParam, lParam);
|
}
|
||||||
if (idx != 0) {
|
}
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
// fallthrough for mouse event
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
Ref<InputEventMouseButton> mb;
|
Ref<InputEventMouseButton> mb;
|
||||||
mb.instance();
|
mb.instance();
|
||||||
|
|
|
@ -1626,6 +1626,11 @@ void OS_X11::process_xevents() {
|
||||||
if (touch.state.has(index)) // Defensive
|
if (touch.state.has(index)) // Defensive
|
||||||
break;
|
break;
|
||||||
touch.state[index] = pos;
|
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);
|
input->parse_input_event(st);
|
||||||
} else {
|
} else {
|
||||||
if (!touch.state.has(index)) // Defensive
|
if (!touch.state.has(index)) // Defensive
|
||||||
|
@ -1832,6 +1837,18 @@ void OS_X11::process_xevents() {
|
||||||
// to be able to send relative motion events.
|
// to be able to send relative motion events.
|
||||||
Point2i pos(event.xmotion.x, event.xmotion.y);
|
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 (mouse_mode == MOUSE_MODE_CAPTURED) {
|
||||||
|
|
||||||
if (pos == Point2i(current_videomode.width / 2, current_videomode.height / 2)) {
|
if (pos == Point2i(current_videomode.width / 2, current_videomode.height / 2)) {
|
||||||
|
|
|
@ -127,6 +127,7 @@ class OS_X11 : public OS_Unix {
|
||||||
Vector<int> devices;
|
Vector<int> devices;
|
||||||
XIEventMask event_mask;
|
XIEventMask event_mask;
|
||||||
Map<int, Vector2> state;
|
Map<int, Vector2> state;
|
||||||
|
Vector2 mouse_pos_to_filter;
|
||||||
} touch;
|
} touch;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "editor/editor_node.h"
|
#include "editor/editor_node.h"
|
||||||
#include "io/marshalls.h"
|
#include "io/marshalls.h"
|
||||||
#include "io/resource_loader.h"
|
#include "io/resource_loader.h"
|
||||||
|
#include "main/input_default.h"
|
||||||
#include "message_queue.h"
|
#include "message_queue.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "os/keyboard.h"
|
#include "os/keyboard.h"
|
||||||
|
@ -618,6 +619,13 @@ void SceneTree::_notification(int p_notification) {
|
||||||
case NOTIFICATION_WM_FOCUS_IN:
|
case NOTIFICATION_WM_FOCUS_IN:
|
||||||
case NOTIFICATION_WM_FOCUS_OUT: {
|
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);
|
get_root()->propagate_notification(p_notification);
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_TRANSLATION_CHANGED: {
|
case NOTIFICATION_TRANSLATION_CHANGED: {
|
||||||
|
|
Loading…
Reference in New Issue