Skip to content

Commit

Permalink
feat: Port FocusController
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Apr 15, 2024
1 parent 48dcf9f commit afea99b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 53 deletions.
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/Hosting/FocusController.h.mux.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace DirectUI;
partial class FocusController
{
private readonly SerialDisposable _focusDepartingEvent = new();
private CoreComponentFocusable? _coreComponentFocusable;
//private CoreComponentFocusable? _coreComponentFocusable;
private InputFocusController? _inputObjectFocusable;

private readonly SerialDisposable _gotFocusToken = new();
Expand Down
99 changes: 47 additions & 52 deletions src/Uno.UI/UI/Xaml/Hosting/FocusController.mux.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
// MUX Reference dxaml\xcp\components\UIBridgeFocus\FocusController.cpp, tag winui3/release/1.5.1, commit 3d10001ba8e12336cad392846b1030ba691b784a
#nullable enable

using System;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml.Hosting;
using Uno.Disposables;
using Uno.UI.Xaml.Input;
using Windows.Foundation;
using Windows.UI.Core;

namespace DirectUI;

internal partial class FocusController
{
public FocusController(CoreComponentFocusable pFocusable)
{
_coreComponentFocusable = pFocusable;
}
//public FocusController(CoreComponentFocusable pFocusable)
//{
// _coreComponentFocusable = pFocusable;
//}

public FocusController(InputFocusController pFocusable)
{
Expand All @@ -32,12 +34,12 @@ public FocusController(InputFocusController pFocusable)

public void Init()
{
if (_coreComponentFocusable != null)
{
_coreComponentFocusable.GotFocus += OnCoreInputGotFocus;
_gotFocusToken.Disposable = Disposable.Create(() => _coreComponentFocusable.GotFocus -= OnCoreInputGotFocus);
}
else
//if (_coreComponentFocusable != null)
//{
// _coreComponentFocusable.GotFocus += OnCoreInputGotFocus;
// _gotFocusToken.Disposable = Disposable.Create(() => _coreComponentFocusable.GotFocus -= OnCoreInputGotFocus);
//}
//else
{
var wrThis = new WeakReference<FocusController>(this);
void OnInputControllerGotFocus(object sender, FocusChangedEventArgs args)
Expand All @@ -48,7 +50,7 @@ void OnInputControllerGotFocus(object sender, FocusChangedEventArgs args)
focusController.OnGotFocusCommon();
}
}
_inputObjectFocusable.GotFocus += OnInputControllerGotFocus;
_inputObjectFocusable!.GotFocus += OnInputControllerGotFocus;
_gotFocusToken.Disposable = Disposable.Create(() => _inputObjectFocusable.GotFocus -= OnInputControllerGotFocus);
}
}
Expand All @@ -58,40 +60,39 @@ void OnInputControllerGotFocus(object sender, FocusChangedEventArgs args)
// _gotFocusToken.Disposable = null;
//}

public static IAsyncOperation<FocusController> CreateAsync(CoreComponentFocusable pFocusable)
{
var focusController = new FocusController(pFocusable);
focusController.Init();
return AsyncOperation.FromTask<FocusController>(() => focusController);
}
//public static FocusController Create(CoreComponentFocusable pFocusable)
//{
// var focusController = new FocusController(pFocusable);
// focusController.Init();
// return focusController;
//}

public static IAsyncOperation<FocusController> CreateAsync(InputFocusController pFocusable)
public static FocusController Create(InputFocusController focusable)
{
var focusController = new FocusController(pFocusable);
var focusController = new FocusController(focusable);
focusController.Init();
return AsyncOperation.FromTask<FocusController>(() => focusController);
return focusController;
}

public IAsyncOperation<XamlSourceFocusNavigationResult> NavigateFocusAsync(XamlSourceFocusNavigationRequest pRequest, FocusObserver pFocusObserver)
public XamlSourceFocusNavigationResult NavigateFocus(XamlSourceFocusNavigationRequest request, FocusObserver focusObserver)
{
_currentRequest = pRequest;
var scopeExit = new Deferral(() =>
_currentRequest = request;
using var scopeExit = Disposable.Create(() =>
{
_currentRequest = null;
});

bool isHandled = false;
pFocusObserver.ProcessNavigateFocusRequest(pRequest, out isHandled);
bool isHandled = focusObserver.ProcessNavigateFocusRequest(request);

var result = new NavigateFocusResult(isHandled);
return AsyncOperation.FromTask<XamlSourceFocusNavigationResult>(() => result);
return result;
}

internal event TypedEventHandler<object, object> FocusDeparting;
internal event TypedEventHandler<object, object>? FocusDeparting;

internal event TypedEventHandler<object, object> GotFocus;
internal event TypedEventHandler<object, object>? GotFocus;

public FocusNavigationResult DepartFocus(XamlSourceFocusNavigationRequest request)
public void DepartFocus(XamlSourceFocusNavigationRequest request)
{
var spLosingFocusRequest = new NavigationLosingFocusEventArgs(request);
var departingEventArgs = spLosingFocusRequest as DesktopWindowXamlSourceTakeFocusRequestedEventArgs;
Expand Down Expand Up @@ -134,23 +135,16 @@ public FocusNavigationResult DepartFocus(XamlSourceFocusNavigationRequest reques
var correlationId = request.CorrelationId;
var ixpRequest = FocusNavigationRequest.Create(ixpReason, hintRect, correlationId);

var inputFocusController2 = _inputObjectFocusable as InputFocusController;
var result = inputFocusController2.DepartFocusAsync(ixpRequest);
_inputObjectFocusable!.DepartFocus(ixpRequest);

// WinUI may wish to respond to the result (Moved/NotMoved/NoFocusableElements) here in some way

return AsyncOperation.FromTask<Windows.UI.Xaml.Input.FocusNavigationResult>(() => result);
}

private IAsyncAction OnCoreInputGotFocus(object sender, CoreWindowEventArgs e)
{
return OnGotFocusCommon().AsAsyncAction();
}
private void OnCoreInputGotFocus(object sender, CoreWindowEventArgs e) => OnGotFocusCommon();

private IAsyncAction OnGotFocusCommon()
private void OnGotFocusCommon()
{
var spDispatcherQueueStatics = DispatcherQueue.GetForCurrentThread();
var spDispatcherQueue = spDispatcherQueueStatics as DispatcherQueue;
var dispatcherQueue = DispatcherQueue.GetForCurrentThread();

var currentRequest = _currentRequest;
_currentRequest = null;
Expand All @@ -160,23 +154,24 @@ private IAsyncAction OnGotFocusCommon()
FireGotFocus(currentRequest);
});

spDispatcherQueue.TryEnqueue(callback);
dispatcherQueue.TryEnqueue(callback);
}

public bool HasFocus => _coreComponentFocusable != null ? _coreComponentFocusable.HasFocus : _inputObjectFocusable.HasFocus;
public bool HasFocus =>
//_coreComponentFocusable != null ? _coreComponentFocusable.HasFocus :
_inputObjectFocusable!.HasFocus;

private void FireGotFocus(XamlSourceFocusNavigationRequest pCurrentRequest)
private void FireGotFocus(XamlSourceFocusNavigationRequest? currentRequest)
{
var spRequest = pCurrentRequest ?? CreateActivationFactory_XamlSourceFocusNavigationRequest().CreateInstance(XamlSourceFocusNavigationReason.Restore);

var spArgs = new NavigationGotFocusEventArgs(spRequest);
var gotFocusEventArgs = spArgs as DesktopWindowXamlSourceGotFocusEventArgs;
var request = currentRequest;
if (request is null)
{
request = new XamlSourceFocusNavigationRequest(XamlSourceFocusNavigationReason.Restore);
}

_gotFocusEvent.InvokeAll(this, gotFocusEventArgs);
}
var args = new NavigationGotFocusEventArgs(request);
var gotFocusEventArgs = args as DesktopWindowXamlSourceGotFocusEventArgs;

private IActivationFactory CreateActivationFactory_XamlSourceFocusNavigationRequest()
{
throw new NotImplementedException();
GotFocus?.Invoke(this, gotFocusEventArgs);
}
}
14 changes: 14 additions & 0 deletions src/Uno.UI/UI/Xaml/Hosting/NavigateFocusResult.mux.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
// MUX Reference dxaml\xcp\components\UIBridgeFocus\NavigateFocusResult.cpp, tag winui3/release/1.5.1, commit 3d10001ba8e12336cad392846b1030ba691b784a

#nullable enable

namespace Microsoft.UI.Xaml.Hosting;

internal class NavigateFocusResult : XamlSourceFocusNavigationResult
{
public NavigateFocusResult(bool focusMoved) : base(focusMoved)
{
}
}

0 comments on commit afea99b

Please sign in to comment.