This interface takes an additional deviceName argument to GetNextFocusableView().
The deviceName is the name of the device where the key event occurred.
A new deviceName added to GetNextFocusableView() should not affect the current app.
Current apps are using the FocusManager.ICustomFocusAlgorithm interface.
So I created a new Tizen.NUI.ICustomAwareDeviceFocusAlgorithm interface.
for example)
Currently
``` c#
class CustomInterface : FocusManager.ICustomFocusAlgorithm
{
public View GetNextFocusableView(View current, View proposed, View.FocusDirection direction)
{
return proposed;
}
}
```
If you wnat to do GetNextFocusableView() with deviceName, you can inherit ICustomAwareDeviceFocusAlgorithm.
``` c#
class CustomInterface : Tizen.NUI.ICustomAwareDeviceFocusAlgorithm
{
// This method is called when a direction key is pressed.
public View GetNextFocusableView(View current, View proposed, View.FocusDirection direction, string deviceName)
{
return proposed;
}
// This method is never called.
public View GetNextFocusableView(View current, View proposed, View.FocusDirection direction)
{
return proposed;
}
}
```
dependency
https://review.tizen.org/gerrit/#/c/platform/core/uifw/dali-toolkit/+/271983/
https://review.tizen.org/gerrit/#/c/platform/core/uifw/dali-csharp-binder/+/271984/
Interop.CustomAlgorithmInterface.DeleteCustomAlgorithmInterface(swigCPtr);
}
- public virtual View GetNextFocusableView(View current, View proposed, View.FocusDirection direction)
+ public virtual View GetNextFocusableView(View current, View proposed, View.FocusDirection direction, string deviceName = "")
{
- View ret = new View(Interop.CustomAlgorithmInterface.GetNextFocusableActor(SwigCPtr, View.getCPtr(current), View.getCPtr(proposed), (int)direction), true);
+ View ret = new View(Interop.CustomAlgorithmInterface.GetNextFocusableActor(SwigCPtr, View.getCPtr(current), View.getCPtr(proposed), (int)direction, deviceName), true);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
return hasDerivedMethod && (methodInfo != null);
}
- private global::System.IntPtr SwigDirectorGetNextFocusableView(global::System.IntPtr current, global::System.IntPtr proposed, int direction)
+ private global::System.IntPtr SwigDirectorGetNextFocusableView(global::System.IntPtr current, global::System.IntPtr proposed, int direction, string deviceName)
{
if (current == global::System.IntPtr.Zero && proposed == global::System.IntPtr.Zero)
{
View currentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
View proposedView = Registry.GetManagedBaseHandleFromNativePtr(proposed) as View;
- return View.getCPtr(GetNextFocusableView(currentView, proposedView, (View.FocusDirection)direction)).Handle;
+ return View.getCPtr(GetNextFocusableView(currentView, proposedView, (View.FocusDirection)direction, deviceName)).Handle;
}
catch (global::System.Exception ex)
{
Tizen.Log.Error("NUI", "Registry Error: " + ex);
+ throw;
}
- return global::System.IntPtr.Zero;
}
- internal delegate global::System.IntPtr SwigDelegateCustomAlgorithmInterface_0(global::System.IntPtr current, global::System.IntPtr proposed, int direction);
+ internal delegate global::System.IntPtr SwigDelegateCustomAlgorithmInterface_0(global::System.IntPtr current, global::System.IntPtr proposed, int direction, string deviceName);
private SwigDelegateCustomAlgorithmInterface_0 swigDelegate0;
- private static global::System.Type[] swigMethodTypes0 = new global::System.Type[] { typeof(View), typeof(View), typeof(View.FocusDirection) };
+ private static global::System.Type[] swigMethodTypes0 = new global::System.Type[] { typeof(View), typeof(View), typeof(View.FocusDirection), typeof(string) };
}
}
public static extern void DeleteCustomAlgorithmInterface(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_CustomAlgorithmInterface_GetNextFocusableActor")]
- public static extern global::System.IntPtr GetNextFocusableActor(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2, global::System.Runtime.InteropServices.HandleRef jarg3, int jarg4);
+ public static extern global::System.IntPtr GetNextFocusableActor(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2, global::System.Runtime.InteropServices.HandleRef jarg3, int jarg4, string deviceName);
[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_CustomAlgorithmInterface")]
public static extern global::System.IntPtr NewCustomAlgorithmInterface();
View GetNextFocusableView(View current, View proposed, View.FocusDirection direction);
}
+
/// <summary>
/// Gets or sets the status of whether the focus movement should be looped within the same focus group.<br />
/// The focus movement is not looped by default.<br />
this.customFocusAlgorithm = customFocusAlgorithm;
}
- public override View GetNextFocusableView(View current, View proposed, View.FocusDirection direction)
+ public override View GetNextFocusableView(View current, View proposed, View.FocusDirection direction, string deviceName)
{
if (customFocusAlgorithm == null)
{
Tizen.Log.Error("NUI", $"[ERROR] User defined ICustomFocusAlgorithm interface class becomes unreachable. Null will be proposed for next focusing!");
return null;
}
- return customFocusAlgorithm.GetNextFocusableView(current, proposed, direction);
+ if (customFocusAlgorithm is ICustomAwareDeviceFocusAlgorithm deviceAwared)
+ {
+ return deviceAwared.GetNextFocusableView(current, proposed, direction, deviceName);
+ }
+ else
+ {
+ return customFocusAlgorithm.GetNextFocusableView(current, proposed, direction);
+ }
}
}
}
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+using System;
+using Tizen.NUI.BaseComponents;
+using System.ComponentModel;
+
+namespace Tizen.NUI
+{
+ /// <summary>
+ /// ICustomAwareDeviceFocusAlgorithm inherits from <see cref="Tizen.NUI.FocusManager.ICustomFocusAlgorithm"/>
+ /// ICustomAwareDeviceFocusAlgorithm is used to provide the custom keyboard focus algorithm for retrieving the next focusable view.<br />
+ /// The application can implement the interface and override the keyboard focus behavior.<br />
+ /// If the focus is changing within a layout container, then the layout container is queried first to provide the next focusable view.<br />
+ /// If this does not provide a valid view, then the Keyboard FocusManager will check focusable properties to determine the next focusable actor.<br />
+ /// If focusable properties are not set, then the keyboard FocusManager calls the GetNextFocusableView() method of this interface.<br />
+ /// This interface calls GetNextFocusableView() with deviceName. <br />
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public interface ICustomAwareDeviceFocusAlgorithm : FocusManager.ICustomFocusAlgorithm
+ {
+ /// <summary>
+ /// Get the next focus actor.
+ /// </summary>
+ /// <param name="current">The current focus view.</param>
+ /// <param name="proposed">The proposed focus view</param>
+ /// <param name="direction">The focus move direction</param>
+ /// <param name="deviceName">The name of device the key event originated from</param>
+ /// <returns>The next focus actor.</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ View GetNextFocusableView(View current, View proposed, View.FocusDirection direction, string deviceName);
+ }
+}
--- /dev/null
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.NUI.Events;
+using System.Collections.Generic;
+
+namespace Tizen.NUI.Samples
+{
+ public class GetNextFocusSample : IExample
+ {
+
+ int ItemWidth = 100;
+ int ItemHeight = 100;
+ int ItemSpacing = 10;
+
+ public View TargetView = new View();
+
+ class CustomInterface : ICustomAwareDeviceFocusAlgorithm
+ {
+ // This method is called when a direction key is pressed.
+ public View GetNextFocusableView(View current, View proposed, View.FocusDirection direction, string deviceName)
+ {
+ Tizen.Log.Error("NUI", $" GetNextFocusableView deviceName {deviceName}\n");
+ return proposed;
+ }
+
+ // This method is never called.
+ public View GetNextFocusableView(View current, View proposed, View.FocusDirection direction)
+ {
+ Tizen.Log.Error("NUI", $" GetNextFocusableView \n");
+ return proposed;
+ }
+ }
+
+ public void Activate()
+ {
+ Window window = NUIApplication.GetDefaultWindow();
+
+ CustomInterface custom = new CustomInterface();
+ FocusManager.Instance.SetCustomAlgorithm(custom);
+
+ var absLayout = new View
+ {
+ Layout = new AbsoluteLayout(),
+ WidthResizePolicy = ResizePolicyType.FillToParent,
+ HeightResizePolicy = ResizePolicyType.FillToParent,
+ Focusable = true,
+ FocusableInTouch = true,
+ };
+ window.Add(absLayout);
+
+ for (int row = 0; row < 5; row++)
+ {
+ for (int cols = 0; cols < 5; cols++)
+ {
+ var btn = MakeFocusableButton($"{row * 5 + cols}");
+ btn.Position = new Position(ItemWidth + cols * (ItemWidth + ItemSpacing), ItemHeight + 300 + row * (ItemHeight + ItemSpacing));
+ absLayout.Add(btn);
+ }
+ }
+ }
+
+ View MakeFocusableButton(string title)
+ {
+ var btn = new Button
+ {
+ Focusable = true,
+ FocusableInTouch = true,
+ Text = title,
+ SizeWidth = ItemWidth,
+ SizeHeight = ItemHeight,
+ BackgroundColor = Color.Blue,
+ };
+
+ btn.FocusGained += (s, e) => btn.Text = $"[{title}]";
+ btn.FocusLost += (s, e) => btn.Text = $"{title}";
+ return btn;
+ }
+
+ public void Deactivate()
+ {
+ }
+ }
+}