@@ -1224,14 +1224,16 @@ Ref<World2D> Viewport::find_world_2d() const {
1224
1224
}
1225
1225
}
1226
1226
1227
- void Viewport::_propagate_viewport_notification (Node *p_node, int p_what) {
1227
+ void Viewport::_propagate_drag_notification (Node *p_node, int p_what) {
1228
+ // Send notification to p_node and all children and descendant nodes of p_node, except to SubViewports which are not children of a SubViewportContainer.
1228
1229
p_node->notification (p_what);
1230
+ bool is_svc = Object::cast_to<SubViewportContainer>(p_node);
1229
1231
for (int i = 0 ; i < p_node->get_child_count (); i++) {
1230
1232
Node *c = p_node->get_child (i);
1231
- if (Object::cast_to<Viewport >(c)) {
1233
+ if (!is_svc && Object::cast_to<SubViewport >(c)) {
1232
1234
continue ;
1233
1235
}
1234
- _propagate_viewport_notification (c, p_what);
1236
+ Viewport::_propagate_drag_notification (c, p_what);
1235
1237
}
1236
1238
}
1237
1239
@@ -1334,7 +1336,7 @@ Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) {
1334
1336
1335
1337
Vector2 Viewport::get_mouse_position () const {
1336
1338
ERR_READ_THREAD_GUARD_V (Vector2 ());
1337
- if (! is_directly_attached_to_screen ()) {
1339
+ if (get_section_root_viewport () != SceneTree::get_singleton ()-> get_root ()) {
1338
1340
// Rely on the most recent mouse coordinate from an InputEventMouse in push_input.
1339
1341
// In this case get_screen_transform is not applicable, because it is ambiguous.
1340
1342
return gui.last_mouse_pos ;
@@ -1689,14 +1691,15 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
1689
1691
}
1690
1692
1691
1693
bool Viewport::_gui_drop (Control *p_at_control, Point2 p_at_pos, bool p_just_check) {
1692
- // Attempt grab , try parent controls too.
1694
+ // Attempt drop , try parent controls too.
1693
1695
CanvasItem *ci = p_at_control;
1696
+ Viewport *section_root = get_section_root_viewport ();
1694
1697
while (ci) {
1695
1698
Control *control = Object::cast_to<Control>(ci);
1696
1699
if (control) {
1697
- if (control->can_drop_data (p_at_pos, gui.drag_data )) {
1700
+ if (control->can_drop_data (p_at_pos, section_root-> gui .drag_data )) {
1698
1701
if (!p_just_check) {
1699
- control->drop_data (p_at_pos, gui.drag_data );
1702
+ control->drop_data (p_at_pos, section_root-> gui .drag_data );
1700
1703
}
1701
1704
1702
1705
return true ;
@@ -1794,13 +1797,13 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1794
1797
1795
1798
if (gui.dragging && mb->get_button_index () == MouseButton::LEFT) {
1796
1799
// Alternate drop use (when using force_drag(), as proposed by #5342).
1797
- _perform_drop (gui.mouse_focus , pos );
1800
+ _perform_drop (gui.mouse_focus );
1798
1801
}
1799
1802
1800
1803
_gui_cancel_tooltip ();
1801
1804
} else {
1802
1805
if (gui.dragging && mb->get_button_index () == MouseButton::LEFT) {
1803
- _perform_drop (gui.drag_mouse_over , gui. drag_mouse_over_pos );
1806
+ _perform_drop (gui.drag_mouse_over );
1804
1807
}
1805
1808
1806
1809
gui.mouse_focus_mask .clear_flag (mouse_button_to_mask (mb->get_button_index ())); // Remove from mask.
@@ -1837,7 +1840,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1837
1840
Point2 mpos = mm->get_position ();
1838
1841
1839
1842
// Drag & drop.
1840
- if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask ().has_flag (MouseButtonMask::LEFT))) {
1843
+ Viewport *section_root = get_section_root_viewport ();
1844
+ if (!gui.drag_attempted && gui.mouse_focus && section_root && !section_root->gui .global_dragging && (mm->get_button_mask ().has_flag (MouseButtonMask::LEFT))) {
1841
1845
gui.drag_accum += mm->get_relative ();
1842
1846
float len = gui.drag_accum .length ();
1843
1847
if (len > 10 ) {
@@ -1846,12 +1850,13 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1846
1850
while (ci) {
1847
1851
Control *control = Object::cast_to<Control>(ci);
1848
1852
if (control) {
1849
- gui.dragging = true ;
1850
- gui.drag_data = control->get_drag_data (control->get_global_transform_with_canvas ().affine_inverse ().xform (mpos - gui.drag_accum ));
1851
- if (gui.drag_data .get_type () != Variant::NIL) {
1853
+ section_root-> gui .global_dragging = true ;
1854
+ section_root-> gui .drag_data = control->get_drag_data (control->get_global_transform_with_canvas ().affine_inverse ().xform (mpos - gui.drag_accum ));
1855
+ if (section_root-> gui .drag_data .get_type () != Variant::NIL) {
1852
1856
gui.mouse_focus = nullptr ;
1853
1857
gui.forced_mouse_focus = false ;
1854
1858
gui.mouse_focus_mask .clear ();
1859
+ gui.dragging = true ;
1855
1860
break ;
1856
1861
} else {
1857
1862
Control *drag_preview = _gui_get_drag_preview ();
@@ -1860,7 +1865,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1860
1865
memdelete (drag_preview);
1861
1866
gui.drag_preview_id = ObjectID ();
1862
1867
}
1863
- gui.dragging = false ;
1868
+ section_root-> gui .global_dragging = false ;
1864
1869
}
1865
1870
1866
1871
if (control->data .mouse_filter == Control::MOUSE_FILTER_STOP) {
@@ -1878,7 +1883,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1878
1883
1879
1884
gui.drag_attempted = true ;
1880
1885
if (gui.dragging ) {
1881
- _propagate_viewport_notification ( this , NOTIFICATION_DRAG_BEGIN);
1886
+ Viewport::_propagate_drag_notification (section_root , NOTIFICATION_DRAG_BEGIN);
1882
1887
}
1883
1888
}
1884
1889
}
@@ -1971,105 +1976,29 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1971
1976
}
1972
1977
1973
1978
if (gui.dragging ) {
1974
- // Handle drag & drop.
1979
+ // Handle drag & drop. This happens in the viewport where dragging started.
1975
1980
1976
1981
Control *drag_preview = _gui_get_drag_preview ();
1977
1982
if (drag_preview) {
1978
1983
drag_preview->set_position (mpos);
1979
1984
}
1980
1985
1981
- gui.drag_mouse_over = over;
1982
- gui.drag_mouse_over_pos = Vector2 ();
1983
-
1984
- // Find the window this is above of.
1985
- // See if there is an embedder.
1986
- Viewport *embedder = nullptr ;
1987
- Vector2 viewport_pos;
1988
-
1989
- if (is_embedding_subwindows ()) {
1990
- embedder = this ;
1991
- viewport_pos = mpos;
1992
- } else {
1993
- // Not an embedder, but may be a subwindow of an embedder.
1994
- Window *w = Object::cast_to<Window>(this );
1995
- if (w) {
1996
- if (w->is_embedded ()) {
1997
- embedder = w->get_embedder ();
1998
-
1999
- viewport_pos = get_final_transform ().xform (mpos) + w->get_position (); // To parent coords.
2000
- }
2001
- }
2002
- }
2003
-
2004
- Viewport *viewport_under = nullptr ;
2005
-
2006
- if (embedder) {
2007
- // Use embedder logic.
2008
-
2009
- for (int i = embedder->gui .sub_windows .size () - 1 ; i >= 0 ; i--) {
2010
- Window *sw = embedder->gui .sub_windows [i].window ;
2011
- Rect2 swrect = Rect2i (sw->get_position (), sw->get_size ());
2012
- if (!sw->get_flag (Window::FLAG_BORDERLESS)) {
2013
- int title_height = sw->theme_cache .title_height ;
2014
- swrect.position .y -= title_height;
2015
- swrect.size .y += title_height;
2016
- }
2017
-
2018
- if (swrect.has_point (viewport_pos)) {
2019
- viewport_under = sw;
2020
- viewport_pos -= sw->get_position ();
2021
- }
2022
- }
2023
-
2024
- if (!viewport_under) {
2025
- // Not in a subwindow, likely in embedder.
2026
- viewport_under = embedder;
2027
- }
2028
- } else {
2029
- // Use DisplayServer logic.
2030
- Vector2i screen_mouse_pos = DisplayServer::get_singleton ()->mouse_get_position ();
2031
-
2032
- DisplayServer::WindowID window_id = DisplayServer::get_singleton ()->get_window_at_screen_position (screen_mouse_pos);
2033
-
2034
- if (window_id != DisplayServer::INVALID_WINDOW_ID) {
2035
- ObjectID object_under = DisplayServer::get_singleton ()->window_get_attached_instance_id (window_id);
2036
-
2037
- if (object_under != ObjectID ()) { // Fetch window.
2038
- Window *w = Object::cast_to<Window>(ObjectDB::get_instance (object_under));
2039
- if (w) {
2040
- viewport_under = w;
2041
- viewport_pos = w->get_final_transform ().affine_inverse ().xform (screen_mouse_pos - w->get_position ());
2042
- }
2043
- }
1986
+ gui.drag_mouse_over = section_root->gui .target_control ;
1987
+ if (gui.drag_mouse_over ) {
1988
+ if (!_gui_drop (gui.drag_mouse_over , gui.drag_mouse_over ->get_local_mouse_position (), true )) {
1989
+ gui.drag_mouse_over = nullptr ;
2044
1990
}
2045
- }
2046
-
2047
- if (viewport_under) {
2048
- if (viewport_under != this ) {
2049
- Transform2D ai = viewport_under->get_final_transform ().affine_inverse ();
2050
- viewport_pos = ai.xform (viewport_pos);
2051
- }
2052
- // Find control under at position.
2053
- gui.drag_mouse_over = viewport_under->gui_find_control (viewport_pos);
2054
1991
if (gui.drag_mouse_over ) {
2055
- Transform2D localizer = gui.drag_mouse_over ->get_global_transform_with_canvas ().affine_inverse ();
2056
- gui.drag_mouse_over_pos = localizer.xform (viewport_pos);
2057
-
2058
- bool can_drop = _gui_drop (gui.drag_mouse_over , gui.drag_mouse_over_pos , true );
2059
-
2060
- if (!can_drop) {
2061
- ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN;
2062
- } else {
2063
- ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP;
2064
- }
1992
+ ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP;
1993
+ } else {
1994
+ ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN;
2065
1995
}
2066
-
2067
- } else {
2068
- gui.drag_mouse_over = nullptr ;
2069
1996
}
2070
1997
}
2071
1998
2072
- if (DisplayServer::get_singleton ()->has_feature (DisplayServer::FEATURE_CURSOR_SHAPE) && !Object::cast_to<SubViewportContainer>(over)) {
1999
+ if (DisplayServer::get_singleton ()->has_feature (DisplayServer::FEATURE_CURSOR_SHAPE) && (gui.dragging || (!section_root->gui .global_dragging && !Object::cast_to<SubViewportContainer>(over)))) {
2000
+ // If dragging is active, then set the cursor shape only from the Viewport where dragging started.
2001
+ // If dragging is inactive, then set the cursor shape only when not over a SubViewportContainer.
2073
2002
DisplayServer::get_singleton ()->cursor_set_shape (ds_cursor_shape);
2074
2003
}
2075
2004
}
@@ -2269,10 +2198,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
2269
2198
}
2270
2199
}
2271
2200
2272
- void Viewport::_perform_drop (Control *p_control, Point2 p_pos ) {
2201
+ void Viewport::_perform_drop (Control *p_control) {
2273
2202
// Without any arguments, simply cancel Drag and Drop.
2274
2203
if (p_control) {
2275
- gui.drag_successful = _gui_drop (p_control, p_pos , false );
2204
+ gui.drag_successful = _gui_drop (p_control, p_control-> get_local_mouse_position () , false );
2276
2205
} else {
2277
2206
gui.drag_successful = false ;
2278
2207
}
@@ -2283,10 +2212,12 @@ void Viewport::_perform_drop(Control *p_control, Point2 p_pos) {
2283
2212
gui.drag_preview_id = ObjectID ();
2284
2213
}
2285
2214
2286
- gui.drag_data = Variant ();
2215
+ Viewport *section_root = get_section_root_viewport ();
2216
+ section_root->gui .drag_data = Variant ();
2287
2217
gui.dragging = false ;
2218
+ section_root->gui .global_dragging = false ;
2288
2219
gui.drag_mouse_over = nullptr ;
2289
- _propagate_viewport_notification ( this , NOTIFICATION_DRAG_END);
2220
+ Viewport::_propagate_drag_notification (section_root , NOTIFICATION_DRAG_END);
2290
2221
// Display the new cursor shape instantly.
2291
2222
update_mouse_cursor_state ();
2292
2223
}
@@ -2316,14 +2247,16 @@ void Viewport::_gui_force_drag(Control *p_base, const Variant &p_data, Control *
2316
2247
ERR_FAIL_COND_MSG (p_data.get_type () == Variant::NIL, " Drag data must be a value." );
2317
2248
2318
2249
gui.dragging = true ;
2319
- gui.drag_data = p_data;
2250
+ Viewport *section_root = get_section_root_viewport ();
2251
+ section_root->gui .global_dragging = true ;
2252
+ section_root->gui .drag_data = p_data;
2320
2253
gui.mouse_focus = nullptr ;
2321
2254
gui.mouse_focus_mask .clear ();
2322
2255
2323
2256
if (p_control) {
2324
2257
_gui_set_drag_preview (p_base, p_control);
2325
2258
}
2326
- _propagate_viewport_notification ( this , NOTIFICATION_DRAG_BEGIN);
2259
+ Viewport::_propagate_drag_notification (section_root , NOTIFICATION_DRAG_BEGIN);
2327
2260
}
2328
2261
2329
2262
void Viewport::_gui_set_drag_preview (Control *p_base, Control *p_control) {
@@ -3005,6 +2938,7 @@ void Viewport::_update_mouse_over() {
3005
2938
}
3006
2939
3007
2940
void Viewport::_update_mouse_over (Vector2 p_pos) {
2941
+ gui.last_mouse_pos = p_pos; // Necessary, because mouse cursor can be over Viewports that are not reached by the InputEvent.
3008
2942
// Look for embedded windows at mouse position.
3009
2943
if (is_embedding_subwindows ()) {
3010
2944
for (int i = gui.sub_windows .size () - 1 ; i >= 0 ; i--) {
@@ -3056,6 +2990,7 @@ void Viewport::_update_mouse_over(Vector2 p_pos) {
3056
2990
3057
2991
// Look for Controls at mouse position.
3058
2992
Control *over = gui_find_control (p_pos);
2993
+ get_section_root_viewport ()->gui .target_control = over;
3059
2994
bool notify_embedded_viewports = false ;
3060
2995
if (over != gui.mouse_over || (!over && !gui.mouse_over_hierarchy .is_empty ())) {
3061
2996
// Find the common ancestor of `gui.mouse_over` and `over`.
@@ -3178,6 +3113,10 @@ void Viewport::_drop_mouse_over(Control *p_until_control) {
3178
3113
if (gui.mouse_over && gui.mouse_over ->is_inside_tree ()) {
3179
3114
gui.mouse_over ->notification (Control::NOTIFICATION_MOUSE_EXIT_SELF);
3180
3115
}
3116
+ Viewport *section_root = get_section_root_viewport ();
3117
+ if (section_root && section_root->gui .target_control == gui.mouse_over ) {
3118
+ section_root->gui .target_control = nullptr ;
3119
+ }
3181
3120
gui.mouse_over = nullptr ;
3182
3121
3183
3122
// Send Mouse Exit notifications to children first. Don't send to p_until_control or above.
@@ -3386,7 +3325,7 @@ bool Viewport::is_input_disabled() const {
3386
3325
3387
3326
Variant Viewport::gui_get_drag_data () const {
3388
3327
ERR_READ_THREAD_GUARD_V (Variant ());
3389
- return gui.drag_data ;
3328
+ return get_section_root_viewport ()-> gui .drag_data ;
3390
3329
}
3391
3330
3392
3331
PackedStringArray Viewport::get_configuration_warnings () const {
@@ -3580,7 +3519,7 @@ bool Viewport::is_snap_2d_vertices_to_pixel_enabled() const {
3580
3519
3581
3520
bool Viewport::gui_is_dragging () const {
3582
3521
ERR_READ_THREAD_GUARD_V (false );
3583
- return gui.dragging ;
3522
+ return get_section_root_viewport ()-> gui .global_dragging ;
3584
3523
}
3585
3524
3586
3525
bool Viewport::gui_is_drag_successful () const {
@@ -5110,9 +5049,12 @@ Transform2D SubViewport::get_popup_base_transform() const {
5110
5049
return c->get_screen_transform () * container_transform * get_final_transform ();
5111
5050
}
5112
5051
5113
- bool SubViewport::is_directly_attached_to_screen () const {
5114
- // SubViewports, that are used as Textures are not considered to be directly attached to screen.
5115
- return Object::cast_to<SubViewportContainer>(get_parent ()) && get_parent ()->get_viewport () && get_parent ()->get_viewport ()->is_directly_attached_to_screen ();
5052
+ Viewport *SubViewport::get_section_root_viewport () const {
5053
+ if (Object::cast_to<SubViewportContainer>(get_parent ()) && get_parent ()->get_viewport ()) {
5054
+ return get_parent ()->get_viewport ()->get_section_root_viewport ();
5055
+ }
5056
+ SubViewport *vp = const_cast <SubViewport *>(this );
5057
+ return vp;
5116
5058
}
5117
5059
5118
5060
bool SubViewport::is_attached_in_viewport () const {
0 commit comments