DevFear
Topic Author
Posts: 53
Joined: 29 Jun 2022, 12:36

How does focus work?

23 May 2023, 13:22

The task is simple - to reproduce the behavior of the menu. That is, it is necessary that the menu closes when the user clicks outside the area of this element.

The LostFocus event is triggered, but it is also triggered when clicking on child elements. The WPF community suggests using FocusManager to solve this problem, but.... FocusManager is missing in Noesis.

Then I looked at how the MenuBase class is implemented and used the LostMouseCapture Event + Mouse mechanisms.Capture. Everything would be fine, but the Original Source is used in the source, while the OriginalSource is also missing in Noesis. At the same time, Source returns not the processed class, but its parent (Parent - Menu - Child)

Is it possible to learn more about how the focusing system works in Noesis? What mechanisms are available on Unity (C#) so that focus can be easily controlled? Can you help me with the task?

Alternative MenuBase examle:
EventManager.RegisterClassHandler(typeof(SelectionPanel), Mouse.LostMouseCaptureEvent, new MouseEventHandler(OnLostMouseCaptured));
private static void OnLostMouseCaptured(object sender, MouseEventArgs e)
		{
			var panel = sender as SelectionPanel;
			var mouse = panel.Mouse;
			var captured = mouse.Captured;


			UIDebug.Log(captured);

			if (captured == panel)
				return;

			if (e.Source == panel)
			{
				if (captured == null)
				{
					UIDebug.Log("Lost Mouse Capture! Null");
					return;
				}

				if (!captured.IsDescendant(panel))
					UIDebug.Log("Lost Mouse Capture! Is not Descendant");

				return;
			}
			
			if (e.Source is DependencyObject dObject && dObject.IsDescendant(panel))
			{
				if (panel.IsOpened && captured == null)
				{
					UIDebug.Log("Capture!");

					mouse.Capture(panel, CaptureMode.SubTree);
					e.Handled = true;
				}

				return;
			}

			UIDebug.Log("Lost Mouse Capture!");
		}
 
DevFear
Topic Author
Posts: 53
Joined: 29 Jun 2022, 12:36

Re: How does focus work?

23 May 2023, 19:12

I figured out Mouse a bit.Capture, and I managed to reproduce the logic of MenuBase (I'm just checking when the click happens outside of the element).

Another problem I found: If I see that the user clicks on any button outside of the elements, then I call Mouse.Capture(null) to release the mouse capture. However, in this case, the event for the button is not thrown. That is, the user needs to press 2 times to make the button work.

Another approach is not to use Mouse.Capture, but then the MouseDown event will have to be tracked on the parent element, which should cover the entire screen so that mouse clicks outside the element can be tracked.
 
User avatar
sfernandez
Site Admin
Posts: 2991
Joined: 22 Dec 2011, 19:20

Re: How does focus work?

24 May 2023, 13:05

The task is simple - to reproduce the behavior of the menu. That is, it is necessary that the menu closes when the user clicks outside the area of this element.
If you use a Popup with StaysOpen="False" that is the default behavior, clicking outside its area will close it. Have you tried that?
Another problem I found: If I see that the user clicks on any button outside of the elements, then I call Mouse.Capture(null) to release the mouse capture. However, in this case, the event for the button is not thrown. That is, the user needs to press 2 times to make the button work.
In Noesis we have code that re-raises Preview/MouseDown events when a Menu/ContextMenu was opened and a click occurs outside the popup. If you are not inheriting from those classes, it could be an option for you to do the same: after closing your custom menu do a HitTest to get the element under the mouse, and raise the PreviewMouseDown and MouseDown events on that element.

Who is online

Users browsing this forum: Google [Bot], jsantos, Semrush [Bot] and 9 guests