@@ -1235,14 +1235,16 @@ Ref<World2D> Viewport::find_world_2d() const {
1235
1235
}
1236
1236
}
1237
1237
1238
- void Viewport::_propagate_viewport_notification (Node *p_node, int p_what) {
1238
+ void Viewport::_propagate_drag_notification (Node *p_node, int p_what) {
1239
+ // Send notification to p_node and all children and descendant nodes of p_node, except to SubViewports which are not children of a SubViewportContainer.
1239
1240
p_node->notification (p_what);
1241
+ bool is_svc = Object::cast_to<SubViewportContainer>(p_node);
1240
1242
for (int i = 0 ; i < p_node->get_child_count (); i++) {
1241
1243
Node *c = p_node->get_child (i);
1242
- if (Object::cast_to<Viewport >(c)) {
1244
+ if (!is_svc && Object::cast_to<SubViewport >(c)) {
1243
1245
continue ;
1244
1246
}
1245
- _propagate_viewport_notification (c, p_what);
1247
+ Viewport::_propagate_drag_notification (c, p_what);
1246
1248
}
1247
1249
}
1248
1250
@@ -1345,7 +1347,7 @@ Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) {
1345
1347
1346
1348
Vector2 Viewport::get_mouse_position () const {
1347
1349
ERR_READ_THREAD_GUARD_V (Vector2 ());
1348
- if (! is_directly_attached_to_screen ()) {
1350
+ if (get_section_root_viewport () != SceneTree::get_singleton ()-> get_root ()) {
1349
1351
// Rely on the most recent mouse coordinate from an InputEventMouse in push_input.
1350
1352
// In this case get_screen_transform is not applicable, because it is ambiguous.
1351
1353
return gui.last_mouse_pos ;
@@ -1701,14 +1703,15 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
1701
1703
}
1702
1704
1703
1705
bool Viewport::_gui_drop (Control *p_at_control, Point2 p_at_pos, bool p_just_check) {
1704
- // Attempt grab , try parent controls too.
1706
+ // Attempt drop , try parent controls too.
1705
1707
CanvasItem *ci = p_at_control;
1708
+ Viewport *section_root = get_section_root_viewport ();
1706
1709
while (ci) {
1707
1710
Control *control = Object::cast_to<Control>(ci);
1708
1711
if (control) {
1709
- if (control->can_drop_data (p_at_pos, gui.drag_data )) {
1712
+ if (control->can_drop_data (p_at_pos, section_root-> gui .drag_data )) {
1710
1713
if (!p_just_check) {
1711
- control->drop_data (p_at_pos, gui.drag_data );
1714
+ control->drop_data (p_at_pos, section_root-> gui .drag_data );
1712
1715
}
1713
1716
1714
1717
return true ;
@@ -1806,13 +1809,13 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1806
1809
1807
1810
if (gui.dragging && mb->get_button_index () == MouseButton::LEFT) {
1808
1811
// Alternate drop use (when using force_drag(), as proposed by #5342).
1809
- _perform_drop (gui.mouse_focus , pos );
1812
+ _perform_drop (gui.mouse_focus );
1810
1813
}
1811
1814
1812
1815
_gui_cancel_tooltip ();
1813
1816
} else {
1814
1817
if (gui.dragging && mb->get_button_index () == MouseButton::LEFT) {
1815
- _perform_drop (gui.drag_mouse_over , gui. drag_mouse_over_pos );
1818
+ _perform_drop (gui.drag_mouse_over );
1816
1819
}
1817
1820
1818
1821
gui.mouse_focus_mask .clear_flag (mouse_button_to_mask (mb->get_button_index ())); // Remove from mask.
@@ -1848,7 +1851,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1848
1851
Point2 mpos = mm->get_position ();
1849
1852
1850
1853
// Drag & drop.
1851
- if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask ().has_flag (MouseButtonMask::LEFT))) {
1854
+ Viewport *section_root = get_section_root_viewport ();
1855
+ if (!gui.drag_attempted && gui.mouse_focus && section_root && !section_root->gui .global_dragging && (mm->get_button_mask ().has_flag (MouseButtonMask::LEFT))) {
1852
1856
gui.drag_accum += mm->get_relative ();
1853
1857
float len = gui.drag_accum .length ();
1854
1858
if (len > 10 ) {
@@ -1857,11 +1861,12 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1857
1861
while (ci) {
1858
1862
Control *control = Object::cast_to<Control>(ci);
1859
1863
if (control) {
1860
- gui.dragging = true ;
1861
- gui.drag_data = control->get_drag_data (control->get_global_transform_with_canvas ().affine_inverse ().xform (mpos - gui.drag_accum ));
1862
- if (gui.drag_data .get_type () != Variant::NIL) {
1864
+ section_root-> gui .global_dragging = true ;
1865
+ section_root-> gui .drag_data = control->get_drag_data (control->get_global_transform_with_canvas ().affine_inverse ().xform (mpos - gui.drag_accum ));
1866
+ if (section_root-> gui .drag_data .get_type () != Variant::NIL) {
1863
1867
gui.mouse_focus = nullptr ;
1864
1868
gui.mouse_focus_mask .clear ();
1869
+ gui.dragging = true ;
1865
1870
break ;
1866
1871
} else {
1867
1872
Control *drag_preview = _gui_get_drag_preview ();
@@ -1870,7 +1875,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1870
1875
memdelete (drag_preview);
1871
1876
gui.drag_preview_id = ObjectID ();
1872
1877
}
1873
- gui.dragging = false ;
1878
+ section_root-> gui .global_dragging = false ;
1874
1879
}
1875
1880
1876
1881
if (control->data .mouse_filter == Control::MOUSE_FILTER_STOP) {
@@ -1888,7 +1893,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1888
1893
1889
1894
gui.drag_attempted = true ;
1890
1895
if (gui.dragging ) {
1891
- _propagate_viewport_notification ( this , NOTIFICATION_DRAG_BEGIN);
1896
+ Viewport::_propagate_drag_notification (section_root , NOTIFICATION_DRAG_BEGIN);
1892
1897
}
1893
1898
}
1894
1899
}
@@ -1986,105 +1991,29 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1986
1991
}
1987
1992
1988
1993
if (gui.dragging ) {
1989
- // Handle drag & drop.
1994
+ // Handle drag & drop. This happens in the viewport where dragging started.
1990
1995
1991
1996
Control *drag_preview = _gui_get_drag_preview ();
1992
1997
if (drag_preview) {
1993
1998
drag_preview->set_position (mpos);
1994
1999
}
1995
2000
1996
- gui.drag_mouse_over = over;
1997
- gui.drag_mouse_over_pos = Vector2 ();
1998
-
1999
- // Find the window this is above of.
2000
- // See if there is an embedder.
2001
- Viewport *embedder = nullptr ;
2002
- Vector2 viewport_pos;
2003
-
2004
- if (is_embedding_subwindows ()) {
2005
- embedder = this ;
2006
- viewport_pos = mpos;
2007
- } else {
2008
- // Not an embedder, but may be a subwindow of an embedder.
2009
- Window *w = Object::cast_to<Window>(this );
2010
- if (w) {
2011
- if (w->is_embedded ()) {
2012
- embedder = w->get_embedder ();
2013
-
2014
- viewport_pos = get_final_transform ().xform (mpos) + w->get_position (); // To parent coords.
2015
- }
2016
- }
2017
- }
2018
-
2019
- Viewport *viewport_under = nullptr ;
2020
-
2021
- if (embedder) {
2022
- // Use embedder logic.
2023
-
2024
- for (int i = embedder->gui .sub_windows .size () - 1 ; i >= 0 ; i--) {
2025
- Window *sw = embedder->gui .sub_windows [i].window ;
2026
- Rect2 swrect = Rect2i (sw->get_position (), sw->get_size ());
2027
- if (!sw->get_flag (Window::FLAG_BORDERLESS)) {
2028
- int title_height = sw->theme_cache .title_height ;
2029
- swrect.position .y -= title_height;
2030
- swrect.size .y += title_height;
2031
- }
2032
-
2033
- if (swrect.has_point (viewport_pos)) {
2034
- viewport_under = sw;
2035
- viewport_pos -= sw->get_position ();
2036
- }
2037
- }
2038
-
2039
- if (!viewport_under) {
2040
- // Not in a subwindow, likely in embedder.
2041
- viewport_under = embedder;
2042
- }
2043
- } else {
2044
- // Use DisplayServer logic.
2045
- Vector2i screen_mouse_pos = DisplayServer::get_singleton ()->mouse_get_position ();
2046
-
2047
- DisplayServer::WindowID window_id = DisplayServer::get_singleton ()->get_window_at_screen_position (screen_mouse_pos);
2048
-
2049
- if (window_id != DisplayServer::INVALID_WINDOW_ID) {
2050
- ObjectID object_under = DisplayServer::get_singleton ()->window_get_attached_instance_id (window_id);
2051
-
2052
- if (object_under != ObjectID ()) { // Fetch window.
2053
- Window *w = Object::cast_to<Window>(ObjectDB::get_instance (object_under));
2054
- if (w) {
2055
- viewport_under = w;
2056
- viewport_pos = w->get_final_transform ().affine_inverse ().xform (screen_mouse_pos - w->get_position ());
2057
- }
2058
- }
2001
+ gui.drag_mouse_over = section_root->gui .target_control ;
2002
+ if (gui.drag_mouse_over ) {
2003
+ if (!_gui_drop (gui.drag_mouse_over , gui.drag_mouse_over ->get_local_mouse_position (), true )) {
2004
+ gui.drag_mouse_over = nullptr ;
2059
2005
}
2060
- }
2061
-
2062
- if (viewport_under) {
2063
- if (viewport_under != this ) {
2064
- Transform2D ai = viewport_under->get_final_transform ().affine_inverse ();
2065
- viewport_pos = ai.xform (viewport_pos);
2066
- }
2067
- // Find control under at position.
2068
- gui.drag_mouse_over = viewport_under->gui_find_control (viewport_pos);
2069
2006
if (gui.drag_mouse_over ) {
2070
- Transform2D localizer = gui.drag_mouse_over ->get_global_transform_with_canvas ().affine_inverse ();
2071
- gui.drag_mouse_over_pos = localizer.xform (viewport_pos);
2072
-
2073
- bool can_drop = _gui_drop (gui.drag_mouse_over , gui.drag_mouse_over_pos , true );
2074
-
2075
- if (!can_drop) {
2076
- ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN;
2077
- } else {
2078
- ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP;
2079
- }
2007
+ ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP;
2008
+ } else {
2009
+ ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN;
2080
2010
}
2081
-
2082
- } else {
2083
- gui.drag_mouse_over = nullptr ;
2084
2011
}
2085
2012
}
2086
2013
2087
- if (DisplayServer::get_singleton ()->has_feature (DisplayServer::FEATURE_CURSOR_SHAPE) && !Object::cast_to<SubViewportContainer>(over)) {
2014
+ if (DisplayServer::get_singleton ()->has_feature (DisplayServer::FEATURE_CURSOR_SHAPE) && (gui.dragging || (!section_root->gui .global_dragging && !Object::cast_to<SubViewportContainer>(over)))) {
2015
+ // If dragging is active, then set the cursor shape only from the Viewport where dragging started.
2016
+ // If dragging is inactive, then set the cursor shape only when not over a SubViewportContainer.
2088
2017
DisplayServer::get_singleton ()->cursor_set_shape (ds_cursor_shape);
2089
2018
}
2090
2019
}
@@ -2284,10 +2213,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
2284
2213
}
2285
2214
}
2286
2215
2287
- void Viewport::_perform_drop (Control *p_control, Point2 p_pos ) {
2216
+ void Viewport::_perform_drop (Control *p_control) {
2288
2217
// Without any arguments, simply cancel Drag and Drop.
2289
2218
if (p_control) {
2290
- gui.drag_successful = _gui_drop (p_control, p_pos , false );
2219
+ gui.drag_successful = _gui_drop (p_control, p_control-> get_local_mouse_position () , false );
2291
2220
} else {
2292
2221
gui.drag_successful = false ;
2293
2222
}
@@ -2298,10 +2227,12 @@ void Viewport::_perform_drop(Control *p_control, Point2 p_pos) {
2298
2227
gui.drag_preview_id = ObjectID ();
2299
2228
}
2300
2229
2301
- gui.drag_data = Variant ();
2230
+ Viewport *section_root = get_section_root_viewport ();
2231
+ section_root->gui .drag_data = Variant ();
2302
2232
gui.dragging = false ;
2233
+ section_root->gui .global_dragging = false ;
2303
2234
gui.drag_mouse_over = nullptr ;
2304
- _propagate_viewport_notification ( this , NOTIFICATION_DRAG_END);
2235
+ Viewport::_propagate_drag_notification (section_root , NOTIFICATION_DRAG_END);
2305
2236
// Display the new cursor shape instantly.
2306
2237
update_mouse_cursor_state ();
2307
2238
}
@@ -2331,14 +2262,16 @@ void Viewport::_gui_force_drag(Control *p_base, const Variant &p_data, Control *
2331
2262
ERR_FAIL_COND_MSG (p_data.get_type () == Variant::NIL, " Drag data must be a value." );
2332
2263
2333
2264
gui.dragging = true ;
2334
- gui.drag_data = p_data;
2265
+ Viewport *section_root = get_section_root_viewport ();
2266
+ section_root->gui .global_dragging = true ;
2267
+ section_root->gui .drag_data = p_data;
2335
2268
gui.mouse_focus = nullptr ;
2336
2269
gui.mouse_focus_mask .clear ();
2337
2270
2338
2271
if (p_control) {
2339
2272
_gui_set_drag_preview (p_base, p_control);
2340
2273
}
2341
- _propagate_viewport_notification ( this , NOTIFICATION_DRAG_BEGIN);
2274
+ Viewport::_propagate_drag_notification (section_root , NOTIFICATION_DRAG_BEGIN);
2342
2275
}
2343
2276
2344
2277
void Viewport::_gui_set_drag_preview (Control *p_base, Control *p_control) {
@@ -3022,6 +2955,7 @@ void Viewport::_update_mouse_over() {
3022
2955
}
3023
2956
3024
2957
void Viewport::_update_mouse_over (Vector2 p_pos) {
2958
+ gui.last_mouse_pos = p_pos; // Necessary, because mouse cursor can be over Viewports that are not reached by the InputEvent.
3025
2959
// Look for embedded windows at mouse position.
3026
2960
if (is_embedding_subwindows ()) {
3027
2961
for (int i = gui.sub_windows .size () - 1 ; i >= 0 ; i--) {
@@ -3073,6 +3007,7 @@ void Viewport::_update_mouse_over(Vector2 p_pos) {
3073
3007
3074
3008
// Look for Controls at mouse position.
3075
3009
Control *over = gui_find_control (p_pos);
3010
+ get_section_root_viewport ()->gui .target_control = over;
3076
3011
bool notify_embedded_viewports = false ;
3077
3012
if (over != gui.mouse_over || (!over && !gui.mouse_over_hierarchy .is_empty ())) {
3078
3013
// Find the common ancestor of `gui.mouse_over` and `over`.
@@ -3195,6 +3130,10 @@ void Viewport::_drop_mouse_over(Control *p_until_control) {
3195
3130
if (gui.mouse_over && gui.mouse_over ->is_inside_tree ()) {
3196
3131
gui.mouse_over ->notification (Control::NOTIFICATION_MOUSE_EXIT_SELF);
3197
3132
}
3133
+ Viewport *section_root = get_section_root_viewport ();
3134
+ if (section_root && section_root->gui .target_control == gui.mouse_over ) {
3135
+ section_root->gui .target_control = nullptr ;
3136
+ }
3198
3137
gui.mouse_over = nullptr ;
3199
3138
3200
3139
// Send Mouse Exit notifications to children first. Don't send to p_until_control or above.
@@ -3403,7 +3342,7 @@ bool Viewport::is_input_disabled() const {
3403
3342
3404
3343
Variant Viewport::gui_get_drag_data () const {
3405
3344
ERR_READ_THREAD_GUARD_V (Variant ());
3406
- return gui.drag_data ;
3345
+ return get_section_root_viewport ()-> gui .drag_data ;
3407
3346
}
3408
3347
3409
3348
PackedStringArray Viewport::get_configuration_warnings () const {
@@ -3597,7 +3536,7 @@ bool Viewport::is_snap_2d_vertices_to_pixel_enabled() const {
3597
3536
3598
3537
bool Viewport::gui_is_dragging () const {
3599
3538
ERR_READ_THREAD_GUARD_V (false );
3600
- return gui.dragging ;
3539
+ return get_section_root_viewport ()-> gui .global_dragging ;
3601
3540
}
3602
3541
3603
3542
bool Viewport::gui_is_drag_successful () const {
@@ -5156,9 +5095,12 @@ Transform2D SubViewport::get_popup_base_transform() const {
5156
5095
return c->get_screen_transform () * container_transform * get_final_transform ();
5157
5096
}
5158
5097
5159
- bool SubViewport::is_directly_attached_to_screen () const {
5160
- // SubViewports, that are used as Textures are not considered to be directly attached to screen.
5161
- return Object::cast_to<SubViewportContainer>(get_parent ()) && get_parent ()->get_viewport () && get_parent ()->get_viewport ()->is_directly_attached_to_screen ();
5098
+ Viewport *SubViewport::get_section_root_viewport () const {
5099
+ if (Object::cast_to<SubViewportContainer>(get_parent ()) && get_parent ()->get_viewport ()) {
5100
+ return get_parent ()->get_viewport ()->get_section_root_viewport ();
5101
+ }
5102
+ SubViewport *vp = const_cast <SubViewport *>(this );
5103
+ return vp;
5162
5104
}
5163
5105
5164
5106
bool SubViewport::is_attached_in_viewport () const {
0 commit comments