Browse Source

Context: Return a boolean value for ProcessMouse functions, to indicate whether the mouse is interacting with any elements in the context. See #124.

Michael Ragazzon 5 years ago
parent
commit
d82ffd21ec
2 changed files with 31 additions and 8 deletions
  1. 12 4
      Include/RmlUi/Core/Context.h
  2. 19 4
      Source/Core/Context.cpp

+ 12 - 4
Include/RmlUi/Core/Context.h

@@ -189,21 +189,29 @@ public:
 	/// @param[in] x The x-coordinate of the mouse cursor, in window-coordinates (ie, 0 should be the left of the client area).
 	/// @param[in] y The y-coordinate of the mouse cursor, in window-coordinates (ie, 0 should be the top of the client area).
 	/// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
-	void ProcessMouseMove(int x, int y, int key_modifier_state);
+	/// @return True if the mouse is not interacting with any elements in the context (see 'IsMouseInteracting'), otherwise false.
+	bool ProcessMouseMove(int x, int y, int key_modifier_state);
 	/// Sends a mouse-button down event into this context.
 	/// @param[in] button_index The index of the button that was pressed; 0 for the left button, 1 for right, and any others from 2 onwards.
 	/// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
-	void ProcessMouseButtonDown(int button_index, int key_modifier_state);
+	/// @return True if the mouse is not interacting with any elements in the context (see 'IsMouseInteracting'), otherwise false.
+	bool ProcessMouseButtonDown(int button_index, int key_modifier_state);
 	/// Sends a mouse-button up event into this context.
 	/// @param[in] button_index The index of the button that was release; 0 for the left button, 1 for right, and any others from 2 onwards.
 	/// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
-	void ProcessMouseButtonUp(int button_index, int key_modifier_state);
+	/// @return True if the mouse is not interacting with any elements in the context (see 'IsMouseInteracting'), otherwise false.
+	bool ProcessMouseButtonUp(int button_index, int key_modifier_state);
 	/// Sends a mouse-wheel movement event into this context.
 	/// @param[in] wheel_delta The mouse-wheel movement this frame. RmlUi treats a negative delta as up movement (away from the user), positive as down.
 	/// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
 	/// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
 	bool ProcessMouseWheel(float wheel_delta, int key_modifier_state);
 
+	/// Returns a hint on whether the mouse is currently interacting with any elements in this context, based on previously submitted 'ProcessMouse...()' commands.
+	/// @note Interaction is determined irrespective of background and opacity. See the RCSS property 'pointer-events' to disable interaction for specific elements.
+	/// @return True if the mouse hovers over or has activated an element in this context, otherwise false.
+	bool IsMouseInteracting() const;
+
 	/// Gets the context's render interface.
 	/// @return The render interface the context renders through.
 	RenderInterface* GetRenderInterface() const;
@@ -258,7 +266,7 @@ private:
 
 	ContextInstancer* instancer;
 
-	using ElementSet = SmallOrderedSet< Element* > ;
+	using ElementSet = SmallOrderedSet< Element* >;
 	using ElementList = Vector< Element* >;
 	// Set of elements that are currently in hover state.
 	ElementSet hover_chain;

+ 19 - 4
Source/Core/Context.cpp

@@ -538,7 +538,7 @@ bool Context::ProcessTextInput(const String& string)
 }
 
 // Sends a mouse movement event into RmlUi.
-void Context::ProcessMouseMove(int x, int y, int key_modifier_state)
+bool Context::ProcessMouseMove(int x, int y, int key_modifier_state)
 {
 	// Check whether the mouse moved since the last event came through.
 	Vector2i old_mouse_position = mouse_position;
@@ -575,6 +575,8 @@ void Context::ProcessMouseMove(int x, int y, int key_modifier_state)
 				drag_hover->DispatchEvent(EventId::Dragmove, drag_parameters);
 		}
 	}
+
+	return !IsMouseInteracting();
 }
 	
 static Element* FindFocusElement(Element* element)
@@ -592,7 +594,7 @@ static Element* FindFocusElement(Element* element)
 }
 
 // Sends a mouse-button down event into RmlUi.
-void Context::ProcessMouseButtonDown(int button_index, int key_modifier_state)
+bool Context::ProcessMouseButtonDown(int button_index, int key_modifier_state)
 {
 	Dictionary parameters;
 	GenerateMouseEventParameters(parameters, button_index);
@@ -609,7 +611,7 @@ void Context::ProcessMouseButtonDown(int button_index, int key_modifier_state)
 			if (new_focus && new_focus != focus)
 			{
 				if (!new_focus->Focus())
-					return;
+					return !IsMouseInteracting();
 			}
 		}
 
@@ -677,15 +679,20 @@ void Context::ProcessMouseButtonDown(int button_index, int key_modifier_state)
 		if (hover)
 			hover->DispatchEvent(EventId::Mousedown, parameters);
 	}
+
+	return !IsMouseInteracting();
 }
 
 // Sends a mouse-button up event into RmlUi.
-void Context::ProcessMouseButtonUp(int button_index, int key_modifier_state)
+bool Context::ProcessMouseButtonUp(int button_index, int key_modifier_state)
 {
 	Dictionary parameters;
 	GenerateMouseEventParameters(parameters, button_index);
 	GenerateKeyModifierEventParameters(parameters, key_modifier_state);
 
+	// We want to return the interaction state before handling the mouse up events, so that any active element that is released is considered to capture the event.
+	const bool result = !IsMouseInteracting();
+
 	// Process primary click.
 	if (button_index == 0)
 	{
@@ -706,6 +713,7 @@ void Context::ProcessMouseButtonUp(int button_index, int key_modifier_state)
 			element->SetPseudoClass("active", false);
 		});
 		active_chain.clear();
+		active = nullptr;
 
 		if (drag)
 		{
@@ -747,6 +755,8 @@ void Context::ProcessMouseButtonUp(int button_index, int key_modifier_state)
 		if (hover)
 			hover->DispatchEvent(EventId::Mouseup, parameters);
 	}
+
+	return result;
 }
 
 // Sends a mouse-wheel movement event into RmlUi.
@@ -764,6 +774,11 @@ bool Context::ProcessMouseWheel(float wheel_delta, int key_modifier_state)
 	return true;
 }
 
+bool Context::IsMouseInteracting() const
+{
+	return (hover && hover != root.get()) || (active && active != root.get());
+}
+
 // Gets the context's render interface.
 RenderInterface* Context::GetRenderInterface() const
 {