Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/classes/Window.xml
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,12 @@
Causes the window to grab focus, allowing it to receive user input.
</description>
</method>
<method name="move_to_mouse">
<return type="void" />
<description>
Moves the window to the current mouse position.
</description>
</method>
<method name="popup">
<return type="void" />
<param index="0" name="rect" type="Rect2i" default="Rect2i(0, 0, 0, 0)" />
Expand Down
38 changes: 24 additions & 14 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1854,8 +1854,8 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
return nullptr;
}

Control *drag_preview = _gui_get_drag_preview();
if (!drag_preview || (c != drag_preview && !drag_preview->is_ancestor_of(c))) {
Window *drag_preview = _gui_get_drag_preview();
if (!drag_preview || !drag_preview->is_ancestor_of(c)) {
return c;
}

Expand Down Expand Up @@ -2029,7 +2029,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.dragging = true;
break;
} else {
Control *drag_preview = _gui_get_drag_preview();
Window *drag_preview = _gui_get_drag_preview();
if (drag_preview) {
ERR_PRINT("Don't set a drag preview and return null data. Preview was deleted and drag request ignored.");
memdelete(drag_preview);
Expand Down Expand Up @@ -2150,10 +2150,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.dragging) {
// Handle drag & drop. This happens in the viewport where dragging started.

Control *drag_preview = _gui_get_drag_preview();
Window *drag_preview = _gui_get_drag_preview();
if (drag_preview) {
Vector2 pos = drag_preview->get_canvas_transform().affine_inverse().xform(mpos);
drag_preview->set_position(pos);
drag_preview->move_to_mouse();
}

gui.drag_mouse_over = section_root->gui.target_control;
Expand Down Expand Up @@ -2390,7 +2389,7 @@ void Viewport::gui_perform_drop_at(const Point2 &p_pos, Control *p_control) {
gui.drag_successful = false;
}

Control *drag_preview = _gui_get_drag_preview();
Window *drag_preview = _gui_get_drag_preview();
if (drag_preview) {
memdelete(drag_preview);
gui.drag_preview_id = ObjectID();
Expand Down Expand Up @@ -2460,23 +2459,34 @@ void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) {
ERR_FAIL_COND(p_control->is_inside_tree());
ERR_FAIL_COND(p_control->get_parent() != nullptr);

Control *drag_preview = _gui_get_drag_preview();
Window *drag_preview = _gui_get_drag_preview();
if (drag_preview) {
memdelete(drag_preview);
}

Window *window = memnew(Window);

window->wrap_controls = true;
window->set_flag(Window::FLAG_BORDERLESS, true);
window->set_flag(Window::FLAG_ALWAYS_ON_TOP, true);
window->set_flag(Window::FLAG_MOUSE_PASSTHROUGH, true);
window->set_flag(Window::FLAG_NO_FOCUS, true);
window->set_flag(Window::FLAG_TRANSPARENT, true);
window->set_size(Size2i(0, 0));
p_base->get_root_parent_control()->add_child(window);

p_control->set_as_top_level(true);
p_control->set_position(gui.last_mouse_pos);
p_base->get_root_parent_control()->add_child(p_control); // Add as child of viewport.
p_control->move_to_front();

gui.drag_preview_id = p_control->get_instance_id();
window->add_child(p_control);
window->visible = true;
gui.drag_preview_id = window->get_instance_id();
}

Control *Viewport::_gui_get_drag_preview() {
Window *Viewport::_gui_get_drag_preview() {
if (gui.drag_preview_id.is_null()) {
return nullptr;
} else {
Control *drag_preview = ObjectDB::get_instance<Control>(gui.drag_preview_id);
Window *drag_preview = ObjectDB::get_instance<Window>(gui.drag_preview_id);
if (!drag_preview) {
ERR_PRINT("Don't free the control set as drag preview.");
gui.drag_preview_id = ObjectID();
Expand Down
2 changes: 1 addition & 1 deletion scene/main/viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ class Viewport : public Node {
void _gui_force_drag_cancel();
void _gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control);
void _gui_set_drag_preview(Control *p_base, Control *p_control);
Control *_gui_get_drag_preview();
Window *_gui_get_drag_preview();

void _gui_remove_focus_for_window(Node *p_window);
void _gui_unfocus_control(Control *p_control);
Expand Down
15 changes: 15 additions & 0 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,20 @@ Point2i Window::get_position() const {
return position;
}

void Window::move_to_mouse() {
ERR_MAIN_THREAD_GUARD;
ERR_FAIL_COND(!is_inside_tree());

Point2i mouse_pos;
if (is_embedded() && !force_native) {
mouse_pos = get_embedder()->get_mouse_position();
set_position(mouse_pos + Point2i(10, 10));
} else {
mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
set_position(mouse_pos + Point2i(10, 10));
}
}

void Window::move_to_center() {
ERR_MAIN_THREAD_GUARD;
ERR_FAIL_COND(!is_inside_tree());
Expand Down Expand Up @@ -3153,6 +3167,7 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_position", "position"), &Window::set_position);
ClassDB::bind_method(D_METHOD("get_position"), &Window::get_position);
ClassDB::bind_method(D_METHOD("move_to_center"), &Window::move_to_center);
ClassDB::bind_method(D_METHOD("move_to_mouse"), &Window::move_to_mouse);

ClassDB::bind_method(D_METHOD("set_size", "size"), &Window::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &Window::get_size);
Expand Down
1 change: 1 addition & 0 deletions scene/main/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ class Window : public Viewport {
void set_position(const Point2i &p_position);
Point2i get_position() const;
void move_to_center();
void move_to_mouse();

void set_size(const Size2i &p_size);
Size2i get_size() const;
Expand Down
3 changes: 2 additions & 1 deletion tests/scene/test_text_edit.h
Original file line number Diff line number Diff line change
Expand Up @@ -2402,7 +2402,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
CHECK(text_edit->get_caret_column() == 4);
CHECK(text_edit->get_selection_origin_line() == 0);
CHECK(text_edit->get_selection_origin_column() == 0);
SEND_GUI_MOUSE_MOTION_EVENT(text_edit->get_rect_at_line_column(1, 11).get_center() + Point2i(2, 0), MouseButtonMask::LEFT, Key::NONE);
// Increased offset to ensure drag preview window moves before dropping, otherwise drop data would be consumed by drag preview window
SEND_GUI_MOUSE_MOTION_EVENT(text_edit->get_rect_at_line_column(1, 11).get_center() + Point2i(20, 20), MouseButtonMask::LEFT, Key::NONE);
SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(text_edit->get_rect_at_line_column(1, 11).get_center() + Point2i(2, 0), MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE);
CHECK_FALSE(text_edit->get_viewport()->gui_is_dragging());
CHECK(text_edit->get_text() == " test\ndrop here 'drag'");
Expand Down
Loading