View Issue Details

IDProjectCategoryView StatusLast Update
0003566NoesisGUIUnrealpublic2024-10-25 12:31
Reporternevayeshirazi Assigned Tohcpizzi  
PrioritynormalSeveritymajor 
Status resolvedResolutionfixed 
Product Version3.2.3 
Target Version3.2.5Fixed in Version3.2.5 
Summary0003566: Inventory Drag and Drop Sample For UE5 Not Working as Excepted for GameAndUI Input Mode
Description

The Inventory sample drag and drop operations does not work for GameAndUI input mode in UE 5.3.

It works for the UIOnly input mode.

Detailed description of the issue can be found
https://www.noesisengine.com/forums/viewtopic.php?t=3398&sid=2fdd242b06268b7c51c393663df59880

Steps To Reproduce

Running the Inventory sample level in Samples project and dragging the inventory items should indicate the issue.

PlatformWindows

Activities

hcpizzi

hcpizzi

2024-07-30 18:11

developer   ~0009851

Hi,

I've attached a patch that should resolve this issue. Please note that this patch contains copious amounts of logging to help us diagnose the issue. Those won't be on the final code. If the problem still persists, could you send us the output of these logs?

Thanks!

DragBehavior.patch (15,413 bytes)   
Index: Plugins/NoesisGUI/Source/NoesisRuntime/Classes/NoesisInstance.h
===================================================================
--- Plugins/NoesisGUI/Source/NoesisRuntime/Classes/NoesisInstance.h	(revision 14201)
+++ Plugins/NoesisGUI/Source/NoesisRuntime/Classes/NoesisInstance.h	(working copy)
@@ -216,6 +216,7 @@
 	void OnPreviewLostKeyboardFocus(Noesis::BaseComponent* Component, const Noesis::KeyboardFocusChangedEventArgs& Args);
 
 	bool HitTest(FVector2D Position) const;
+	bool HasMouseCapture() const;
 
 	void TermInstance();
 
@@ -264,9 +265,17 @@
 	virtual FReply NativeOnTouchEnded(const FGeometry& MyGeometry, const FPointerEvent& InTouchEvent) override;
 	virtual FCursorReply NativeOnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) override;
 	virtual FReply NativeOnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
+	virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
+	virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override;
 	virtual bool NativeSupportsKeyboardFocus() const override;
 	virtual void NativeConstruct() override;
 	virtual void NativeDestruct() override;
+	virtual FReply NativeOnFocusReceived(const FGeometry& InGeometry, const FFocusEvent& InFocusEvent) override;
+	virtual void NativeOnFocusLost(const FFocusEvent& InFocusEvent) override;
+	virtual void NativeOnFocusChanging(const FWeakWidgetPath& PreviousFocusPath, const FWidgetPath& NewWidgetPath, const FFocusEvent& InFocusEvent) override;
+	virtual void NativeOnAddedToFocusPath(const FFocusEvent& InFocusEvent) override;
+	virtual void NativeOnRemovedFromFocusPath(const FFocusEvent& InFocusEvent) override;
+	virtual FNavigationReply NativeOnNavigation(const FGeometry& MyGeometry, const FNavigationEvent& InNavigationEvent, const FNavigationReply& InDefaultReply) override;
 	// End of UUserWidget interface
 };
 
Index: Plugins/NoesisGUI/Source/NoesisRuntime/Private/NoesisInstance.cpp
===================================================================
--- Plugins/NoesisGUI/Source/NoesisRuntime/Private/NoesisInstance.cpp	(revision 14201)
+++ Plugins/NoesisGUI/Source/NoesisRuntime/Private/NoesisInstance.cpp	(working copy)
@@ -1162,6 +1162,18 @@
 	return HitTester.Hit != nullptr;
 }
 
+bool UNoesisInstance::HasMouseCapture() const
+{
+	if (XamlView)
+	{
+		auto Root = XamlView->GetContent();
+		auto Mouse = Root != nullptr ? Root->GetMouse() : nullptr;
+		return Mouse != nullptr && Mouse->GetCaptured() != nullptr;
+	}
+
+	return false;
+}
+
 void UNoesisInstance::TermInstance()
 {
 	if (XamlView)
@@ -1465,10 +1477,17 @@
 	{
 		TCHAR Character = CharacterEvent.GetCharacter();
 
-		XamlView->Char(CharCast<char>(Character));
+		bool Handled = XamlView->Char(CharCast<char>(Character));
+
+		if (Handled)
+		{
+			UE_LOG(LogNoesis, Warning, TEXT("Char handled %c"), Character);
+			return FReply::Handled();
+		}
 	}
 
-	return Super::NativeOnKeyChar(MyGeometry, CharacterEvent);
+	UE_LOG(LogNoesis, Warning, TEXT("Char unhandled %c"), CharacterEvent.GetCharacter());
+	return FReply::Unhandled();
 }
 
 static TMap<FKey, Noesis::Key> InitKeyMap()
@@ -1595,11 +1614,18 @@
 		Noesis::Key* NoesisKey = KeyToNoesisKey(Key);
 		if (NoesisKey != nullptr)
 		{
-			XamlView->KeyDown(*NoesisKey);
+			bool Handled = XamlView->KeyDown(*NoesisKey);
+
+			if (Handled)
+			{
+				UE_LOG(LogNoesis, Warning, TEXT("KeyDown handled %s"), *KeyEvent.GetKey().ToString());
+				return FReply::Handled();
+			}
 		}
 	}
 
-	return Super::NativeOnKeyDown(MyGeometry, KeyEvent);
+	UE_LOG(LogNoesis, Warning, TEXT("KeyDown unhandled %s"), *KeyEvent.GetKey().ToString());
+	return FReply::Unhandled();
 }
 
 FReply UNoesisInstance::NativeOnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
@@ -1611,31 +1637,22 @@
 		Noesis::Key* NoesisKey = KeyToNoesisKey(Key);
 		if (NoesisKey != nullptr)
 		{
-			XamlView->KeyUp(*NoesisKey);
+			bool Handled = XamlView->KeyUp(*NoesisKey);
+
+			if (Handled)
+			{
+				UE_LOG(LogNoesis, Warning, TEXT("KeyUp handled %s"), *KeyEvent.GetKey().ToString());
+				return FReply::Handled();
+			}
 		}
 	}
 
-	return Super::NativeOnKeyUp(MyGeometry, KeyEvent);
+	UE_LOG(LogNoesis, Warning, TEXT("KeyUp unhandled %s"), *KeyEvent.GetKey().ToString());
+	return FReply::Unhandled();
 }
 
 FReply UNoesisInstance::NativeOnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& InAnalogEvent)
 {
-	SCOPE_CYCLE_COUNTER(STAT_NoesisInstance_OnAnalogValueChanged);
-	if (XamlView)
-	{
-		if (FMath::Abs(InAnalogEvent.GetAnalogValue()) > 0.25f)
-		{
-			if (InAnalogEvent.GetKey() == EKeys::Gamepad_RightX)
-			{
-				XamlView->HScroll(InAnalogEvent.GetAnalogValue());
-			}
-			else if (InAnalogEvent.GetKey() == EKeys::Gamepad_RightY)
-			{
-				XamlView->Scroll(InAnalogEvent.GetAnalogValue());
-			}
-		}
-	}
-
 	return Super::NativeOnAnalogValueChanged(MyGeometry, InAnalogEvent);
 }
 
@@ -1670,7 +1687,7 @@
 
 			if (Handled)
 			{
-				return FReply::Handled().PreventThrottling().CaptureMouse(MyWidget.Pin().ToSharedRef());
+				return FReply::Handled().PreventThrottling().CaptureMouse(TakeWidget());
 			}
 		}
 		else
@@ -1679,15 +1696,27 @@
 			bool Hit = HitTest(Position);
 
 			Noesis::MouseButton MouseButton = GetNoesisMouseButton(MouseEvent.GetEffectingButton());
-			bool Handled = XamlView->MouseButtonDown(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y), MouseButton);
+			bool Handled = XamlView->MouseButtonDown(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y), MouseButton) || HasMouseCapture();
 
 			if (Handled && Hit)
 			{
-				return FReply::Handled().PreventThrottling();
+				auto Reply = FReply::Handled().PreventThrottling().SetUserFocus(FSlateApplication::Get().GetGameViewport().ToSharedRef());
+				if (HasMouseCapture())
+				{
+					UE_LOG(LogNoesis, Warning, TEXT("MouseButtonDown CaptureMouse"));
+					Reply.CaptureMouse(TakeWidget());
+				}
+				else
+				{
+					UE_LOG(LogNoesis, Warning, TEXT("MouseButtonDown ReleaseMouseCapture"));
+					Reply.ReleaseMouseCapture();
+				}
+				return Reply;
 			}
 		}
 	}
 
+	UE_LOG(LogNoesis, Warning, TEXT("MouseButtonDown Unhandled"));
 	return FReply::Unhandled();
 }
 
@@ -1712,15 +1741,27 @@
 			bool Hit = HitTest(Position);
 
 			Noesis::MouseButton MouseButton = GetNoesisMouseButton(MouseEvent.GetEffectingButton());
-			bool Handled = XamlView->MouseButtonUp(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y), MouseButton);
+			bool Handled = XamlView->MouseButtonUp(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y), MouseButton) || HasMouseCapture();
 
 			if (Handled && Hit)
 			{
-				return FReply::Handled().PreventThrottling();
+				auto Reply = FReply::Handled().PreventThrottling().SetUserFocus(FSlateApplication::Get().GetGameViewport().ToSharedRef());
+				if (HasMouseCapture())
+				{
+					UE_LOG(LogNoesis, Warning, TEXT("MouseButtonUp CaptureMouse"));
+					Reply.CaptureMouse(TakeWidget());
+				}
+				else
+				{
+					UE_LOG(LogNoesis, Warning, TEXT("MouseButtonUp ReleaseMouseCapture"));
+					Reply.ReleaseMouseCapture();
+				}
+				return Reply;
 			}
 		}
 	}
 
+	UE_LOG(LogNoesis, Warning, TEXT("MouseButtonUp Unhandled"));
 	return FReply::Unhandled();
 }
 
@@ -1732,14 +1773,29 @@
 		FVector2D Position = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()) * MyGeometry.Scale;
 		bool Hit = HitTest(Position);
 
-		bool Handled = XamlView->MouseMove(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y));
+		bool Handled = XamlView->MouseMove(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y)) || HasMouseCapture();
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling().SetUserFocus(FSlateApplication::Get().GetGameViewport().ToSharedRef());
+			if (HasMouseCapture())
+			{
+				UE_LOG(LogNoesis, Warning, TEXT("MouseMove CaptureMouse"));
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				UE_LOG(LogNoesis, Warning, TEXT("MouseMove ReleaseMouseCapture"));
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
+	if (!MouseEvent.GetCursorDelta().IsZero())
+	{
+		UE_LOG(LogNoesis, Warning, TEXT("MouseMove Unhandled"));
+	}
 	return FReply::Unhandled();
 }
 
@@ -1756,7 +1812,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1776,7 +1841,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1796,7 +1870,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1816,7 +1899,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1841,7 +1933,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1848,6 +1949,59 @@
 	return FReply::Unhandled();
 }
 
+void UNoesisInstance::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
+{
+	UE_LOG(LogNoesis, Warning, TEXT("MouseEnter"));
+	if (XamlView)
+	{
+		UE_LOG(LogNoesis, Warning, TEXT("Activate View"));
+		XamlView->Activate();
+	}
+}
+
+void UNoesisInstance::NativeOnMouseLeave(const FPointerEvent& InMouseEvent)
+{
+	UE_LOG(LogNoesis, Warning, TEXT("MouseLeave"));
+	if (XamlView && !HasMouseCapture())
+	{
+		UE_LOG(LogNoesis, Warning, TEXT("Deactivate View"));
+		XamlView->Deactivate();
+	}
+}
+
+FReply UNoesisInstance::NativeOnFocusReceived(const FGeometry& InGeometry, const FFocusEvent& InFocusEvent)
+{
+	UE_LOG(LogNoesis, Warning, TEXT("FocusReceived"));
+	return Super::NativeOnFocusReceived(InGeometry, InFocusEvent);
+	//return FReply::Handled().ClearUserFocus();
+}
+
+void UNoesisInstance::NativeOnFocusLost(const FFocusEvent& InFocusEvent)
+{
+	UE_LOG(LogNoesis, Warning, TEXT("FocusLost"));
+}
+
+void UNoesisInstance::NativeOnFocusChanging(const FWeakWidgetPath& PreviousFocusPath, const FWidgetPath& NewWidgetPath, const FFocusEvent& InFocusEvent)
+{
+	UE_LOG(LogNoesis, Warning, TEXT("FocusChanging"));
+}
+
+void UNoesisInstance::NativeOnAddedToFocusPath(const FFocusEvent& InFocusEvent)
+{
+	UE_LOG(LogNoesis, Warning, TEXT("AddedToFocusPath"));
+}
+
+void UNoesisInstance::NativeOnRemovedFromFocusPath(const FFocusEvent& InFocusEvent)
+{
+	UE_LOG(LogNoesis, Warning, TEXT("RemovedFromFocusPath"));
+}
+
+FNavigationReply UNoesisInstance::NativeOnNavigation(const FGeometry& MyGeometry, const FNavigationEvent& InNavigationEvent, const FNavigationReply& InDefaultReply)
+{
+	UE_LOG(LogNoesis, Warning, TEXT("Navigation"));
+	return Super::NativeOnNavigation(MyGeometry, InNavigationEvent, InDefaultReply);
+}
+
 bool UNoesisInstance::NativeSupportsKeyboardFocus() const
 {
 	// SObjectWidget::OnKeyDown calls UNoesisInstance::NativeOnKeyDown. There we set SupportsKeyboardFocus = !EnableActions.
Index: Source/Inventory/DragItemBehavior.cpp
===================================================================
--- Source/Inventory/DragItemBehavior.cpp	(revision 14126)
+++ Source/Inventory/DragItemBehavior.cpp	(working copy)
@@ -100,14 +100,32 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 void DragItemBehavior::OnMouseDown(BaseComponent*, const MouseButtonEventArgs& e)
 {
+    UE_LOG(LogNoesisInventory, Warning, TEXT("DragItemBehavior::OnMouseDown"));
     _mouseClicked = true;
     e.handled = true;
 }
 
+static void ResetFocus(BaseComponent* source)
+{
+    auto element = Noesis::DynamicCast<UIElement*>(source);
+    if (element != nullptr)
+    {
+        auto keyboard = element->GetKeyboard();
+        if (keyboard != nullptr)
+        {
+            keyboard->Focus(nullptr);
+        }
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-void DragItemBehavior::OnMouseUp(BaseComponent*, const MouseButtonEventArgs&)
+void DragItemBehavior::OnMouseUp(BaseComponent* source, const MouseButtonEventArgs& e)
 {
+    UE_LOG(LogNoesisInventory, Warning, TEXT("DragItemBehavior::OnMouseUp"));
     _mouseClicked = false;
+    e.handled = true;
+
+    ResetFocus(source);
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -118,6 +136,7 @@
         return;
     }
 
+    UE_LOG(LogNoesisInventory, Warning, TEXT("DragItemBehavior::OnMouseMove"));
     _mouseClicked = false;
 
     FrameworkElement* element = GetAssociatedObject();
@@ -131,7 +150,7 @@
 
             startDrag->Execute(item);
 
-            DragDrop::DoDragDrop(element, item, DragDropEffects_Move, [this](DependencyObject*,
+            DragDrop::DoDragDrop(element, item, DragDropEffects_Move, [this](DependencyObject* source,
                 BaseComponent*, UIElement*, const Noesis::Point&, uint32_t effects)
             {
                 Noesis::Ptr<BaseComponent> dragSuccess = Boxing::Box<bool>(effects != DragDropEffects_None);
@@ -140,9 +159,13 @@
                 {
                     endDrag->Execute(dragSuccess);
                 }
+
+                ResetFocus(source);
             });
         }
     }
+
+    e.handled = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
Index: Source/Inventory/InventoryGame.cpp
===================================================================
--- Source/Inventory/InventoryGame.cpp	(revision 14126)
+++ Source/Inventory/InventoryGame.cpp	(working copy)
@@ -11,6 +11,8 @@
 #include "DragItemBehavior.h"
 #include "DropItemBehavior.h"
 
+DEFINE_LOG_CATEGORY(LogNoesisInventory);
+
 class InventoryModule : public FDefaultGameModuleImpl
 {
     virtual void StartupModule() override
DragBehavior.patch (15,413 bytes)   
hcpizzi

hcpizzi

2024-08-01 16:19

developer   ~0009856

I'm attaching a new one generated from 3.2.3.

DragBehavior3.2.3.patch (11,343 bytes)   
Index: NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp
===================================================================
--- NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp	(revision 13872)
+++ NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp	(working copy)
@@ -60,6 +60,7 @@
 		DefaultInstance->EnableKeyboard = NoesisBlueprint->EnableKeyboard;
 		DefaultInstance->EnableMouse = NoesisBlueprint->EnableMouse;
 		DefaultInstance->EmulateTouch = NoesisBlueprint->EmulateTouch;
+		DefaultInstance->SetUserFocusToViewport = NoesisBlueprint->SetUserFocusToViewport;
 		DefaultInstance->EnableTouch = NoesisBlueprint->EnableTouch;
 		DefaultInstance->EnableActions = NoesisBlueprint->EnableActions;
 		DefaultInstance->PixelDepthBias = NoesisBlueprint->PixelDepthBias;
Index: NoesisRuntime/Classes/NoesisBlueprint.h
===================================================================
--- NoesisRuntime/Classes/NoesisBlueprint.h	(revision 13872)
+++ NoesisRuntime/Classes/NoesisBlueprint.h	(working copy)
@@ -56,6 +56,10 @@
 	UPROPERTY(EditAnywhere, Category = "Noesis View", meta = (EditCondition = "EnableMouse"))
 	bool EmulateTouch;
 
+	/** Handled mouse events set user focus to the game viewport. */
+	UPROPERTY(EditAnywhere, Category = "Noesis View", meta = (EditCondition = "EnableMouse"))
+	bool SetUserFocusToViewport;
+
 	UPROPERTY(EditAnywhere, Category = "Noesis View")
 	bool EnableTouch;
 
Index: NoesisRuntime/Classes/NoesisInstance.h
===================================================================
--- NoesisRuntime/Classes/NoesisInstance.h	(revision 13872)
+++ NoesisRuntime/Classes/NoesisInstance.h	(working copy)
@@ -166,6 +166,9 @@
 	bool EmulateTouch;
 
 	UPROPERTY(BlueprintReadWrite, Category = "NoesisGUI")
+	bool SetUserFocusToViewport;
+
+	UPROPERTY(BlueprintReadWrite, Category = "NoesisGUI")
 	bool EnableTouch;
 
 	UPROPERTY(BlueprintReadWrite, Category = "NoesisGUI")
@@ -217,6 +220,7 @@
 	void OnPreviewLostKeyboardFocus(Noesis::BaseComponent* Component, const Noesis::KeyboardFocusChangedEventArgs& Args);
 
 	bool HitTest(FVector2D Position) const;
+	bool HasMouseCapture() const;
 
 	void TermInstance();
 
@@ -267,6 +271,8 @@
 	virtual FReply NativeOnTouchEnded(const FGeometry& MyGeometry, const FPointerEvent& InTouchEvent) override;
 	virtual FCursorReply NativeOnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) override;
 	virtual FReply NativeOnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
+	virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
+	virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override;
 	virtual bool NativeSupportsKeyboardFocus() const override;
 	virtual void NativeConstruct() override;
 	virtual void NativeDestruct() override;
Index: NoesisRuntime/Private/NoesisBlueprint.cpp
===================================================================
--- NoesisRuntime/Private/NoesisBlueprint.cpp	(revision 13872)
+++ NoesisRuntime/Private/NoesisBlueprint.cpp	(working copy)
@@ -18,6 +18,7 @@
 	EnableKeyboard = true;
 	EnableMouse = true;
 	EmulateTouch = false;
+	SetUserFocusToViewport = false;
 	EnableTouch = true;
 	EnableActions = false;
 	PixelDepthBias = -1.0f;
Index: NoesisRuntime/Private/NoesisInstance.cpp
===================================================================
--- NoesisRuntime/Private/NoesisInstance.cpp	(revision 13872)
+++ NoesisRuntime/Private/NoesisInstance.cpp	(working copy)
@@ -502,6 +502,7 @@
 	EnableKeyboard = true;
 	EnableMouse = true;
 	EmulateTouch = false;
+	SetUserFocusToViewport = false;
 	EnableTouch = true;
 	EnableActions = false;
 	PixelDepthBias = -1.0f;
@@ -1128,6 +1129,18 @@
 	return HitTester.Hit != nullptr;
 }
 
+bool UNoesisInstance::HasMouseCapture() const
+{
+	if (XamlView)
+	{
+		auto Root = XamlView->GetContent();
+		auto Mouse = Root != nullptr ? Root->GetMouse() : nullptr;
+		return Mouse != nullptr && Mouse->GetCaptured() != nullptr;
+	}
+
+	return false;
+}
+
 void UNoesisInstance::TermInstance()
 {
 	if (XamlView)
@@ -1431,10 +1444,15 @@
 	{
 		TCHAR Character = CharacterEvent.GetCharacter();
 
-		XamlView->Char(CharCast<char>(Character));
+		bool Handled = XamlView->Char(CharCast<char>(Character));
+
+		if (Handled)
+		{
+			return FReply::Handled();
+		}
 	}
 
-	return Super::NativeOnKeyChar(MyGeometry, CharacterEvent);
+	return FReply::Unhandled();
 }
 
 static TMap<FKey, Noesis::Key> InitKeyMap()
@@ -1561,11 +1579,16 @@
 		Noesis::Key* NoesisKey = KeyToNoesisKey(Key);
 		if (NoesisKey != nullptr)
 		{
-			XamlView->KeyDown(*NoesisKey);
+			bool Handled = XamlView->KeyDown(*NoesisKey);
+
+			if (Handled)
+			{
+				return FReply::Handled();
+			}
 		}
 	}
 
-	return Super::NativeOnKeyDown(MyGeometry, KeyEvent);
+	return FReply::Unhandled();
 }
 
 FReply UNoesisInstance::NativeOnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
@@ -1577,31 +1600,20 @@
 		Noesis::Key* NoesisKey = KeyToNoesisKey(Key);
 		if (NoesisKey != nullptr)
 		{
-			XamlView->KeyUp(*NoesisKey);
+			bool Handled = XamlView->KeyUp(*NoesisKey);
+
+			if (Handled)
+			{
+				return FReply::Handled();
+			}
 		}
 	}
 
-	return Super::NativeOnKeyUp(MyGeometry, KeyEvent);
+	return FReply::Unhandled();
 }
 
 FReply UNoesisInstance::NativeOnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& InAnalogEvent)
 {
-	SCOPE_CYCLE_COUNTER(STAT_NoesisInstance_OnAnalogValueChanged);
-	if (XamlView)
-	{
-		if (FMath::Abs(InAnalogEvent.GetAnalogValue()) > 0.25f)
-		{
-			if (InAnalogEvent.GetKey() == EKeys::Gamepad_RightX)
-			{
-				XamlView->HScroll(InAnalogEvent.GetAnalogValue());
-			}
-			else if (InAnalogEvent.GetKey() == EKeys::Gamepad_RightY)
-			{
-				XamlView->Scroll(InAnalogEvent.GetAnalogValue());
-			}
-		}
-	}
-
 	return Super::NativeOnAnalogValueChanged(MyGeometry, InAnalogEvent);
 }
 
@@ -1636,7 +1648,7 @@
 
 			if (Handled)
 			{
-				return FReply::Handled().PreventThrottling().CaptureMouse(MyWidget.Pin().ToSharedRef());
+				return FReply::Handled().PreventThrottling().CaptureMouse(TakeWidget());
 			}
 		}
 		else
@@ -1645,11 +1657,24 @@
 			bool Hit = HitTest(Position);
 
 			Noesis::MouseButton MouseButton = GetNoesisMouseButton(MouseEvent.GetEffectingButton());
-			bool Handled = XamlView->MouseButtonDown(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y), MouseButton);
+			bool Handled = XamlView->MouseButtonDown(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y), MouseButton) || HasMouseCapture();
 
 			if (Handled && Hit)
 			{
-				return FReply::Handled().PreventThrottling();
+				auto Reply = FReply::Handled().PreventThrottling();
+				if (SetUserFocusToViewport)
+				{
+					Reply.SetUserFocus(FSlateApplication::Get().GetGameViewport().ToSharedRef());
+				}
+				if (HasMouseCapture())
+				{
+					Reply.CaptureMouse(TakeWidget());
+				}
+				else
+				{
+					Reply.ReleaseMouseCapture();
+				}
+				return Reply;
 			}
 		}
 	}
@@ -1678,11 +1703,24 @@
 			bool Hit = HitTest(Position);
 
 			Noesis::MouseButton MouseButton = GetNoesisMouseButton(MouseEvent.GetEffectingButton());
-			bool Handled = XamlView->MouseButtonUp(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y), MouseButton);
+			bool Handled = XamlView->MouseButtonUp(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y), MouseButton) || HasMouseCapture();
 
 			if (Handled && Hit)
 			{
-				return FReply::Handled().PreventThrottling();
+				auto Reply = FReply::Handled().PreventThrottling();
+				if (SetUserFocusToViewport)
+				{
+					Reply.SetUserFocus(FSlateApplication::Get().GetGameViewport().ToSharedRef());
+				}
+				if (HasMouseCapture())
+				{
+					Reply.CaptureMouse(TakeWidget());
+				}
+				else
+				{
+					Reply.ReleaseMouseCapture();
+				}
+				return Reply;
 			}
 		}
 	}
@@ -1698,11 +1736,24 @@
 		FVector2D Position = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()) * MyGeometry.Scale;
 		bool Hit = HitTest(Position);
 
-		bool Handled = XamlView->MouseMove(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y));
+		bool Handled = XamlView->MouseMove(FPlatformMath::RoundToInt(Position.X), FPlatformMath::RoundToInt(Position.Y)) || HasMouseCapture();
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (SetUserFocusToViewport)
+			{
+				Reply.SetUserFocus(FSlateApplication::Get().GetGameViewport().ToSharedRef());
+			}
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1722,7 +1773,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1742,7 +1802,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1762,7 +1831,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1782,7 +1860,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1807,7 +1894,16 @@
 
 		if (Handled && Hit)
 		{
-			return FReply::Handled().PreventThrottling();
+			auto Reply = FReply::Handled().PreventThrottling();
+			if (HasMouseCapture())
+			{
+				Reply.CaptureMouse(TakeWidget());
+			}
+			else
+			{
+				Reply.ReleaseMouseCapture();
+			}
+			return Reply;
 		}
 	}
 
@@ -1814,6 +1910,22 @@
 	return FReply::Unhandled();
 }
 
+void UNoesisInstance::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
+{
+	if (XamlView)
+	{
+		XamlView->Activate();
+	}
+}
+
+void UNoesisInstance::NativeOnMouseLeave(const FPointerEvent& InMouseEvent)
+{
+	if (XamlView && !HasMouseCapture())
+	{
+		XamlView->Deactivate();
+	}
+}
+
 bool UNoesisInstance::NativeSupportsKeyboardFocus() const
 {
 	// SObjectWidget::OnKeyDown calls UNoesisInstance::NativeOnKeyDown. There we set SupportsKeyboardFocus = !EnableActions.
DragBehavior3.2.3.patch (11,343 bytes)   
nevayeshirazi

nevayeshirazi

2024-08-01 16:46

reporter   ~0009857

Hey,

Thanks for the updated patch but it failed again, maybe its me.
I manually applied patch to 3.2.3 Samples project but now drag and drop was not running at all in GameAndUI Input mode. It works in UIOnly input mode as before.

hcpizzi

hcpizzi

2024-08-01 17:24

developer   ~0009858

I'm sorry, those were the changes to the plugin. There's a change to the DragItemBehavior that's necessary too. Here's the patch.

DragItemBehavior.cpp.patch (846 bytes)   
Index: DragItemBehavior.cpp
===================================================================
--- DragItemBehavior.cpp	(revision 14126)
+++ DragItemBehavior.cpp	(working copy)
@@ -105,9 +105,10 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-void DragItemBehavior::OnMouseUp(BaseComponent*, const MouseButtonEventArgs&)
+void DragItemBehavior::OnMouseUp(BaseComponent* source, const MouseButtonEventArgs& e)
 {
     _mouseClicked = false;
+    e.handled = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -143,6 +144,8 @@
             });
         }
     }
+
+    e.handled = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
DragItemBehavior.cpp.patch (846 bytes)   
nevayeshirazi

nevayeshirazi

2024-08-02 11:28

reporter   ~0009859

Hey, unfortunately latest patch did not solve the issue.
However, I had to manually apply the patch by hand so I could have done a mistake.
By any chance, can you share the patch applied files instead?

Issue History

Date Modified Username Field Change
2024-07-29 22:37 nevayeshirazi New Issue
2024-07-30 13:13 jsantos Assigned To => hcpizzi
2024-07-30 13:13 jsantos Status new => assigned
2024-07-30 13:13 jsantos Target Version => 3.2.5
2024-07-30 18:11 hcpizzi Note Added: 0009851
2024-07-30 18:11 hcpizzi File Added: DragBehavior.patch
2024-07-30 18:11 hcpizzi Status assigned => feedback
2024-08-01 16:08 nevayeshirazi Status feedback => assigned
2024-08-01 16:19 hcpizzi Note Added: 0009856
2024-08-01 16:19 hcpizzi File Added: DragBehavior3.2.3.patch
2024-08-01 16:19 hcpizzi Status assigned => feedback
2024-08-01 16:46 nevayeshirazi Note Added: 0009857
2024-08-01 16:46 nevayeshirazi Status feedback => assigned
2024-08-01 17:24 hcpizzi Note Added: 0009858
2024-08-01 17:24 hcpizzi File Added: DragItemBehavior.cpp.patch
2024-08-01 17:24 hcpizzi Status assigned => feedback
2024-08-02 11:28 nevayeshirazi Note Added: 0009859
2024-08-02 11:28 nevayeshirazi Status feedback => assigned
2024-10-25 12:31 jsantos Status assigned => resolved
2024-10-25 12:31 jsantos Resolution open => fixed
2024-10-25 12:31 jsantos Fixed in Version => 3.2.5