diff options
| author | Marcel Admiraal <madmiraal@users.noreply.github.com> | 2021-04-24 13:03:38 +0100 | 
|---|---|---|
| committer | Marcel Admiraal <madmiraal@users.noreply.github.com> | 2022-02-01 16:12:37 +0000 | 
| commit | eaa70fd3f836a995b54cd90a568ce9a5db8f94af (patch) | |
| tree | 2050caeecd6196e0955ff244ca5bcd641ecf0d6d | |
| parent | ea12094f19b028c1dcf6d402b8cbb3296b2065a8 (diff) | |
Fix mouse_over not dropped when mouse leaves window
| -rw-r--r-- | scene/main/viewport.cpp | 49 | ||||
| -rw-r--r-- | scene/main/viewport.h | 2 | 
2 files changed, 27 insertions, 24 deletions
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 1244e0c028..bde68f0b3d 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -492,20 +492,26 @@ void Viewport::_notification(int p_what) {  			}  #endif // _3D_DISABLED  		} break; +		case NOTIFICATION_WM_MOUSE_ENTER: { +			gui.mouse_in_window = true; +		} break;  		case NOTIFICATION_WM_MOUSE_EXIT: { +			gui.mouse_in_window = false;  			_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 +			_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_WINDOW_FOCUS_OUT: {  			_drop_physics_mouseover(); -  			if (gui.mouse_focus && !gui.forced_mouse_focus) {  				_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;  	}  } @@ -1447,8 +1453,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();  		gui.last_mouse_pos = mpos;  		if (mb->is_pressed()) { @@ -1594,6 +1598,7 @@ 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 { @@ -1601,10 +1606,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {  			}  			if (gui.mouse_focus_mask == MouseButton::NONE && over != gui.mouse_over) { -				if (gui.mouse_over) { -					_gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT); -				} - +				_drop_mouse_over();  				_gui_cancel_tooltip();  				if (over) { @@ -1625,8 +1627,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {  		gui.last_mouse_pos = mpos; -		Control *over = nullptr; -  		// Drag & drop.  		if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {  			gui.drag_accum += mm->get_relative(); @@ -1674,29 +1674,23 @@ 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);  		}  		if (over != gui.mouse_over) { -			if (gui.mouse_over) { -				_gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT); -			} - +			_drop_mouse_over();  			_gui_cancel_tooltip();  			if (over) {  				_gui_call_notification(over, Control::NOTIFICATION_MOUSE_ENTER); +				gui.mouse_over = over;  			}  		} -		gui.mouse_over = over; -  		DisplayServer::CursorShape ds_cursor_shape = (DisplayServer::CursorShape)Input::get_singleton()->get_default_cursor_shape();  		if (over) { @@ -2183,6 +2177,13 @@ void Viewport::_gui_accept_event() {  	}  } +void Viewport::_drop_mouse_over() { +	if (gui.mouse_over) { +		_gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT); +		gui.mouse_over = nullptr; +	} +} +  void Viewport::_drop_mouse_focus() {  	Control *c = gui.mouse_focus;  	MouseButton mask = gui.mouse_focus_mask; diff --git a/scene/main/viewport.h b/scene/main/viewport.h index a3127811f5..2541474cf3 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -335,6 +335,7 @@ private:  		// info used when this is a window  		bool forced_mouse_focus = false; //used for menu buttons +		bool mouse_in_window = true;  		bool key_event_accepted = false;  		Control *mouse_focus = nullptr;  		Control *last_mouse_focus = nullptr; @@ -433,6 +434,7 @@ private:  	void _canvas_layer_add(CanvasLayer *p_canvas_layer);  	void _canvas_layer_remove(CanvasLayer *p_canvas_layer); +	void _drop_mouse_over();  	void _drop_mouse_focus();  	void _drop_physics_mouseover(bool p_paused_only = false);  |