mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 07:53:26 +00:00
Merge pull request #105222 from kitbdev/fix-mouse-filter-recursive-and-rename
Fix and rename mouse filter recursive behavior and focus mode recursive behavior
This commit is contained in:
commit
00bd421089
10 changed files with 282 additions and 173 deletions
|
@ -415,10 +415,10 @@
|
|||
Returns [member offset_right] and [member offset_bottom].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_focus_mode_with_recursive" qualifiers="const">
|
||||
<method name="get_focus_mode_with_override" qualifiers="const">
|
||||
<return type="int" enum="Control.FocusMode" />
|
||||
<description>
|
||||
Similar to the getter of [member focus_mode], but takes parent's [member focus_recursive_behavior] into account.
|
||||
Returns the [member focus_mode], but takes the [member focus_behavior_recursive] into account. If [member focus_behavior_recursive] is set to [constant FOCUS_BEHAVIOR_DISABLED], or it is set to [constant FOCUS_BEHAVIOR_INHERITED] and its ancestor is set to [constant FOCUS_BEHAVIOR_DISABLED], then this returns [constant FOCUS_NONE].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_focus_neighbor" qualifiers="const">
|
||||
|
@ -443,10 +443,10 @@
|
|||
Returns the minimum size for this control. See [member custom_minimum_size].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_mouse_filter_with_recursive" qualifiers="const">
|
||||
<method name="get_mouse_filter_with_override" qualifiers="const">
|
||||
<return type="int" enum="Control.MouseFilter" />
|
||||
<description>
|
||||
Similar to the getter of [member mouse_filter], but takes parent's [member mouse_recursive_behavior] into account.
|
||||
Returns the [member mouse_filter], but takes the [member mouse_behavior_recursive] into account. If [member mouse_behavior_recursive] is set to [constant MOUSE_BEHAVIOR_DISABLED], or it is set to [constant MOUSE_BEHAVIOR_INHERITED] and its ancestor is set to [constant MOUSE_BEHAVIOR_DISABLED], then this returns [constant MOUSE_FILTER_IGNORE].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_offset" qualifiers="const">
|
||||
|
@ -983,8 +983,11 @@
|
|||
<member name="custom_minimum_size" type="Vector2" setter="set_custom_minimum_size" getter="get_custom_minimum_size" default="Vector2(0, 0)">
|
||||
The minimum size of the node's bounding rectangle. If you set it to a value greater than [code](0, 0)[/code], the node's bounding rectangle will always have at least this size. Note that [Control] nodes have their internal minimum size returned by [method get_minimum_size]. It depends on the control's contents, like text, textures, or style boxes. The actual minimum size is the maximum value of this property and the internal minimum size (see [method get_combined_minimum_size]).
|
||||
</member>
|
||||
<member name="focus_behavior_recursive" type="int" setter="set_focus_behavior_recursive" getter="get_focus_behavior_recursive" enum="Control.FocusBehaviorRecursive" default="0">
|
||||
Determines which controls can be focused together with [member focus_mode]. See [method get_focus_mode_with_override]. Since the default behavior is [constant FOCUS_BEHAVIOR_INHERITED], this can be used to prevent all children controls from getting focused.
|
||||
</member>
|
||||
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" enum="Control.FocusMode" default="0">
|
||||
The focus access mode for the control (None, Click or All). Only one Control can be focused at the same time, and it will receive keyboard, gamepad, and mouse signals.
|
||||
Determines which controls can be focused. Only one control can be focused at a time, and the focused control will receive keyboard, gamepad, and mouse events in [method _gui_input]. Use [method get_focus_mode_with_override] to determine if a control can grab focus, since [member focus_behavior_recursive] also affects it. See also [method grab_focus].
|
||||
</member>
|
||||
<member name="focus_neighbor_bottom" type="NodePath" setter="set_focus_neighbor" getter="get_focus_neighbor" default="NodePath("")" keywords="focus_neighbour_bottom">
|
||||
Tells Godot which node it should give focus to if the user presses the down arrow on the keyboard or down on a gamepad by default. You can change the key by editing the [member ProjectSettings.input/ui_down] input action. The node must be a [Control]. If this property is not set, Godot will give focus to the closest [Control] to the bottom of this one.
|
||||
|
@ -1006,9 +1009,6 @@
|
|||
Tells Godot which node it should give focus to if the user presses [kbd]Shift + Tab[/kbd] on a keyboard by default. You can change the key by editing the [member ProjectSettings.input/ui_focus_prev] input action.
|
||||
If this property is not set, Godot will select a "best guess" based on surrounding nodes in the scene tree.
|
||||
</member>
|
||||
<member name="focus_recursive_behavior" type="int" setter="set_focus_recursive_behavior" getter="get_focus_recursive_behavior" enum="Control.RecursiveBehavior" default="0">
|
||||
Controls whether the recursive child nodes should have their [member focus_mode] overridden to [constant FOCUS_NONE] when evaluating input.
|
||||
</member>
|
||||
<member name="global_position" type="Vector2" setter="_set_global_position" getter="get_global_position">
|
||||
The node's global position, relative to the world (usually to the [CanvasLayer]).
|
||||
</member>
|
||||
|
@ -1025,21 +1025,21 @@
|
|||
If [code]true[/code], automatically converts code line numbers, list indices, [SpinBox] and [ProgressBar] values from the Western Arabic (0..9) to the numeral systems used in current locale.
|
||||
[b]Note:[/b] Numbers within the text are not automatically converted, it can be done manually, using [method TextServer.format_number].
|
||||
</member>
|
||||
<member name="mouse_behavior_recursive" type="int" setter="set_mouse_behavior_recursive" getter="get_mouse_behavior_recursive" enum="Control.MouseBehaviorRecursive" default="0">
|
||||
Determines which controls can receive mouse input together with [member mouse_filter]. See [method get_mouse_filter_with_override]. Since the default behavior is [constant MOUSE_BEHAVIOR_INHERITED], this can be used to prevent all children controls from receiving mouse input.
|
||||
</member>
|
||||
<member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" enum="Control.CursorShape" default="0">
|
||||
The default cursor shape for this control. Useful for Godot plugins and applications or games that use the system's mouse cursors.
|
||||
[b]Note:[/b] On Linux, shapes may vary depending on the cursor theme of the system.
|
||||
</member>
|
||||
<member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" enum="Control.MouseFilter" default="0">
|
||||
Controls whether the control will be able to receive mouse button input events through [method _gui_input] and how these events should be handled. Also controls whether the control can receive the [signal mouse_entered], and [signal mouse_exited] signals. See the constants to learn what each does.
|
||||
Determines which controls will be able to receive mouse button input events through [method _gui_input] and the [signal mouse_entered], and [signal mouse_exited] signals. Also determines how these events should be propagated. See the constants to learn what each does. Use [method get_mouse_filter_with_override] to determine if a control can receive mouse input, since [member mouse_behavior_recursive] also affects it.
|
||||
</member>
|
||||
<member name="mouse_force_pass_scroll_events" type="bool" setter="set_force_pass_scroll_events" getter="is_force_pass_scroll_events" default="true">
|
||||
When enabled, scroll wheel events processed by [method _gui_input] will be passed to the parent control even if [member mouse_filter] is set to [constant MOUSE_FILTER_STOP].
|
||||
You should disable it on the root of your UI if you do not want scroll events to go to the [method Node._unhandled_input] processing.
|
||||
[b]Note:[/b] Because this property defaults to [code]true[/code], this allows nested scrollable containers to work out of the box.
|
||||
</member>
|
||||
<member name="mouse_recursive_behavior" type="int" setter="set_mouse_recursive_behavior" getter="get_mouse_recursive_behavior" enum="Control.RecursiveBehavior" default="0">
|
||||
Controls whether the recursive child nodes should have their [member mouse_filter] overridden to [constant MOUSE_FILTER_IGNORE] when evaluating input.
|
||||
</member>
|
||||
<member name="offset_bottom" type="float" setter="set_offset" getter="get_offset" default="0.0">
|
||||
Distance between the node's bottom edge and its parent control, based on [member anchor_bottom].
|
||||
Offsets are often controlled by one or multiple parent [Container] nodes, so you should not modify them manually if your node is a direct child of a [Container]. Offsets update automatically when you move or resize the node.
|
||||
|
@ -1198,14 +1198,23 @@
|
|||
<constant name="FOCUS_ACCESSIBILITY" value="3" enum="FocusMode">
|
||||
The node can grab focus only when screen reader is active. Use with [member focus_mode].
|
||||
</constant>
|
||||
<constant name="RECURSIVE_BEHAVIOR_INHERITED" value="0" enum="RecursiveBehavior">
|
||||
Inherits the associated behavior from the control's parent. This is the default for any newly created control.
|
||||
<constant name="FOCUS_BEHAVIOR_INHERITED" value="0" enum="FocusBehaviorRecursive">
|
||||
Inherits the [member focus_behavior_recursive] from the parent control. If there is no parent control, this is the same as [constant FOCUS_BEHAVIOR_ENABLED].
|
||||
</constant>
|
||||
<constant name="RECURSIVE_BEHAVIOR_DISABLED" value="1" enum="RecursiveBehavior">
|
||||
The current control and all its recursive child controls have their associated behavior disabled, regardless of the parent control's configuration.
|
||||
<constant name="FOCUS_BEHAVIOR_DISABLED" value="1" enum="FocusBehaviorRecursive">
|
||||
Prevents the control from getting focused. [method get_focus_mode_with_override] will return [constant FOCUS_NONE].
|
||||
</constant>
|
||||
<constant name="RECURSIVE_BEHAVIOR_ENABLED" value="2" enum="RecursiveBehavior">
|
||||
The current control and all its recursive child controls have their associated behavior enabled, regardless of the parent control's configuration.
|
||||
<constant name="FOCUS_BEHAVIOR_ENABLED" value="2" enum="FocusBehaviorRecursive">
|
||||
Allows the control to be focused, depending on the [member focus_mode]. This can be used to ignore the parent's [member focus_behavior_recursive]. [method get_focus_mode_with_override] will return the [member focus_mode].
|
||||
</constant>
|
||||
<constant name="MOUSE_BEHAVIOR_INHERITED" value="0" enum="MouseBehaviorRecursive">
|
||||
Inherits the [member mouse_behavior_recursive] from the parent control. If there is no parent control, this is the same as [constant MOUSE_BEHAVIOR_ENABLED].
|
||||
</constant>
|
||||
<constant name="MOUSE_BEHAVIOR_DISABLED" value="1" enum="MouseBehaviorRecursive">
|
||||
Prevents the control from receiving mouse input. [method get_mouse_filter_with_override] will return [constant MOUSE_FILTER_IGNORE].
|
||||
</constant>
|
||||
<constant name="MOUSE_BEHAVIOR_ENABLED" value="2" enum="MouseBehaviorRecursive">
|
||||
Allows the control to be receive mouse input, depending on the [member mouse_filter]. This can be used to ignore the parent's [member mouse_behavior_recursive]. [method get_mouse_filter_with_override] will return the [member mouse_filter].
|
||||
</constant>
|
||||
<constant name="NOTIFICATION_RESIZED" value="40">
|
||||
Sent when the node changes size. Use [member size] to get the new size.
|
||||
|
|
|
@ -2764,7 +2764,7 @@ TileSetAtlasSourceEditor::~TileSetAtlasSourceEditor() {
|
|||
|
||||
void EditorPropertyTilePolygon::_add_focusable_children(Node *p_node) {
|
||||
Control *control = Object::cast_to<Control>(p_node);
|
||||
if (control && control->get_focus_mode_with_recursive() != Control::FOCUS_NONE) {
|
||||
if (control && control->get_focus_mode_with_override() != Control::FOCUS_NONE) {
|
||||
add_focusable(control);
|
||||
}
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
|
|
|
@ -1891,44 +1891,67 @@ Control::MouseFilter Control::get_mouse_filter() const {
|
|||
return data.mouse_filter;
|
||||
}
|
||||
|
||||
Control::MouseFilter Control::get_mouse_filter_with_recursive() const {
|
||||
Control::MouseFilter Control::get_mouse_filter_with_override() const {
|
||||
ERR_READ_THREAD_GUARD_V(MOUSE_FILTER_IGNORE);
|
||||
if (_is_parent_mouse_disabled()) {
|
||||
if (!_is_mouse_filter_enabled()) {
|
||||
return MOUSE_FILTER_IGNORE;
|
||||
}
|
||||
return data.mouse_filter;
|
||||
}
|
||||
|
||||
void Control::set_mouse_recursive_behavior(RecursiveBehavior p_recursive_mouse_behavior) {
|
||||
void Control::set_mouse_behavior_recursive(MouseBehaviorRecursive p_mouse_behavior_recursive) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
ERR_FAIL_INDEX((int)p_recursive_mouse_behavior, 4);
|
||||
if (data.mouse_recursive_behavior == p_recursive_mouse_behavior) {
|
||||
ERR_FAIL_INDEX(p_mouse_behavior_recursive, 3);
|
||||
if (data.mouse_behavior_recursive == p_mouse_behavior_recursive) {
|
||||
return;
|
||||
}
|
||||
_set_mouse_recursive_behavior_ignore_cache(p_recursive_mouse_behavior);
|
||||
data.mouse_behavior_recursive = p_mouse_behavior_recursive;
|
||||
_update_mouse_behavior_recursive();
|
||||
}
|
||||
|
||||
void Control::_set_mouse_recursive_behavior_ignore_cache(RecursiveBehavior p_recursive_mouse_behavior) {
|
||||
data.mouse_recursive_behavior = p_recursive_mouse_behavior;
|
||||
if (p_recursive_mouse_behavior == RECURSIVE_BEHAVIOR_INHERITED) {
|
||||
Control *parent = get_parent_control();
|
||||
if (parent) {
|
||||
_propagate_mouse_behavior_recursively(parent->data.parent_mouse_recursive_behavior, false);
|
||||
Control::MouseBehaviorRecursive Control::get_mouse_behavior_recursive() const {
|
||||
ERR_READ_THREAD_GUARD_V(MOUSE_BEHAVIOR_INHERITED);
|
||||
return data.mouse_behavior_recursive;
|
||||
}
|
||||
|
||||
bool Control::_is_mouse_filter_enabled() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
if (data.mouse_behavior_recursive == MOUSE_BEHAVIOR_INHERITED) {
|
||||
if (data.parent_control) {
|
||||
return data.parent_mouse_behavior_recursive_enabled;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return data.mouse_behavior_recursive == MOUSE_BEHAVIOR_ENABLED;
|
||||
}
|
||||
|
||||
void Control::_update_mouse_behavior_recursive() {
|
||||
if (data.mouse_behavior_recursive == MOUSE_BEHAVIOR_INHERITED) {
|
||||
if (data.parent_control) {
|
||||
_propagate_mouse_behavior_recursive_recursively(data.parent_control->_is_mouse_filter_enabled(), false);
|
||||
} else {
|
||||
_propagate_mouse_behavior_recursively(RECURSIVE_BEHAVIOR_ENABLED, false);
|
||||
_propagate_mouse_behavior_recursive_recursively(true, false);
|
||||
}
|
||||
} else {
|
||||
_propagate_mouse_behavior_recursively(p_recursive_mouse_behavior, false);
|
||||
_propagate_mouse_behavior_recursive_recursively(data.mouse_behavior_recursive == MOUSE_BEHAVIOR_ENABLED, false);
|
||||
}
|
||||
|
||||
if (get_viewport()) {
|
||||
get_viewport()->_gui_update_mouse_over();
|
||||
}
|
||||
}
|
||||
|
||||
Control::RecursiveBehavior Control::get_mouse_recursive_behavior() const {
|
||||
ERR_READ_THREAD_GUARD_V(RECURSIVE_BEHAVIOR_INHERITED);
|
||||
return data.mouse_recursive_behavior;
|
||||
void Control::_propagate_mouse_behavior_recursive_recursively(bool p_enabled, bool p_skip_non_inherited) {
|
||||
if (p_skip_non_inherited && data.mouse_behavior_recursive != MOUSE_BEHAVIOR_INHERITED) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.parent_mouse_behavior_recursive_enabled = p_enabled;
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *control = Object::cast_to<Control>(get_child(i));
|
||||
if (control) {
|
||||
control->_propagate_mouse_behavior_recursive_recursively(p_enabled, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Control::set_force_pass_scroll_events(bool p_force_pass_scroll_events) {
|
||||
|
@ -2112,40 +2135,69 @@ Control::FocusMode Control::get_focus_mode() const {
|
|||
return data.focus_mode;
|
||||
}
|
||||
|
||||
Control::FocusMode Control::get_focus_mode_with_recursive() const {
|
||||
Control::FocusMode Control::get_focus_mode_with_override() const {
|
||||
ERR_READ_THREAD_GUARD_V(FOCUS_NONE);
|
||||
if (_is_focus_disabled_recursively()) {
|
||||
if (!_is_focus_mode_enabled()) {
|
||||
return FOCUS_NONE;
|
||||
}
|
||||
return data.focus_mode;
|
||||
}
|
||||
|
||||
void Control::set_focus_recursive_behavior(RecursiveBehavior p_recursive_focus_behavior) {
|
||||
void Control::set_focus_behavior_recursive(FocusBehaviorRecursive p_focus_behavior_recursive) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
ERR_FAIL_INDEX((int)p_recursive_focus_behavior, 4);
|
||||
if (data.focus_recursive_behavior == p_recursive_focus_behavior) {
|
||||
ERR_FAIL_INDEX((int)p_focus_behavior_recursive, 3);
|
||||
if (data.focus_behavior_recursive == p_focus_behavior_recursive) {
|
||||
return;
|
||||
}
|
||||
_set_focus_recursive_behavior_ignore_cache(p_recursive_focus_behavior);
|
||||
data.focus_behavior_recursive = p_focus_behavior_recursive;
|
||||
_update_focus_behavior_recursive();
|
||||
}
|
||||
|
||||
void Control::_set_focus_recursive_behavior_ignore_cache(RecursiveBehavior p_recursive_focus_behavior) {
|
||||
data.focus_recursive_behavior = p_recursive_focus_behavior;
|
||||
if (p_recursive_focus_behavior == RECURSIVE_BEHAVIOR_INHERITED) {
|
||||
Control::FocusBehaviorRecursive Control::get_focus_behavior_recursive() const {
|
||||
ERR_READ_THREAD_GUARD_V(FOCUS_BEHAVIOR_INHERITED);
|
||||
return data.focus_behavior_recursive;
|
||||
}
|
||||
|
||||
bool Control::_is_focus_mode_enabled() const {
|
||||
if (data.focus_behavior_recursive == FOCUS_BEHAVIOR_INHERITED) {
|
||||
if (data.parent_control) {
|
||||
return data.parent_focus_behavior_recursive_enabled;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return data.focus_behavior_recursive == FOCUS_BEHAVIOR_ENABLED;
|
||||
}
|
||||
|
||||
void Control::_update_focus_behavior_recursive() {
|
||||
if (data.focus_behavior_recursive == FOCUS_BEHAVIOR_INHERITED) {
|
||||
Control *parent = get_parent_control();
|
||||
if (parent) {
|
||||
_propagate_focus_behavior_recursively(parent->data.parent_focus_recursive_behavior, false);
|
||||
_propagate_focus_behavior_recursive_recursively(parent->_is_focus_mode_enabled(), false);
|
||||
} else {
|
||||
_propagate_focus_behavior_recursively(RECURSIVE_BEHAVIOR_ENABLED, false);
|
||||
_propagate_focus_behavior_recursive_recursively(true, false);
|
||||
}
|
||||
} else {
|
||||
_propagate_focus_behavior_recursively(p_recursive_focus_behavior, false);
|
||||
_propagate_focus_behavior_recursive_recursively(data.focus_behavior_recursive == FOCUS_BEHAVIOR_ENABLED, false);
|
||||
}
|
||||
}
|
||||
|
||||
Control::RecursiveBehavior Control::get_focus_recursive_behavior() const {
|
||||
ERR_READ_THREAD_GUARD_V(RECURSIVE_BEHAVIOR_INHERITED);
|
||||
return data.focus_recursive_behavior;
|
||||
void Control::_propagate_focus_behavior_recursive_recursively(bool p_enabled, bool p_skip_non_inherited) {
|
||||
if (is_inside_tree() && (data.focus_behavior_recursive == FOCUS_BEHAVIOR_DISABLED || (data.focus_behavior_recursive == FOCUS_BEHAVIOR_INHERITED && !p_enabled)) && has_focus()) {
|
||||
release_focus();
|
||||
}
|
||||
|
||||
if (p_skip_non_inherited && data.focus_behavior_recursive != FOCUS_BEHAVIOR_INHERITED) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.parent_focus_behavior_recursive_enabled = p_enabled;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *control = Object::cast_to<Control>(get_child(i));
|
||||
if (control) {
|
||||
control->_propagate_focus_behavior_recursive_recursively(p_enabled, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Control::has_focus() const {
|
||||
|
@ -2157,8 +2209,8 @@ void Control::grab_focus() {
|
|||
ERR_MAIN_THREAD_GUARD;
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
|
||||
if (data.focus_mode == FOCUS_NONE) {
|
||||
WARN_PRINT("This control can't grab focus. Use set_focus_mode() to allow a control to get focus.");
|
||||
if (get_focus_mode_with_override() == FOCUS_NONE) {
|
||||
WARN_PRINT("This control can't grab focus. Use set_focus_mode() and set_focus_behavior_recursive() to allow a control to get focus.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2218,7 +2270,7 @@ Control *Control::find_next_valid_focus() const {
|
|||
ERR_FAIL_NULL_V_MSG(n, nullptr, "Next focus node path is invalid: '" + data.focus_next + "'.");
|
||||
Control *c = Object::cast_to<Control>(n);
|
||||
ERR_FAIL_NULL_V_MSG(c, nullptr, "Next focus node is not a control: '" + n->get_name() + "'.");
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_recursive() != FOCUS_NONE) {
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_override() != FOCUS_NONE) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
@ -2285,7 +2337,7 @@ Control *Control::find_next_valid_focus() const {
|
|||
break;
|
||||
}
|
||||
|
||||
if ((next_child->get_focus_mode_with_recursive() == FOCUS_ALL) || (ac_enabled && next_child->get_focus_mode_with_recursive() == FOCUS_ACCESSIBILITY)) {
|
||||
if ((next_child->get_focus_mode_with_override() == FOCUS_ALL) || (ac_enabled && next_child->get_focus_mode_with_override() == FOCUS_ACCESSIBILITY)) {
|
||||
return next_child;
|
||||
}
|
||||
|
||||
|
@ -2322,7 +2374,7 @@ Control *Control::find_prev_valid_focus() const {
|
|||
ERR_FAIL_NULL_V_MSG(n, nullptr, "Previous focus node path is invalid: '" + data.focus_prev + "'.");
|
||||
Control *c = Object::cast_to<Control>(n);
|
||||
ERR_FAIL_NULL_V_MSG(c, nullptr, "Previous focus node is not a control: '" + n->get_name() + "'.");
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_recursive() != FOCUS_NONE) {
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_override() != FOCUS_NONE) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
@ -2383,7 +2435,7 @@ Control *Control::find_prev_valid_focus() const {
|
|||
}
|
||||
}
|
||||
|
||||
if ((prev_child->get_focus_mode_with_recursive() == FOCUS_ALL) || (ac_enabled && prev_child->get_focus_mode_with_recursive() == FOCUS_ACCESSIBILITY)) {
|
||||
if ((prev_child->get_focus_mode_with_override() == FOCUS_ALL) || (ac_enabled && prev_child->get_focus_mode_with_override() == FOCUS_ACCESSIBILITY)) {
|
||||
return prev_child;
|
||||
}
|
||||
|
||||
|
@ -2442,7 +2494,7 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) {
|
|||
ERR_FAIL_NULL_V_MSG(n, nullptr, "Neighbor focus node path is invalid: '" + data.focus_neighbor[p_side] + "'.");
|
||||
Control *c = Object::cast_to<Control>(n);
|
||||
ERR_FAIL_NULL_V_MSG(c, nullptr, "Neighbor focus node is not a control: '" + n->get_name() + "'.");
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_recursive() != FOCUS_NONE) {
|
||||
if (c->is_visible_in_tree() && c->get_focus_mode_with_override() != FOCUS_NONE) {
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -2551,64 +2603,6 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool Control::_is_focus_disabled_recursively() const {
|
||||
switch (data.focus_recursive_behavior) {
|
||||
case RECURSIVE_BEHAVIOR_INHERITED:
|
||||
return data.parent_focus_recursive_behavior == RECURSIVE_BEHAVIOR_DISABLED;
|
||||
case RECURSIVE_BEHAVIOR_DISABLED:
|
||||
return true;
|
||||
case RECURSIVE_BEHAVIOR_ENABLED:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Control::_propagate_focus_behavior_recursively(RecursiveBehavior p_focus_recursive_behavior, bool p_skip_non_inherited) {
|
||||
if (is_inside_tree() && (data.focus_recursive_behavior == RECURSIVE_BEHAVIOR_DISABLED || (data.focus_recursive_behavior == RECURSIVE_BEHAVIOR_INHERITED && p_focus_recursive_behavior == RECURSIVE_BEHAVIOR_DISABLED)) && has_focus()) {
|
||||
release_focus();
|
||||
}
|
||||
|
||||
if (p_skip_non_inherited && data.focus_recursive_behavior != RECURSIVE_BEHAVIOR_INHERITED) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.parent_focus_recursive_behavior = p_focus_recursive_behavior;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *control = Object::cast_to<Control>(get_child(i));
|
||||
if (control) {
|
||||
control->_propagate_focus_behavior_recursively(p_focus_recursive_behavior, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Control::_is_parent_mouse_disabled() const {
|
||||
switch (data.mouse_recursive_behavior) {
|
||||
case RECURSIVE_BEHAVIOR_INHERITED:
|
||||
return data.parent_mouse_recursive_behavior == RECURSIVE_BEHAVIOR_DISABLED;
|
||||
case RECURSIVE_BEHAVIOR_DISABLED:
|
||||
return true;
|
||||
case RECURSIVE_BEHAVIOR_ENABLED:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Control::_propagate_mouse_behavior_recursively(RecursiveBehavior p_mouse_recursive_behavior, bool p_skip_non_inherited) {
|
||||
if (p_skip_non_inherited && data.mouse_recursive_behavior != RECURSIVE_BEHAVIOR_INHERITED) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.parent_mouse_recursive_behavior = p_mouse_recursive_behavior;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *control = Object::cast_to<Control>(get_child(i));
|
||||
if (control) {
|
||||
control->_propagate_mouse_behavior_recursively(p_mouse_recursive_behavior, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Control *Control::find_valid_focus_neighbor(Side p_side) const {
|
||||
return const_cast<Control *>(this)->_get_focus_neighbor(p_side);
|
||||
}
|
||||
|
@ -2624,7 +2618,7 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons
|
|||
Container *container = Object::cast_to<Container>(p_at);
|
||||
bool in_container = container ? container->is_ancestor_of(this) : false;
|
||||
|
||||
if (c && c != this && ((c->get_focus_mode_with_recursive() == FOCUS_ALL) || (ac_enabled && c->get_focus_mode_with_recursive() == FOCUS_ACCESSIBILITY)) && !in_container && p_clamp.intersects(c->get_global_rect())) {
|
||||
if (c && c != this && ((c->get_focus_mode_with_override() == FOCUS_ALL) || (ac_enabled && c->get_focus_mode_with_override() == FOCUS_ACCESSIBILITY)) && !in_container && p_clamp.intersects(c->get_global_rect())) {
|
||||
Rect2 r_c = c->get_global_rect();
|
||||
r_c = r_c.intersection(p_clamp);
|
||||
real_t begin_d = p_dir.dot(r_c.get_position());
|
||||
|
@ -3627,8 +3621,8 @@ void Control::_notification(int p_notification) {
|
|||
|
||||
_update_layout_mode();
|
||||
|
||||
_set_focus_recursive_behavior_ignore_cache(data.focus_recursive_behavior);
|
||||
_set_mouse_recursive_behavior_ignore_cache(data.mouse_recursive_behavior);
|
||||
_update_focus_behavior_recursive();
|
||||
_update_mouse_behavior_recursive();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_UNPARENTED: {
|
||||
|
@ -3849,9 +3843,9 @@ void Control::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect);
|
||||
ClassDB::bind_method(D_METHOD("set_focus_mode", "mode"), &Control::set_focus_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_mode"), &Control::get_focus_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_mode_with_recursive"), &Control::get_focus_mode_with_recursive);
|
||||
ClassDB::bind_method(D_METHOD("set_focus_recursive_behavior", "focus_recursive_behavior"), &Control::set_focus_recursive_behavior);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_recursive_behavior"), &Control::get_focus_recursive_behavior);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_mode_with_override"), &Control::get_focus_mode_with_override);
|
||||
ClassDB::bind_method(D_METHOD("set_focus_behavior_recursive", "focus_behavior_recursive"), &Control::set_focus_behavior_recursive);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_behavior_recursive"), &Control::get_focus_behavior_recursive);
|
||||
ClassDB::bind_method(D_METHOD("has_focus"), &Control::has_focus);
|
||||
ClassDB::bind_method(D_METHOD("grab_focus"), &Control::grab_focus);
|
||||
ClassDB::bind_method(D_METHOD("release_focus"), &Control::release_focus);
|
||||
|
@ -3950,10 +3944,10 @@ 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("get_mouse_filter_with_recursive"), &Control::get_mouse_filter_with_recursive);
|
||||
ClassDB::bind_method(D_METHOD("get_mouse_filter_with_override"), &Control::get_mouse_filter_with_override);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_mouse_recursive_behavior", "mouse_recursive_behavior"), &Control::set_mouse_recursive_behavior);
|
||||
ClassDB::bind_method(D_METHOD("get_mouse_recursive_behavior"), &Control::get_mouse_recursive_behavior);
|
||||
ClassDB::bind_method(D_METHOD("set_mouse_behavior_recursive", "mouse_behavior_recursive"), &Control::set_mouse_behavior_recursive);
|
||||
ClassDB::bind_method(D_METHOD("get_mouse_behavior_recursive"), &Control::get_mouse_behavior_recursive);
|
||||
|
||||
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);
|
||||
|
@ -4050,11 +4044,11 @@ void Control::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "focus_next", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_next", "get_focus_next");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "focus_previous", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_previous", "get_focus_previous");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All,Accessibility"), "set_focus_mode", "get_focus_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_recursive_behavior", PROPERTY_HINT_ENUM, "Inherited,Disabled,Enabled"), "set_focus_recursive_behavior", "get_focus_recursive_behavior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_behavior_recursive", PROPERTY_HINT_ENUM, "Inherited,Disabled,Enabled"), "set_focus_behavior_recursive", "get_focus_behavior_recursive");
|
||||
|
||||
ADD_GROUP("Mouse", "mouse_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass (Propagate Up),Ignore"), "set_mouse_filter", "get_mouse_filter");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_recursive_behavior", PROPERTY_HINT_ENUM, "Inherited,Disabled,Enabled"), "set_mouse_recursive_behavior", "get_mouse_recursive_behavior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_behavior_recursive", PROPERTY_HINT_ENUM, "Inherited,Disabled,Enabled"), "set_mouse_behavior_recursive", "get_mouse_behavior_recursive");
|
||||
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");
|
||||
|
||||
|
@ -4070,9 +4064,13 @@ void Control::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(FOCUS_ALL);
|
||||
BIND_ENUM_CONSTANT(FOCUS_ACCESSIBILITY);
|
||||
|
||||
BIND_ENUM_CONSTANT(RECURSIVE_BEHAVIOR_INHERITED);
|
||||
BIND_ENUM_CONSTANT(RECURSIVE_BEHAVIOR_DISABLED);
|
||||
BIND_ENUM_CONSTANT(RECURSIVE_BEHAVIOR_ENABLED);
|
||||
BIND_ENUM_CONSTANT(FOCUS_BEHAVIOR_INHERITED);
|
||||
BIND_ENUM_CONSTANT(FOCUS_BEHAVIOR_DISABLED);
|
||||
BIND_ENUM_CONSTANT(FOCUS_BEHAVIOR_ENABLED);
|
||||
|
||||
BIND_ENUM_CONSTANT(MOUSE_BEHAVIOR_INHERITED);
|
||||
BIND_ENUM_CONSTANT(MOUSE_BEHAVIOR_DISABLED);
|
||||
BIND_ENUM_CONSTANT(MOUSE_BEHAVIOR_ENABLED);
|
||||
|
||||
BIND_CONSTANT(NOTIFICATION_RESIZED);
|
||||
BIND_CONSTANT(NOTIFICATION_MOUSE_ENTER);
|
||||
|
|
|
@ -68,10 +68,10 @@ public:
|
|||
FOCUS_ACCESSIBILITY,
|
||||
};
|
||||
|
||||
enum RecursiveBehavior {
|
||||
RECURSIVE_BEHAVIOR_INHERITED,
|
||||
RECURSIVE_BEHAVIOR_DISABLED,
|
||||
RECURSIVE_BEHAVIOR_ENABLED,
|
||||
enum FocusBehaviorRecursive {
|
||||
FOCUS_BEHAVIOR_INHERITED,
|
||||
FOCUS_BEHAVIOR_DISABLED,
|
||||
FOCUS_BEHAVIOR_ENABLED,
|
||||
};
|
||||
|
||||
enum SizeFlags {
|
||||
|
@ -90,6 +90,12 @@ public:
|
|||
MOUSE_FILTER_IGNORE
|
||||
};
|
||||
|
||||
enum MouseBehaviorRecursive {
|
||||
MOUSE_BEHAVIOR_INHERITED,
|
||||
MOUSE_BEHAVIOR_DISABLED,
|
||||
MOUSE_BEHAVIOR_ENABLED,
|
||||
};
|
||||
|
||||
enum CursorShape {
|
||||
CURSOR_ARROW,
|
||||
CURSOR_IBEAM,
|
||||
|
@ -197,8 +203,8 @@ private:
|
|||
real_t offset[4] = { 0.0, 0.0, 0.0, 0.0 };
|
||||
real_t anchor[4] = { ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN };
|
||||
FocusMode focus_mode = FOCUS_NONE;
|
||||
RecursiveBehavior parent_focus_recursive_behavior = RECURSIVE_BEHAVIOR_INHERITED;
|
||||
RecursiveBehavior focus_recursive_behavior = RECURSIVE_BEHAVIOR_INHERITED;
|
||||
FocusBehaviorRecursive focus_behavior_recursive = FOCUS_BEHAVIOR_INHERITED;
|
||||
bool parent_focus_behavior_recursive_enabled = false;
|
||||
GrowDirection h_grow = GROW_DIRECTION_END;
|
||||
GrowDirection v_grow = GROW_DIRECTION_END;
|
||||
|
||||
|
@ -227,8 +233,8 @@ private:
|
|||
// Input events and rendering.
|
||||
|
||||
MouseFilter mouse_filter = MOUSE_FILTER_STOP;
|
||||
RecursiveBehavior parent_mouse_recursive_behavior = RECURSIVE_BEHAVIOR_INHERITED;
|
||||
RecursiveBehavior mouse_recursive_behavior = RECURSIVE_BEHAVIOR_INHERITED;
|
||||
MouseBehaviorRecursive mouse_behavior_recursive = MOUSE_BEHAVIOR_INHERITED;
|
||||
bool parent_mouse_behavior_recursive_enabled = true;
|
||||
bool force_pass_scroll_events = true;
|
||||
|
||||
bool clip_contents = false;
|
||||
|
@ -325,17 +331,17 @@ private:
|
|||
|
||||
// Mouse Filter.
|
||||
|
||||
bool _is_parent_mouse_disabled() const;
|
||||
bool _is_mouse_filter_enabled() const;
|
||||
void _update_mouse_behavior_recursive();
|
||||
void _propagate_mouse_behavior_recursive_recursively(bool p_enabled, bool p_skip_non_inherited);
|
||||
|
||||
// Focus.
|
||||
|
||||
void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Rect2 &p_rect, const Rect2 &p_clamp, real_t p_min, real_t &r_closest_dist_squared, Control **r_closest);
|
||||
Control *_get_focus_neighbor(Side p_side, int p_count = 0);
|
||||
bool _is_focus_disabled_recursively() const;
|
||||
void _propagate_focus_behavior_recursively(RecursiveBehavior p_focus_recursive_behavior, bool p_force);
|
||||
void _propagate_mouse_behavior_recursively(RecursiveBehavior p_focus_recursive_behavior, bool p_force);
|
||||
void _set_mouse_recursive_behavior_ignore_cache(RecursiveBehavior p_recursive_mouse_behavior);
|
||||
void _set_focus_recursive_behavior_ignore_cache(RecursiveBehavior p_recursive_mouse_behavior);
|
||||
bool _is_focus_mode_enabled() const;
|
||||
void _update_focus_behavior_recursive();
|
||||
void _propagate_focus_behavior_recursive_recursively(bool p_enabled, bool p_skip_non_inherited);
|
||||
|
||||
// Theming.
|
||||
|
||||
|
@ -541,10 +547,10 @@ public:
|
|||
|
||||
void set_mouse_filter(MouseFilter p_filter);
|
||||
MouseFilter get_mouse_filter() const;
|
||||
MouseFilter get_mouse_filter_with_recursive() const;
|
||||
MouseFilter get_mouse_filter_with_override() const;
|
||||
|
||||
void set_mouse_recursive_behavior(RecursiveBehavior p_recursive_mouse_behavior);
|
||||
RecursiveBehavior get_mouse_recursive_behavior() const;
|
||||
void set_mouse_behavior_recursive(MouseBehaviorRecursive p_mouse_behavior_recursive);
|
||||
MouseBehaviorRecursive get_mouse_behavior_recursive() const;
|
||||
|
||||
void set_force_pass_scroll_events(bool p_force_pass_scroll_events);
|
||||
bool is_force_pass_scroll_events() const;
|
||||
|
@ -571,9 +577,9 @@ public:
|
|||
|
||||
void set_focus_mode(FocusMode p_focus_mode);
|
||||
FocusMode get_focus_mode() const;
|
||||
FocusMode get_focus_mode_with_recursive() const;
|
||||
void set_focus_recursive_behavior(RecursiveBehavior p_recursive_mouse_behavior);
|
||||
RecursiveBehavior get_focus_recursive_behavior() const;
|
||||
FocusMode get_focus_mode_with_override() const;
|
||||
void set_focus_behavior_recursive(FocusBehaviorRecursive p_focus_behavior_recursive);
|
||||
FocusBehaviorRecursive get_focus_behavior_recursive() const;
|
||||
bool has_focus() const;
|
||||
void grab_focus();
|
||||
void grab_click_focus();
|
||||
|
@ -695,7 +701,8 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Control::FocusMode);
|
||||
VARIANT_ENUM_CAST(Control::RecursiveBehavior);
|
||||
VARIANT_ENUM_CAST(Control::FocusBehaviorRecursive);
|
||||
VARIANT_ENUM_CAST(Control::MouseBehaviorRecursive);
|
||||
VARIANT_BITFIELD_CAST(Control::SizeFlags);
|
||||
VARIANT_ENUM_CAST(Control::CursorShape);
|
||||
VARIANT_ENUM_CAST(Control::LayoutPreset);
|
||||
|
|
|
@ -1421,7 +1421,7 @@ bool GraphEdit::_check_clickable_control(Control *p_control, const Vector2 &mpos
|
|||
control_rect.size *= zoom;
|
||||
control_rect.position += p_offset;
|
||||
|
||||
if (!control_rect.has_point(mpos) || p_control->get_mouse_filter_with_recursive() == MOUSE_FILTER_IGNORE) {
|
||||
if (!control_rect.has_point(mpos) || p_control->get_mouse_filter_with_override() == MOUSE_FILTER_IGNORE) {
|
||||
// Test children.
|
||||
for (int i = 0; i < p_control->get_child_count(); i++) {
|
||||
Control *child_rect = Object::cast_to<Control>(p_control->get_child(i));
|
||||
|
|
|
@ -89,12 +89,12 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
|
|||
}
|
||||
} else if (scrollable) {
|
||||
if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) {
|
||||
if (get_focus_mode_with_recursive() != FOCUS_NONE) {
|
||||
if (get_focus_mode_with_override() != FOCUS_NONE) {
|
||||
grab_focus();
|
||||
}
|
||||
set_value(get_value() + get_step());
|
||||
} else if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) {
|
||||
if (get_focus_mode_with_recursive() != FOCUS_NONE) {
|
||||
if (get_focus_mode_with_override() != FOCUS_NONE) {
|
||||
grab_focus();
|
||||
}
|
||||
set_value(get_value() - get_step());
|
||||
|
|
|
@ -773,7 +773,7 @@ void TabContainer::set_tab_focus_mode(Control::FocusMode p_focus_mode) {
|
|||
}
|
||||
|
||||
Control::FocusMode TabContainer::get_tab_focus_mode() const {
|
||||
return tab_bar->get_focus_mode_with_recursive();
|
||||
return tab_bar->get_focus_mode();
|
||||
}
|
||||
|
||||
void TabContainer::set_clip_tabs(bool p_clip_tabs) {
|
||||
|
|
|
@ -750,7 +750,7 @@ void Viewport::_process_picking() {
|
|||
#endif // PHYSICS_2D_DISABLED
|
||||
|
||||
SubViewportContainer *parent_svc = Object::cast_to<SubViewportContainer>(get_parent());
|
||||
bool parent_ignore_mouse = (parent_svc && parent_svc->get_mouse_filter_with_recursive() == Control::MOUSE_FILTER_IGNORE);
|
||||
bool parent_ignore_mouse = (parent_svc && parent_svc->get_mouse_filter_with_override() == Control::MOUSE_FILTER_IGNORE);
|
||||
bool create_passive_hover_event = true;
|
||||
if (gui.mouse_over || parent_ignore_mouse) {
|
||||
// When the mouse is over a Control node, passive hovering would cause input events for Colliders, that are behind Control nodes.
|
||||
|
@ -1546,7 +1546,7 @@ String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Cont
|
|||
|
||||
// Otherwise, we check parent controls unless some conditions prevent it.
|
||||
|
||||
if (p_control->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
|
||||
if (p_control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP) {
|
||||
break;
|
||||
}
|
||||
if (p_control->is_set_as_top_level()) {
|
||||
|
@ -1717,14 +1717,14 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
|
|||
while (ci) {
|
||||
Control *control = Object::cast_to<Control>(ci);
|
||||
if (control) {
|
||||
if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
|
||||
if (control->get_mouse_filter_with_override() != Control::MOUSE_FILTER_IGNORE) {
|
||||
control->_call_gui_input(ev);
|
||||
}
|
||||
|
||||
if (!control->is_inside_tree() || control->is_set_as_top_level()) {
|
||||
break;
|
||||
}
|
||||
if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP && is_pointer_event && !(is_scroll_event && control->data.force_pass_scroll_events)) {
|
||||
if (control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP && is_pointer_event && !(is_scroll_event && control->data.force_pass_scroll_events)) {
|
||||
// Mouse, ScreenDrag and ScreenTouch events are stopped by default with MOUSE_FILTER_STOP, unless we have a scroll event and force_pass_scroll_events set to true
|
||||
set_input_as_handled();
|
||||
break;
|
||||
|
@ -1750,7 +1750,7 @@ void Viewport::_gui_call_notification(Control *p_control, int p_what) {
|
|||
while (ci) {
|
||||
Control *control = Object::cast_to<Control>(ci);
|
||||
if (control) {
|
||||
if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
|
||||
if (control->get_mouse_filter_with_override() != Control::MOUSE_FILTER_IGNORE) {
|
||||
control->notification(p_what);
|
||||
}
|
||||
|
||||
|
@ -1761,7 +1761,7 @@ void Viewport::_gui_call_notification(Control *p_control, int p_what) {
|
|||
if (!control->is_inside_tree() || control->is_set_as_top_level()) {
|
||||
break;
|
||||
}
|
||||
if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
|
||||
if (control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1831,7 +1831,7 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
|
|||
}
|
||||
}
|
||||
|
||||
if (!c || c->data.mouse_filter == Control::MOUSE_FILTER_IGNORE) {
|
||||
if (!c || c->get_mouse_filter_with_override() == Control::MOUSE_FILTER_IGNORE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1863,7 +1863,7 @@ bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_che
|
|||
return true;
|
||||
}
|
||||
|
||||
if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
|
||||
if (control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1929,7 +1929,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
while (ci) {
|
||||
Control *control = Object::cast_to<Control>(ci);
|
||||
if (control) {
|
||||
if (control->get_focus_mode_with_recursive() != Control::FOCUS_NONE) {
|
||||
if (control->get_focus_mode_with_override() != Control::FOCUS_NONE) {
|
||||
// Grabbing unhovered focus can cause issues when mouse is dragged
|
||||
// with another button held down.
|
||||
if (control != gui.key_focus && gui.mouse_over_hierarchy.has(control)) {
|
||||
|
@ -1938,7 +1938,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
|
||||
if (control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2024,7 +2024,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
section_root->gui.global_dragging = false;
|
||||
}
|
||||
|
||||
if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
|
||||
if (control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2116,7 +2116,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
if (cursor_shape != Control::CURSOR_ARROW) {
|
||||
break;
|
||||
}
|
||||
if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP) {
|
||||
if (c->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP) {
|
||||
break;
|
||||
}
|
||||
if (c->is_set_as_top_level()) {
|
||||
|
@ -2550,7 +2550,7 @@ void Viewport::_gui_update_mouse_over() {
|
|||
int found = gui.mouse_over_hierarchy.find(ancestor_control);
|
||||
if (found >= 0) {
|
||||
// Remove the node if the propagation chain has been broken or it is now MOUSE_FILTER_IGNORE.
|
||||
if (removing || ancestor_control->get_mouse_filter_with_recursive() == Control::MOUSE_FILTER_IGNORE) {
|
||||
if (removing || ancestor_control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_IGNORE) {
|
||||
needs_exit.push_back(found);
|
||||
}
|
||||
}
|
||||
|
@ -2561,14 +2561,14 @@ void Viewport::_gui_update_mouse_over() {
|
|||
}
|
||||
reached_top = true;
|
||||
}
|
||||
if (!removing && ancestor_control->get_mouse_filter_with_recursive() != Control::MOUSE_FILTER_IGNORE) {
|
||||
if (!removing && ancestor_control->get_mouse_filter_with_override() != Control::MOUSE_FILTER_IGNORE) {
|
||||
new_mouse_over_hierarchy.push_back(ancestor_control);
|
||||
// Add the node if it was not found and it is now not MOUSE_FILTER_IGNORE.
|
||||
if (found < 0) {
|
||||
needs_enter.push_back(ancestor_control);
|
||||
}
|
||||
}
|
||||
if (ancestor_control->get_mouse_filter_with_recursive() == Control::MOUSE_FILTER_STOP) {
|
||||
if (ancestor_control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP) {
|
||||
// MOUSE_FILTER_STOP breaks the propagation chain.
|
||||
if (reached_top) {
|
||||
break;
|
||||
|
@ -3229,7 +3229,7 @@ void Viewport::_update_mouse_over(Vector2 p_pos) {
|
|||
while (ancestor) {
|
||||
Control *ancestor_control = Object::cast_to<Control>(ancestor);
|
||||
if (ancestor_control) {
|
||||
if (ancestor_control->get_mouse_filter_with_recursive() != Control::MOUSE_FILTER_IGNORE) {
|
||||
if (ancestor_control->get_mouse_filter_with_override() != Control::MOUSE_FILTER_IGNORE) {
|
||||
int found = gui.mouse_over_hierarchy.find(ancestor_control);
|
||||
if (found >= 0) {
|
||||
common_ancestor = gui.mouse_over_hierarchy[found];
|
||||
|
@ -3237,7 +3237,7 @@ void Viewport::_update_mouse_over(Vector2 p_pos) {
|
|||
}
|
||||
over_ancestors.push_back(ancestor_control);
|
||||
}
|
||||
if (ancestor_control->get_mouse_filter_with_recursive() == Control::MOUSE_FILTER_STOP) {
|
||||
if (ancestor_control->get_mouse_filter_with_override() == Control::MOUSE_FILTER_STOP) {
|
||||
// MOUSE_FILTER_STOP breaks the propagation chain.
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -138,6 +138,62 @@ TEST_CASE("[SceneTree][Control] Focus") {
|
|||
memdelete(child_ctrl);
|
||||
}
|
||||
|
||||
SUBCASE("[SceneTree][Control] Grab focus with focus behavior recursive") {
|
||||
CHECK_UNARY_FALSE(ctrl->has_focus());
|
||||
|
||||
// Cannot grab focus if focus behavior is disabled.
|
||||
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
|
||||
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_DISABLED);
|
||||
|
||||
ERR_PRINT_OFF
|
||||
ctrl->grab_focus();
|
||||
ERR_PRINT_ON
|
||||
CHECK_UNARY_FALSE(ctrl->has_focus());
|
||||
|
||||
// Cannot grab focus if focus behavior is enabled but focus mode is none.
|
||||
ctrl->set_focus_mode(Control::FocusMode::FOCUS_NONE);
|
||||
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_ENABLED);
|
||||
|
||||
ERR_PRINT_OFF
|
||||
ctrl->grab_focus();
|
||||
ERR_PRINT_ON
|
||||
CHECK_UNARY_FALSE(ctrl->has_focus());
|
||||
|
||||
// Can grab focus if focus behavior is enabled and focus mode is all.
|
||||
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
|
||||
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_ENABLED);
|
||||
|
||||
ctrl->grab_focus();
|
||||
CHECK_UNARY(ctrl->has_focus());
|
||||
}
|
||||
|
||||
SUBCASE("[SceneTree][Control] Children focus with focus behavior recursive") {
|
||||
Control *child_control = memnew(Control);
|
||||
ctrl->add_child(child_control);
|
||||
|
||||
// Can grab focus on child if parent focus behavior is inherit.
|
||||
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
|
||||
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_INHERITED);
|
||||
child_control->set_focus_mode(Control::FocusMode::FOCUS_ALL);
|
||||
child_control->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_INHERITED);
|
||||
|
||||
child_control->grab_focus();
|
||||
CHECK_UNARY(child_control->has_focus());
|
||||
|
||||
// Cannot grab focus on child if parent focus behavior is disabled.
|
||||
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
|
||||
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_DISABLED);
|
||||
child_control->set_focus_mode(Control::FocusMode::FOCUS_ALL);
|
||||
child_control->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_INHERITED);
|
||||
|
||||
ERR_PRINT_OFF
|
||||
child_control->grab_focus();
|
||||
ERR_PRINT_ON
|
||||
CHECK_UNARY_FALSE(child_control->has_focus());
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
memdelete(ctrl);
|
||||
}
|
||||
|
||||
|
|
|
@ -512,6 +512,45 @@ TEST_CASE("[SceneTree][Viewport] Controls and InputEvent handling") {
|
|||
CHECK_FALSE(node_d->invalid_order);
|
||||
}
|
||||
|
||||
SUBCASE("[Viewport][GuiInputEvent] Mouse behavior recursive disables mouse motion events.") {
|
||||
node_i->set_mouse_filter(Control::MOUSE_FILTER_PASS);
|
||||
|
||||
// Enabled when parent is set to inherit.
|
||||
node_h->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_INHERITED);
|
||||
node_i->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_INHERITED);
|
||||
SEND_GUI_MOUSE_MOTION_EVENT(on_i, MouseButtonMask::NONE, Key::NONE);
|
||||
CHECK(node_i->mouse_over);
|
||||
CHECK(node_i->mouse_over_self);
|
||||
|
||||
// Enabled when parent is set to enabled.
|
||||
node_h->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_ENABLED);
|
||||
node_i->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_INHERITED);
|
||||
SEND_GUI_MOUSE_MOTION_EVENT(on_i, MouseButtonMask::NONE, Key::NONE);
|
||||
CHECK(node_i->mouse_over);
|
||||
CHECK(node_i->mouse_over_self);
|
||||
|
||||
// Disabled when parent is set to disabled.
|
||||
node_h->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_DISABLED);
|
||||
node_i->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_INHERITED);
|
||||
SEND_GUI_MOUSE_MOTION_EVENT(on_i, MouseButtonMask::NONE, Key::NONE);
|
||||
CHECK_FALSE(node_i->mouse_over);
|
||||
CHECK_FALSE(node_i->mouse_over_self);
|
||||
|
||||
// Enabled when set to enabled and parent is set to disabled.
|
||||
node_h->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_DISABLED);
|
||||
node_i->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_ENABLED);
|
||||
SEND_GUI_MOUSE_MOTION_EVENT(on_i, MouseButtonMask::NONE, Key::NONE);
|
||||
CHECK(node_i->mouse_over);
|
||||
CHECK(node_i->mouse_over_self);
|
||||
|
||||
// Disabled when it is set to disabled.
|
||||
node_h->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_ENABLED);
|
||||
node_i->set_mouse_behavior_recursive(Control::MOUSE_BEHAVIOR_DISABLED);
|
||||
SEND_GUI_MOUSE_MOTION_EVENT(on_i, MouseButtonMask::NONE, Key::NONE);
|
||||
CHECK_FALSE(node_i->mouse_over);
|
||||
CHECK_FALSE(node_i->mouse_over_self);
|
||||
}
|
||||
|
||||
SUBCASE("[Viewport][GuiInputEvent] Mouse Enter/Exit notification propagation.") {
|
||||
node_d->set_mouse_filter(Control::MOUSE_FILTER_PASS);
|
||||
node_g->set_mouse_filter(Control::MOUSE_FILTER_PASS);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue