summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/gui/control.cpp20
-rw-r--r--scene/gui/control.h4
-rw-r--r--scene/main/viewport.cpp71
-rw-r--r--scene/main/viewport.h2
4 files changed, 72 insertions, 25 deletions
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index a0104387c9..5c5b2683a4 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -471,6 +471,13 @@ void Control::_validate_property(PropertyInfo &property) const {
property.hint_string = hint_string;
}
+ if (property.name == "mouse_force_pass_scroll_events") {
+ // Disable force pass if the control is not stopping the event.
+ if (data.mouse_filter != MOUSE_FILTER_STOP) {
+ property.usage |= PROPERTY_USAGE_READ_ONLY;
+ }
+ }
+
// Validate which positioning properties should be displayed depending on the parent and the layout mode.
Node *parent_node = get_parent_control();
if (!parent_node) {
@@ -2921,6 +2928,7 @@ int Control::get_v_size_flags() const {
void Control::set_mouse_filter(MouseFilter p_filter) {
ERR_FAIL_INDEX(p_filter, 3);
data.mouse_filter = p_filter;
+ notify_property_list_changed();
update_configuration_warnings();
}
@@ -2928,6 +2936,14 @@ Control::MouseFilter Control::get_mouse_filter() const {
return data.mouse_filter;
}
+void Control::set_force_pass_scroll_events(bool p_force_pass_scroll_events) {
+ data.force_pass_scroll_events = p_force_pass_scroll_events;
+}
+
+bool Control::is_force_pass_scroll_events() const {
+ return data.force_pass_scroll_events;
+}
+
void Control::warp_mouse(const Point2 &p_position) {
ERR_FAIL_COND(!is_inside_tree());
get_viewport()->warp_mouse(get_global_transform_with_canvas().xform(p_position));
@@ -3240,6 +3256,9 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mouse_filter", "filter"), &Control::set_mouse_filter);
ClassDB::bind_method(D_METHOD("get_mouse_filter"), &Control::get_mouse_filter);
+ ClassDB::bind_method(D_METHOD("set_force_pass_scroll_events", "force_pass_scroll_events"), &Control::set_force_pass_scroll_events);
+ ClassDB::bind_method(D_METHOD("is_force_pass_scroll_events"), &Control::is_force_pass_scroll_events);
+
ClassDB::bind_method(D_METHOD("set_clip_contents", "enable"), &Control::set_clip_contents);
ClassDB::bind_method(D_METHOD("is_clipping_contents"), &Control::is_clipping_contents);
@@ -3321,6 +3340,7 @@ void Control::_bind_methods() {
ADD_GROUP("Mouse", "mouse_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mouse_force_pass_scroll_events"), "set_force_pass_scroll_events", "is_force_pass_scroll_events");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,I-Beam,Pointing Hand,Cross,Wait,Busy,Drag,Can Drop,Forbidden,Vertical Resize,Horizontal Resize,Secondary Diagonal Resize,Main Diagonal Resize,Move,Vertical Split,Horizontal Split,Help"), "set_default_cursor_shape", "get_default_cursor_shape");
ADD_GROUP("Theme", "theme_");
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 65b71d74f8..43d49da055 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -190,6 +190,7 @@ private:
Point2 custom_minimum_size;
MouseFilter mouse_filter = MOUSE_FILTER_STOP;
+ bool force_pass_scroll_events = true;
bool clip_contents = false;
@@ -468,6 +469,9 @@ public:
void set_mouse_filter(MouseFilter p_filter);
MouseFilter get_mouse_filter() const;
+ void set_force_pass_scroll_events(bool p_force_pass_scroll_events);
+ bool is_force_pass_scroll_events() const;
+
/* SKINNING */
void begin_bulk_theme_override();
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index a2399c8b5a..0be4216e99 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1277,21 +1277,19 @@ void Viewport::_gui_show_tooltip() {
gui.tooltip_popup->child_controls_changed();
}
-void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_input) {
+bool Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_input) {
+ bool stopped = false;
Ref<InputEvent> ev = p_input;
- // Mouse wheel events can't be stopped.
- Ref<InputEventMouseButton> mb = p_input;
+ // Returns true if an event should be impacted by a control's mouse filter.
+ bool is_mouse_event = Ref<InputEventMouse>(p_input).is_valid();
- bool cant_stop_me_now = (mb.is_valid() &&
+ Ref<InputEventMouseButton> mb = p_input;
+ bool is_scroll_event = mb.is_valid() &&
(mb->get_button_index() == MouseButton::WHEEL_DOWN ||
mb->get_button_index() == MouseButton::WHEEL_UP ||
mb->get_button_index() == MouseButton::WHEEL_LEFT ||
- mb->get_button_index() == MouseButton::WHEEL_RIGHT));
- Ref<InputEventPanGesture> pn = p_input;
- cant_stop_me_now = pn.is_valid() || cant_stop_me_now;
-
- bool ismouse = ev.is_valid() || Object::cast_to<InputEventMouseMotion>(*p_input) != nullptr;
+ mb->get_button_index() == MouseButton::WHEEL_RIGHT);
CanvasItem *ci = p_control;
while (ci) {
@@ -1305,9 +1303,12 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
break;
}
if (gui.key_event_accepted) {
+ stopped = true;
break;
}
- if (!cant_stop_me_now && control->data.mouse_filter == Control::MOUSE_FILTER_STOP && ismouse) {
+ if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP && is_mouse_event && !(is_scroll_event && control->data.force_pass_scroll_events)) {
+ // Mouse events are stopped by default with MOUSE_FILTER_STOP, unless we have a scroll event and force_pass_scroll_events set to true
+ stopped = true;
break;
}
}
@@ -1319,6 +1320,7 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
ev = ev->xformed_by(ci->get_transform()); // Transform event upwards.
ci = ci->get_parent_item();
}
+ return stopped;
}
void Viewport::_gui_call_notification(Control *p_control, int p_what) {
@@ -1530,11 +1532,14 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
+ bool stopped = false;
if (gui.mouse_focus && gui.mouse_focus->can_process()) {
- _gui_call_input(gui.mouse_focus, mb);
+ stopped = _gui_call_input(gui.mouse_focus, mb);
}
- set_input_as_handled();
+ if (stopped) {
+ set_input_as_handled();
+ }
if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) {
// Alternate drop use (when using force_drag(), as proposed by #5342).
@@ -1600,11 +1605,14 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.forced_mouse_focus = false;
}
+ bool stopped = false;
if (mouse_focus && mouse_focus->can_process()) {
- _gui_call_input(mouse_focus, mb);
+ stopped = _gui_call_input(mouse_focus, mb);
}
- set_input_as_handled();
+ if (stopped) {
+ set_input_as_handled();
+ }
}
}
@@ -1767,11 +1775,14 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
ds_cursor_shape = (DisplayServer::CursorShape)cursor_shape;
+ bool stopped = false;
if (over && over->can_process()) {
- _gui_call_input(over, mm);
+ stopped = _gui_call_input(over, mm);
}
- set_input_as_handled();
+ if (stopped) {
+ set_input_as_handled();
+ }
}
if (gui.drag_data.get_type() != Variant::NIL) {
@@ -1884,6 +1895,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (touch_event->is_pressed()) {
Control *over = gui_find_control(pos);
if (over) {
+ bool stopped = false;
if (over->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); // Make a copy.
if (over == gui.mouse_focus) {
@@ -1892,19 +1904,24 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
}
touch_event->set_position(pos);
- _gui_call_input(over, touch_event);
+ stopped = _gui_call_input(over, touch_event);
+ }
+ if (stopped) {
+ set_input_as_handled();
}
- set_input_as_handled();
return;
}
} else if (touch_event->get_index() == 0 && gui.last_mouse_focus) {
+ bool stopped = false;
if (gui.last_mouse_focus->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); // Make a copy.
touch_event->set_position(gui.focus_inv_xform.xform(pos));
- _gui_call_input(gui.last_mouse_focus, touch_event);
+ stopped = _gui_call_input(gui.last_mouse_focus, touch_event);
+ }
+ if (stopped) {
+ set_input_as_handled();
}
- set_input_as_handled();
return;
}
}
@@ -1919,6 +1936,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *over = gui_find_control(pos);
if (over) {
+ bool stopped = false;
if (over->can_process()) {
gesture_event = gesture_event->xformed_by(Transform2D()); // Make a copy.
if (over == gui.mouse_focus) {
@@ -1927,9 +1945,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
}
gesture_event->set_position(pos);
- _gui_call_input(over, gesture_event);
+ stopped = _gui_call_input(over, gesture_event);
+ }
+ if (stopped) {
+ set_input_as_handled();
}
- set_input_as_handled();
return;
}
}
@@ -1941,6 +1961,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
over = gui_find_control(drag_event->get_position());
}
if (over) {
+ bool stopped = false;
if (over->can_process()) {
Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse();
Size2 pos = localizer.xform(drag_event->get_position());
@@ -1953,10 +1974,12 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
drag_event->set_relative(rel);
drag_event->set_position(pos);
- _gui_call_input(over, drag_event);
+ stopped = _gui_call_input(over, drag_event);
}
- set_input_as_handled();
+ if (stopped) {
+ set_input_as_handled();
+ }
return;
}
}
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index c1e4b30c20..48e4b175b6 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -381,7 +381,7 @@ private:
bool disable_input = false;
- void _gui_call_input(Control *p_control, const Ref<InputEvent> &p_input);
+ bool _gui_call_input(Control *p_control, const Ref<InputEvent> &p_input);
void _gui_call_notification(Control *p_control, int p_what);
void _gui_sort_roots();