Fix mouse_over not dropped when mouse leaves window

This commit is contained in:
Marcel Admiraal 2021-04-24 13:05:06 +01:00
parent 2d54d3d71d
commit 0992621200
2 changed files with 22 additions and 21 deletions

View file

@ -184,6 +184,7 @@ public:
Viewport::GUI::GUI() {
dragging = false;
drag_successful = false;
mouse_in_window = true;
mouse_focus = nullptr;
mouse_click_grabber = nullptr;
mouse_focus_mask = 0;
@ -398,21 +399,26 @@ void Viewport::_notification(int p_what) {
_process_picking(false);
}
} break;
case SceneTree::NOTIFICATION_WM_MOUSE_EXIT: {
_drop_physics_mouseover();
// Unlike on loss of focus (NOTIFICATION_WM_WINDOW_FOCUS_OUT), do not
// drop the gui mouseover here, as a scrollbar may be dragged while the
// mouse is outside the window (without the window having lost focus).
// See bug #39634
case NOTIFICATION_WM_MOUSE_ENTER: {
gui.mouse_in_window = true;
} break;
case SceneTree::NOTIFICATION_WM_FOCUS_OUT: {
case NOTIFICATION_WM_MOUSE_EXIT: {
gui.mouse_in_window = false;
_drop_physics_mouseover();
_drop_mouse_over();
// When the mouse exits the window, we want to end mouse_over, but
// not mouse_focus, because, for example, we want to continue
// dragging a scrollbar even if the mouse has left the window.
} break;
case NOTIFICATION_WM_FOCUS_OUT: {
_drop_physics_mouseover();
if (gui.mouse_focus) {
//if mouse is being pressed, send a release event
_drop_mouse_focus();
}
// When the window focus changes, we want to end mouse_focus, but
// not the mouse_over. Note: The OS will trigger a separate mouse
// exit event if the change in focus results in the mouse exiting
// the window.
} break;
}
}
@ -1861,9 +1867,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (mb.is_valid()) {
gui.key_event_accepted = false;
Control *over = nullptr;
Point2 mpos = mb->get_position();
if (mb->is_pressed()) {
Size2 pos = mpos;
@ -2057,6 +2060,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
// it is different, rather than wait for it to be updated the next time the
// mouse is moved, notify the control so that it can e.g. drop the highlight.
// This code is duplicated from the mm.is_valid()-case further below.
Control *over = nullptr;
if (gui.mouse_focus) {
over = gui.mouse_focus;
} else {
@ -2087,8 +2092,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.last_mouse_pos = mpos;
Control *over = nullptr;
// D&D
if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & BUTTON_MASK_LEFT) {
gui.drag_accum += mm->get_relative();
@ -2135,12 +2138,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
// These sections of code are reused in the mb.is_valid() case further up
// for the purpose of notifying controls about potential changes in focus
// when the mousebutton is released.
Control *over = nullptr;
if (gui.mouse_focus) {
over = gui.mouse_focus;
} else {
} else if (gui.mouse_in_window) {
over = _gui_find_control(mpos);
}
@ -2187,11 +2188,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (over) {
_gui_call_notification(over, Control::NOTIFICATION_MOUSE_ENTER);
gui.mouse_over = over;
}
}
gui.mouse_over = over;
Control *drag_preview = _gui_get_drag_preview();
if (drag_preview) {
drag_preview->set_position(mpos);

View file

@ -295,6 +295,7 @@ private:
// info used when this is a window
bool key_event_accepted;
bool mouse_in_window;
Control *mouse_focus;
Control *last_mouse_focus;
Control *mouse_click_grabber;