refactor toolboxView

This commit is contained in:
True Zhuanjia
2026-07-28 17:56:12 +08:00
parent 8f93cce257
commit 4a3ca7774e
8 changed files with 2174 additions and 552 deletions
+77 -11
View File
@@ -19,12 +19,14 @@ import UIKit
// MARK: - Properties
@objc public private(set) var identifier: String
@objc var cmdString: String
@objc var alias: String
// MARK: - Initialization
init(cmdString: String, alias: String) {
self.identifier = UUID().uuidString
self.cmdString = cmdString
self.alias = alias
}
@@ -36,11 +38,13 @@ import UIKit
let alias = coder.decodeObject(of: NSString.self, forKey: "alias") as String? else {
return nil
}
self.identifier = coder.decodeObject(of: NSString.self, forKey: "identifier") as String? ?? UUID().uuidString
self.cmdString = cmdString
self.alias = alias
}
public func encode(with coder: NSCoder) {
coder.encode(identifier, forKey: "identifier")
coder.encode(cmdString, forKey: "keyboardCmdString")
coder.encode(alias, forKey: "alias")
}
@@ -50,6 +54,29 @@ import UIKit
// Define the CommandManager class
@objc public class CommandManager: NSObject {
@objc public static let shared = CommandManager()
private static let defaultCommandAliasMigrationMap: [String: String] = [
"任务管理器(Task Manager)": "=taskManager",
"Task Manager": "=taskManager",
"N卡截图(Nvidia Screenshot)": "=nvidiaShot",
"Nvidia Screenshot": "=nvidiaShot",
"N卡录屏(Nvidia Screen Recording)": "=nvidiaRec",
"Nvidia Screen Recording": "=nvidiaRec",
"关闭窗口(ALT+F4)": "=closeWindow",
"Close Window": "=closeWindow",
"全选(Select All)": "=selectAll",
"Select All": "=selectAll",
"复制(Copy)": "=copy",
"Copy": "=copy",
"粘贴(Paste)": "=paste",
"Paste": "=paste",
"切换桌面(Switch to Desktop)": "=switchDesktop",
"Switch to Desktop": "=switchDesktop",
"多显模式(Project)": "=projectDisplay",
"Project": "=projectDisplay",
"Xbox Game Bar": "=xboxGameBar",
"Steam Overlay": "=steamOverlay",
]
@objc public static let mouseButtonMappings: [String: Int32] = [
"M_LEFT" : BUTTON_LEFT,
@@ -463,17 +490,17 @@ import UIKit
RemoteCommand(cmdString: "WIN", alias: "WIN"),
RemoteCommand(cmdString: "F11", alias: "F11"),
RemoteCommand(cmdString: "ESC", alias: "ESC"),
RemoteCommand(cmdString: "CTRL+SHIFT+ESC", alias: "任务管理器(Task Manager)"),
RemoteCommand(cmdString: "ALT+F1", alias: "N卡截图(Nvidia Screenshot)"),
RemoteCommand(cmdString: "ALT+F9", alias: "N卡录屏(Nvidia Screen Recording)"),
RemoteCommand(cmdString: "ALT+F4", alias: "关闭窗口(ALT+F4)"),
RemoteCommand(cmdString: "CTRL+A", alias: "全选(Select All)"),
RemoteCommand(cmdString: "CTRL+C", alias: "复制(Copy)"),
RemoteCommand(cmdString: "CTRL+V", alias: "粘贴(Paste)"),
RemoteCommand(cmdString: "WIN+D", alias: "切换桌面(Switch to Desktop)"),
RemoteCommand(cmdString: "WIN+P", alias: "多显模式(Project)"),
RemoteCommand(cmdString: "WIN+G", alias: "Xbox Game Bar"),
RemoteCommand(cmdString: "SHIFT+TAB", alias: "Steam Overlay"),
RemoteCommand(cmdString: "CTRL+SHIFT+ESC", alias: "=taskManager"),
RemoteCommand(cmdString: "ALT+F1", alias: "=nvidiaShot"),
RemoteCommand(cmdString: "ALT+F9", alias: "=nvidiaRec"),
RemoteCommand(cmdString: "ALT+F4", alias: "=closeWindow"),
RemoteCommand(cmdString: "CTRL+A", alias: "=selectAll"),
RemoteCommand(cmdString: "CTRL+C", alias: "=copy"),
RemoteCommand(cmdString: "CTRL+V", alias: "=paste"),
RemoteCommand(cmdString: "WIN+D", alias: "=switchDesktop"),
RemoteCommand(cmdString: "WIN+P", alias: "=projectDisplay"),
RemoteCommand(cmdString: "WIN+G", alias: "=xboxGameBar"),
RemoteCommand(cmdString: "SHIFT+TAB", alias: "=steamOverlay"),
]
let data = try? NSKeyedArchiver.archivedData(withRootObject: defaultCommands, requiringSecureCoding: false)
@@ -633,6 +660,29 @@ import UIKit
@objc public func getAllCommands() -> [RemoteCommand] {
return commands
}
public func reorderCommands(withIdentifiers identifiers: [String]) {
guard !identifiers.isEmpty else { return }
var remainingCommandsByID = Dictionary(grouping: commands, by: { $0.identifier })
var reorderedCommands: [RemoteCommand] = []
for identifier in identifiers {
guard var commandGroup = remainingCommandsByID[identifier],
!commandGroup.isEmpty else {
continue
}
reorderedCommands.append(commandGroup.removeFirst())
remainingCommandsByID[identifier] = commandGroup
}
for command in commands where !reorderedCommands.contains(where: { $0 === command }) {
reorderedCommands.append(command)
}
commands = reorderedCommands
saveCommands()
}
private func loadCommands() {
if let savedCommandsData = UserDefaults.standard.data(forKey: "savedCommands") {
@@ -642,6 +692,7 @@ import UIKit
// Assign the unarchived commands to your property
print(" Assign the unarchived commands to your property ")
commands = savedCommands
migrateDefaultCommandAliasesIfNeeded()
} else {
// Handle the case where the data could not be unarchived into the expected type
print("Data could not be unarchived into [RemoteCommand]")
@@ -658,6 +709,21 @@ import UIKit
UserDefaults.standard.set(data, forKey: "savedCommands")
}
}
private func migrateDefaultCommandAliasesIfNeeded() {
var didMigrate = false
for command in commands {
guard let migratedAlias = Self.defaultCommandAliasMigrationMap[command.alias] else {
continue
}
command.alias = migratedAlias
didMigrate = true
}
if didMigrate {
saveCommands()
}
}
@objc public func sendAutoReleaseComboCommand(cmdStrings: [String]?, delay: TimeInterval = 0.2, index: Int = 0, pressOnly: Bool = false, releaseOnly:Bool = false) { // we need a large delay for WAN streaming
// 如果已处理完所有按键,则开始释放按键
+180 -68
View File
@@ -23,6 +23,7 @@ final class ControllerNavigationElement: NSObject {
private var controllerNavigationSelectedIndexPathKey: UInt8 = 0
private var controllerNavigationPersistTokenKey: UInt8 = 0
private var controllerNavigationHighlightGenerationKey: UInt8 = 0
private let settingsControllerNavigationHighlightedIdentifierKey = "SettingsControllerNavigationHighlightedIdentifier"
private let hostControllerNavigationHighlightedUUIDKey = "HostControllerNavigationHighlightedUUID"
@@ -50,6 +51,27 @@ private final class ControllerMouseDisplayLinkTarget: NSObject {
func restoreControllerNavigationHighlightAfterSettingsModeSwitch()
}
protocol ControllerNavigationHighlightTargetProviding: AnyObject {
var controllerNavigationHighlightTargetView: UIView { get }
func controllerNavigationHighlightDidApply()
func controllerNavigationHighlightDidClear()
}
extension ControllerNavigationHighlightTargetProviding {
func controllerNavigationHighlightDidApply() {
}
func controllerNavigationHighlightDidClear() {
}
}
@available(iOS 13.0, *)
protocol ControllerCollectionNavigationDelegate: ControllerUINavigationDelegate where Self: UIViewController {
var controllerNavigationCollectionView: UICollectionView { get }
func controllerNavigationCurrentIndexPathForControllerNavigator() -> IndexPath?
func clearCollectionControllerNavigationHighlightForControllerNavigator()
}
@available(iOS 13.0, *)
final class ControllerNavigator: NSObject {
typealias Handler = (_ buttonDict: NSDictionary, _ gamepad: GCExtendedGamepad, _ element: GCControllerElement) -> Void
@@ -416,7 +438,7 @@ final class ControllerNavigator: NSObject {
mainFrameVC.hostCollectionVC?.clearCollectionControllerNavigationHighlightForControllerNavigator()
} else {
(uiNavigationDelegate as? SettingsViewController)?.clearControllerNavigationHighlightForControllerNavigator()
(uiNavigationDelegate as? UICollectionViewController)?.clearCollectionControllerNavigationHighlightForControllerNavigator()
(uiNavigationDelegate as? ControllerCollectionNavigationDelegate)?.clearCollectionControllerNavigationHighlightForControllerNavigator()
}
controllerNavigationHighlightedView = nil
@@ -486,6 +508,12 @@ final class ControllerNavigator: NSObject {
}
case .exit:
exit(0)
case .shortcuts:
DispatchQueue.main.async {
radialMenuView?.dismiss()
radialMenuView = nil
StreamFrameViewController.sharedInstance().bringUpToolboxMenu()
}
default:
break
}
@@ -516,7 +544,7 @@ final class ControllerNavigator: NSObject {
if radialMenuState == .moreOptions {
if mainFrameVC.isStreaming() {
RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "Game Profiles".localized, subtitle: "", symbol:PublicUtils.iOS18Available ? "gamecontroller.circle" : "gamecontroller.fill", item: .gameProfiles))
RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "=shortcuts".localized, subtitle: "", symbol: "apple.terminal", item: .mouse))
RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "=shortcuts".localized, subtitle: "", symbol: "apple.terminal", item: .shortcuts))
}
else {
if !mainFrameVC.isInAppView(), !mainFrameVC.settingsViewExpanded {RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "About".localized, subtitle: "", symbol: "questionmark.circle", item: .aboutView))}
@@ -668,7 +696,7 @@ final class ControllerNavigator: NSObject {
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView {
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView || uiNavigationDelegate is ToolboxViewController {
let verticalNavigationAxis: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .leftStickY : .rightStickY
ControllerUtil.listenPrimaryControllerStickAxis(verticalNavigationAxis, threshold: 0.6) {state in
GamepadNavigationIllustrationHud.updateActionState(for: verticalNavigationAxis, isInAction: state != .orderedSame)
@@ -679,7 +707,7 @@ final class ControllerNavigator: NSObject {
if uiNavigationDelegate is SettingsViewController {
navigateContinuously(forward: true)
}
if uiNavigationDelegate is UICollectionViewController {
if uiNavigationDelegate is ControllerCollectionNavigationDelegate {
navigateContinuously(downward: true)
}
}
@@ -688,7 +716,7 @@ final class ControllerNavigator: NSObject {
if uiNavigationDelegate is SettingsViewController {
navigateContinuously(forward: false)
}
if uiNavigationDelegate is UICollectionViewController {
if uiNavigationDelegate is ControllerCollectionNavigationDelegate {
navigateContinuously(downward: false)
}
}
@@ -698,7 +726,7 @@ final class ControllerNavigator: NSObject {
}
}
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() {
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || uiNavigationDelegate is ToolboxViewController{
let horizontalNavigationAxis: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .leftStickX : .rightStickX
ControllerUtil.listenPrimaryControllerStickAxis(horizontalNavigationAxis, threshold: 0.6) {state in
GamepadNavigationIllustrationHud.updateActionState(for: horizontalNavigationAxis, isInAction: state != .orderedSame)
@@ -706,13 +734,13 @@ final class ControllerNavigator: NSObject {
switch state {
case .orderedAscending:
if navigationTimer?.isRunning() != true {
if uiNavigationDelegate is UICollectionViewController {
if uiNavigationDelegate is ControllerCollectionNavigationDelegate {
navigateContinuously(forward: false)
}
}
case .orderedDescending:
if navigationTimer?.isRunning() != true {
if uiNavigationDelegate is UICollectionViewController {
if uiNavigationDelegate is ControllerCollectionNavigationDelegate {
navigateContinuously(forward: true)
}
}
@@ -722,7 +750,7 @@ final class ControllerNavigator: NSObject {
}
}
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView || uiNavigationDelegate is UIAlertController || uiNavigationDelegate is OSCProfilesTableViewController {
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView || uiNavigationDelegate is UIAlertController || uiNavigationDelegate is OSCProfilesTableViewController || uiNavigationDelegate is ToolboxViewController {
let navigations = uiNavigationDelegate.getNavigationElements()
let buttonNavigations = navigations.filter({$0.control.type == .button})
// let stickNavigations = navigations.filter({$0.control.type == .stick || $0.control.type == .stickAxis})
@@ -764,7 +792,7 @@ final class ControllerNavigator: NSObject {
@available(iOS 13.0, *)
extension SettingsViewController: ControllerUINavigationDelegate {
func persistControllerNavigationHighlight() {
@objc func persistControllerNavigationHighlight() {
guard let highlightedView = ControllerNavigator.controllerNavigationHighlightedView,
let identifier = controllerNavigationPersistenceIdentifier(for: highlightedView) else {
return
@@ -773,20 +801,20 @@ extension SettingsViewController: ControllerUINavigationDelegate {
UserDefaults.standard.set(identifier, forKey: settingsControllerNavigationHighlightedIdentifierKey)
}
func restoreControllerNavigationHighlight() {
@objc func restoreControllerNavigationHighlight() {
guard ControllerNavigator.enabled, ControllerUtil.primaryGCController != nil else {return}
PublicUtils.runOnMain { [weak self] in
self?.restoreControllerNavigationHighlightOnMain()
}
}
func restoreControllerNavigationHighlightAfterSettingsModeSwitch() {
@objc func restoreControllerNavigationHighlightAfterSettingsModeSwitch() {
PublicUtils.runOnMain { [weak self] in
self?.restoreControllerNavigationHighlightAfterSettingsModeSwitchOnMain()
}
}
func uiButtonActionForControllerNavigator(pressed: Bool, from navigation: ControllerNavigationElement) {
@objc func uiButtonActionForControllerNavigator(pressed: Bool, from navigation: ControllerNavigationElement) {
let isHighlightingUIStack = ControllerNavigator.controllerNavigationHighlightedView is UIStackView
if navigation.action == "holdToReorder", isHighlightingUIStack {
@@ -1427,7 +1455,8 @@ extension SettingsViewController: ControllerUINavigationDelegate {
}
}
extension UICollectionViewController {
@available(iOS 13.0, *)
extension ControllerCollectionNavigationDelegate {
var controllerNavigationSelectedIndexPath: IndexPath? {
get {
objc_getAssociatedObject(self, &controllerNavigationSelectedIndexPathKey) as? IndexPath
@@ -1446,16 +1475,49 @@ extension UICollectionViewController {
}
}
private var controllerNavigationHighlightGeneration: Int {
get {
objc_getAssociatedObject(self, &controllerNavigationHighlightGenerationKey) as? Int ?? 0
}
set {
objc_setAssociatedObject(self, &controllerNavigationHighlightGenerationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var controllerNavigationCollectionView: UICollectionView {
guard let collectionViewController = self as? UICollectionViewController else {
assertionFailure("ControllerCollectionNavigationDelegate adopters must provide controllerNavigationCollectionView")
return UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
}
return collectionViewController.collectionView
}
func applyControllerNavigationHighlight(to cell: UICollectionViewCell, highlighted: Bool) {
clearControllerNavigationHighlightBorder(in: cell)
guard highlighted else { return }
let highlightedView = controllerNavigationHighlightTargetView(for: cell)
highlightedView.layer.borderWidth = (self is HostCollectionViewController) ? 3 : 5
let isDarkTheme = ThemeManager.userInterfaceStyle() == .dark
highlightedView.layer.borderColor = ThemeManager.appPrimaryColor.withAlphaComponent(isDarkTheme ? 0.85 : 0.93).cgColor
if self is ToolboxViewController {
highlightedView.layer.borderColor = UIColor.systemOrange.withAlphaComponent(isDarkTheme ? 0.8 : 0.97).cgColor
highlightedView.layer.borderWidth = 3
}
else {
highlightedView.layer.borderColor = ThemeManager.appPrimaryColor.withAlphaComponent(isDarkTheme ? 0.85 : 0.93).cgColor
highlightedView.layer.borderWidth = (self is HostCollectionViewController) ? 3 : 5
}
(cell as? ControllerNavigationHighlightTargetProviding)?.controllerNavigationHighlightDidApply()
}
private func clearControllerNavigationHighlightBorder(in cell: UICollectionViewCell) {
if let highlightProvider = cell as? ControllerNavigationHighlightTargetProviding {
let targetView = highlightProvider.controllerNavigationHighlightTargetView
targetView.layer.borderWidth = 0
targetView.layer.borderColor = nil
highlightProvider.controllerNavigationHighlightDidClear()
return
}
for view in [cell, cell.contentView] + cell.contentView.subviews + cell.subviews {
view.layer.borderWidth = 0
view.layer.borderColor = nil
@@ -1463,6 +1525,10 @@ extension UICollectionViewController {
}
private func controllerNavigationHighlightTargetView(for cell: UICollectionViewCell) -> UIView {
if let highlightProvider = cell as? ControllerNavigationHighlightTargetProviding {
return highlightProvider.controllerNavigationHighlightTargetView
}
if let contentView = controllerNavigationContentView(in: cell) {
return contentView
}
@@ -1486,8 +1552,41 @@ extension UICollectionViewController {
}
@available(iOS 13.0, *)
extension UICollectionViewController: ControllerUINavigationDelegate {
func persistControllerNavigationHighlight() {
extension UICollectionViewController: ControllerCollectionNavigationDelegate {
@objc func persistControllerNavigationHighlight() {
controllerNavigationPersistCollectionHighlight()
}
@objc func restoreControllerNavigationHighlight() {
controllerNavigationRestoreCollectionHighlight()
}
@objc func restoreControllerNavigationHighlightAfterSettingsModeSwitch() {
}
@objc func uiWidgetActionForControllerNavigator(forward: Bool, from navigation: ControllerNavigationElement) {
}
@objc func uiButtonActionForControllerNavigator(pressed: Bool, from navigation: ControllerNavigationElement) {
controllerNavigationPerformDefaultButtonAction(pressed: pressed, from: navigation)
}
@objc func getNavigationElements() -> [ControllerNavigationElement] {
controllerNavigationDefaultNavigationElements()
}
@objc func navigateByController(forward: Bool) {
controllerNavigationNavigateCollection(forward: forward)
}
@objc func navigateByController(downward: Bool) {
controllerNavigationNavigateCollection(downward: downward)
}
}
@available(iOS 13.0, *)
extension ControllerCollectionNavigationDelegate {
func controllerNavigationPersistCollectionHighlight() {
if let hostCollectionVC = self as? HostCollectionViewController {
persistHostControllerNavigationHighlight(in: hostCollectionVC)
return
@@ -1498,7 +1597,7 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
}
}
func restoreControllerNavigationHighlight() {
func controllerNavigationRestoreCollectionHighlight() {
guard ControllerNavigator.enabled, ControllerUtil.primaryGCController != nil else {return}
PublicUtils.runOnMain { [weak self] in
@@ -1515,18 +1614,15 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
}
}
func restoreControllerNavigationHighlightAfterSettingsModeSwitch() {
}
private func currentControllerNavigationCell() -> UICollectionViewCell? {
guard let selectedIndexPath = controllerNavigationSelectedIndexPath,
selectedIndexPath.section < collectionView.numberOfSections,
selectedIndexPath.section < controllerNavigationCollectionView.numberOfSections,
selectedIndexPath.item >= 0,
selectedIndexPath.item < collectionView.numberOfItems(inSection: selectedIndexPath.section) else {
selectedIndexPath.item < controllerNavigationCollectionView.numberOfItems(inSection: selectedIndexPath.section) else {
return nil
}
return collectionView.cellForItem(at: selectedIndexPath)
return controllerNavigationCollectionView.cellForItem(at: selectedIndexPath)
}
private func currentControllerNavigationContentView() -> UIView? {
@@ -1534,7 +1630,7 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
return controllerNavigationContentView(in: cell)
}
func uiButtonActionForControllerNavigator(pressed: Bool, from navigation: ControllerNavigationElement) {
func controllerNavigationPerformDefaultButtonAction(pressed: Bool, from navigation: ControllerNavigationElement) {
PublicUtils.runOnMain { [weak self] in
guard let self else { return }
@@ -1570,10 +1666,7 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
}
}
func uiWidgetActionForControllerNavigator(forward: Bool, from navigation: ControllerNavigationElement) {
}
func getNavigationElements() -> [ControllerNavigationElement] {
func controllerNavigationDefaultNavigationElements() -> [ControllerNavigationElement] {
var elements: [ControllerNavigationElement] = []
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButton, action: "radialMenu"))
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .rightStick : .leftStick, action: "focusNavigation"))
@@ -1584,13 +1677,13 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
return elements
}
func navigateByController(forward: Bool) {
func controllerNavigationNavigateCollection(forward: Bool) {
guard hasNoPresentedVC else { return }
performControllerNavigationSelectionMove(horizontalOffset: forward ? 1 : -1)
scheduleControllerNavigationHighlightPersistenceWhenStickSettles()
}
func navigateByController(downward: Bool) {
func controllerNavigationNavigateCollection(downward: Bool) {
guard hasNoPresentedVC else { return }
performControllerNavigationSelectionMove(verticalOffset: downward ? 1 : -1)
scheduleControllerNavigationHighlightPersistenceWhenStickSettles()
@@ -1648,7 +1741,7 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
continue
}
highlightControllerNavigationItem(at: IndexPath(item: index, section: 0))
controllerNavigationHighlightItemForControllerNavigator(at: IndexPath(item: index, section: 0))
return
}
@@ -1674,7 +1767,7 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
}
for (index, app) in mainFrameVC.sortedAppList.enumerated() where app.id == appID {
highlightControllerNavigationItem(at: IndexPath(item: index, section: 0))
controllerNavigationHighlightItemForControllerNavigator(at: IndexPath(item: index, section: 0))
return
}
@@ -1682,13 +1775,13 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
}
private func restoreFirstControllerNavigationItemIfNeeded() {
guard collectionView.numberOfSections > 0,
collectionView.numberOfItems(inSection: 0) > 0 else {
guard controllerNavigationCollectionView.numberOfSections > 0,
controllerNavigationCollectionView.numberOfItems(inSection: 0) > 0 else {
clearCollectionControllerNavigationHighlight()
return
}
highlightControllerNavigationItem(at: IndexPath(item: 0, section: 0))
controllerNavigationHighlightItemForControllerNavigator(at: IndexPath(item: 0, section: 0))
}
private func performControllerNavigationSelectionMove(horizontalOffset: Int) {
@@ -1704,23 +1797,23 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
}
private func moveControllerNavigationSelection(horizontalOffset: Int) {
let itemCount = collectionView.numberOfItems(inSection: 0)
let itemCount = controllerNavigationCollectionView.numberOfItems(inSection: 0)
guard itemCount > 0 else {
clearCollectionControllerNavigationHighlight()
return
}
guard let currentIndexPath = currentControllerNavigationIndexPath() else {
highlightControllerNavigationItem(at: IndexPath(item: horizontalOffset >= 0 ? 0 : itemCount - 1, section: 0))
controllerNavigationHighlightItemForControllerNavigator(at: IndexPath(item: horizontalOffset >= 0 ? 0 : itemCount - 1, section: 0))
return
}
let nextItem = (currentIndexPath.item + horizontalOffset + itemCount) % itemCount
highlightControllerNavigationItem(at: IndexPath(item: nextItem, section: currentIndexPath.section))
controllerNavigationHighlightItemForControllerNavigator(at: IndexPath(item: nextItem, section: currentIndexPath.section))
}
private func moveControllerNavigationSelection(verticalOffset: Int) {
let itemCount = collectionView.numberOfItems(inSection: 0)
let itemCount = controllerNavigationCollectionView.numberOfItems(inSection: 0)
guard itemCount > 0 else {
clearCollectionControllerNavigationHighlight()
return
@@ -1728,7 +1821,7 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
guard let currentIndexPath = currentControllerNavigationIndexPath(),
let currentAttributes = layoutAttributesForItem(at: currentIndexPath) else {
highlightControllerNavigationItem(at: IndexPath(item: verticalOffset >= 0 ? 0 : itemCount - 1, section: 0))
controllerNavigationHighlightItemForControllerNavigator(at: IndexPath(item: verticalOffset >= 0 ? 0 : itemCount - 1, section: 0))
return
}
@@ -1767,65 +1860,77 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
}?.indexPath
if let nextIndexPath {
highlightControllerNavigationItem(at: nextIndexPath)
controllerNavigationHighlightItemForControllerNavigator(at: nextIndexPath)
}
}
private func currentControllerNavigationIndexPath() -> IndexPath? {
if let selectedIndexPath = controllerNavigationSelectedIndexPath,
selectedIndexPath.section < collectionView.numberOfSections,
selectedIndexPath.item < collectionView.numberOfItems(inSection: selectedIndexPath.section) {
selectedIndexPath.section < controllerNavigationCollectionView.numberOfSections,
selectedIndexPath.item < controllerNavigationCollectionView.numberOfItems(inSection: selectedIndexPath.section) {
return selectedIndexPath
}
if let highlightedView = ControllerNavigator.controllerNavigationHighlightedView,
let highlightedCell = collectionViewCell(containing: highlightedView),
let indexPath = collectionView.indexPath(for: highlightedCell) {
let indexPath = controllerNavigationCollectionView.indexPath(for: highlightedCell) {
return indexPath
}
return nil
}
private func highlightControllerNavigationItem(at indexPath: IndexPath) {
func controllerNavigationCurrentIndexPathForControllerNavigator() -> IndexPath? {
currentControllerNavigationIndexPath()
}
func controllerNavigationHighlightItemForControllerNavigator(at indexPath: IndexPath) {
PublicUtils.runOnMain { [weak self] in
guard let self else { return }
guard indexPath.section < self.collectionView.numberOfSections,
let collectionView = self.controllerNavigationCollectionView
guard indexPath.section < collectionView.numberOfSections,
indexPath.item >= 0,
indexPath.item < self.collectionView.numberOfItems(inSection: indexPath.section) else {
indexPath.item < collectionView.numberOfItems(inSection: indexPath.section) else {
self.clearCollectionControllerNavigationHighlight()
return
}
self.collectionView.layoutIfNeeded()
collectionView.layoutIfNeeded()
let previousIndexPath = self.controllerNavigationSelectedIndexPath
self.controllerNavigationHighlightGeneration += 1
let highlightGeneration = self.controllerNavigationHighlightGeneration
self.controllerNavigationSelectedIndexPath = indexPath
if let previousIndexPath,
previousIndexPath != indexPath,
let previousCell = self.collectionView.cellForItem(at: previousIndexPath) {
let previousCell = collectionView.cellForItem(at: previousIndexPath) {
self.applyControllerNavigationHighlight(to: previousCell, highlighted: false)
}
self.collectionView.scrollToItem(at: indexPath, at: [.centeredHorizontally, .centeredVertically], animated: true)
collectionView.scrollToItem(at: indexPath, at: [.centeredHorizontally, .centeredVertically], animated: true)
self.applyControllerNavigationHighlightWhenCellIsReady(at: indexPath, generation: highlightGeneration, remainingAttempts: 8)
}
}
if let cell = self.collectionView.cellForItem(at: indexPath) {
self.applyControllerNavigationHighlight(to: cell, highlighted: true)
ControllerNavigator.controllerNavigationHighlightedView = self.controllerNavigationHighlightTargetView(for: cell)
}
private func applyControllerNavigationHighlightWhenCellIsReady(at indexPath: IndexPath, generation: Int, remainingAttempts: Int) {
guard controllerNavigationSelectedIndexPath == indexPath,
controllerNavigationHighlightGeneration == generation else { return }
DispatchQueue.main.async { [weak self] in
guard let self,
self.controllerNavigationSelectedIndexPath == indexPath,
let cell = self.collectionView.cellForItem(at: indexPath) else {
return
}
let collectionView = controllerNavigationCollectionView
collectionView.layoutIfNeeded()
self.applyControllerNavigationHighlight(to: cell, highlighted: true)
ControllerNavigator.controllerNavigationHighlightedView = self.controllerNavigationHighlightTargetView(for: cell)
}
if let cell = collectionView.cellForItem(at: indexPath) {
applyControllerNavigationHighlight(to: cell, highlighted: true)
ControllerNavigator.controllerNavigationHighlightedView = controllerNavigationHighlightTargetView(for: cell)
return
}
guard remainingAttempts > 0 else { return }
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { [weak self] in
self?.applyControllerNavigationHighlightWhenCellIsReady(at: indexPath, generation: generation, remainingAttempts: remainingAttempts - 1)
}
}
@@ -1834,21 +1939,28 @@ extension UICollectionViewController: ControllerUINavigationDelegate {
guard let self else { return }
if let selectedIndexPath = self.controllerNavigationSelectedIndexPath,
let cell = self.collectionView.cellForItem(at: selectedIndexPath) {
let cell = self.controllerNavigationCollectionView.cellForItem(at: selectedIndexPath) {
self.applyControllerNavigationHighlight(to: cell, highlighted: false)
}
self.controllerNavigationHighlightGeneration += 1
self.controllerNavigationSelectedIndexPath = nil
ControllerNavigator.controllerNavigationHighlightedView = nil
}
}
fileprivate func clearCollectionControllerNavigationHighlightForControllerNavigator() {
func clearCollectionControllerNavigationHighlightForControllerNavigator() {
clearCollectionControllerNavigationHighlight()
}
func invalidateCollectionControllerNavigationHighlightForControllerNavigator() {
controllerNavigationHighlightGeneration += 1
controllerNavigationSelectedIndexPath = nil
ControllerNavigator.controllerNavigationHighlightedView = nil
}
private func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
collectionView.collectionViewLayout.layoutAttributesForItem(at: indexPath)
controllerNavigationCollectionView.collectionViewLayout.layoutAttributesForItem(at: indexPath)
}
private func collectionViewCell(containing view: UIView) -> UICollectionViewCell? {
+468 -120
View File
@@ -866,7 +866,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Close"
"value" : "Close Window"
}
},
"zh-Hans" : {
@@ -2519,25 +2519,25 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Nvidia Rec"
"value" : "NVIDIA Recording"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "N卡录屏"
"value" : "NVIDIA 录屏"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "N卡錄影"
"value" : "NVIDIA 螢幕錄影"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "N卡錄影"
"value" : "NVIDIA 螢幕錄影"
}
}
}
@@ -2548,25 +2548,25 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Nvidia Shot"
"value" : "NVIDIA Screenshot"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "N卡截图"
"value" : "NVIDIA 截图"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "N卡截圖"
"value" : "NVIDIA 螢幕截圖"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "N卡截圖"
"value" : "NVIDIA 螢幕截圖"
}
}
}
@@ -2832,6 +2832,35 @@
}
}
},
"=projectDisplay" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Project Display"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "投影显示"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "投影顯示"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "投影顯示"
}
}
}
},
"=prone" : {
"extractionState" : "manual",
"localizations" : {
@@ -3470,6 +3499,64 @@
}
}
},
"=steamOverlay" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Steam Overlay"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "Steam 覆盖层"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "Steam 覆蓋介面"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "Steam 覆蓋介面"
}
}
}
},
"=switchDesktop" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Switch to Desktop"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "切换到桌面"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "切換到桌面"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "切換到桌面"
}
}
}
},
"=switchWindow" : {
"extractionState" : "manual",
"localizations" : {
@@ -3586,6 +3673,151 @@
}
}
},
"=toolboxDisconnectQuit" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Disconnect & Quit"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "断开并退出"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "斷線並退出"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "斷線並退出"
}
}
}
},
"=toolboxSoftKeyboard" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Soft Keyboard"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "软键盘"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "軟體鍵盤"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "軟體鍵盤"
}
}
}
},
"=toolboxStatsOverlay" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Stats Overlay"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "统计覆盖层"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "統計覆蓋層"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "統計覆蓋層"
}
}
}
},
"=toolboxSwitchProfile" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Switch Profile"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "切换配置"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "切換配置"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "切換配置"
}
}
}
},
"=toolboxWidgetLayout" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Edit Layout"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "编辑布局"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "編輯佈局"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "編輯佈局"
}
}
}
},
"=ult" : {
"extractionState" : "manual",
"localizations" : {
@@ -3876,6 +4108,35 @@
}
}
},
"=xboxGameBar" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Xbox Game Bar"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "Xbox 游戏栏"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "Xbox 遊戲列"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "Xbox 遊戲列"
}
}
}
},
"=zoomIn" : {
"extractionState" : "manual",
"localizations" : {
@@ -4256,6 +4517,35 @@
}
}
},
"addEntry" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Add Entry"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "新增条目"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "新增條目"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "新增條目"
}
}
}
},
"Adjust the pressure curve by adding or dragging the purple squares." : {
"extractionState" : "manual",
"localizations" : {
@@ -6716,6 +7006,35 @@
}
}
},
"doublePressPinExecute" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Double Press Pin Execute"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "双击执行不退出"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "雙擊執行不退出"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "雙擊執行不退出"
}
}
}
},
"doublePressToAddFavorite" : {
"extractionState" : "manual",
"localizations" : {
@@ -7742,6 +8061,35 @@
}
}
},
"execute" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Execute"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "执行"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "執行"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "執行"
}
}
}
},
"exit" : {
"extractionState" : "manual",
"localizations" : {
@@ -10193,35 +10541,6 @@
}
}
},
"leftButton" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Left Button"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "鼠标左键"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "滑鼠左鍵"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "滑鼠左鍵"
}
}
}
},
"Layout of the Default profile can not be changed" : {
"extractionState" : "manual",
"localizations" : {
@@ -10504,6 +10823,35 @@
}
}
},
"leftButton" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Left Button"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "鼠标左键"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "滑鼠左鍵"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "滑鼠左鍵"
}
}
}
},
"legacyFramePacingTip" : {
"extractionState" : "manual",
"localizations" : {
@@ -11410,6 +11758,29 @@
}
}
},
"Move the stick you want to use for mouse control. The other stick will be used for vertical and horizontal scrolling" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "移动用于控制鼠标指针的摇杆。另一侧的摇杆将用于控制垂直、水平滚动。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "移動用於控制滑鼠指標的搖桿。另一側的搖桿將用於控制垂直、水平滾動。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "移動用於控制滑鼠指標的搖桿。另一側的搖桿將用於控制垂直、水平滾動。"
}
}
}
},
"moveCursor" : {
"extractionState" : "manual",
"localizations" : {
@@ -11439,29 +11810,6 @@
}
}
},
"Move the stick you want to use for mouse control. The other stick will be used for vertical and horizontal scrolling" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "移动用于控制鼠标指针的摇杆。另一侧的摇杆将用于控制垂直、水平滚动。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "移動用於控制滑鼠指標的搖桿。另一側的搖桿將用於控制垂直、水平滾動。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "移動用於控制滑鼠指標的搖桿。另一側的搖桿將用於控制垂直、水平滾動。"
}
}
}
},
"name" : {
"extractionState" : "manual",
"localizations" : {
@@ -14679,35 +15027,6 @@
}
}
},
"rightButton" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Right Button"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "鼠标右键"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "滑鼠右鍵"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "滑鼠右鍵"
}
}
}
},
"Right Button" : {
"extractionState" : "manual",
"localizations" : {
@@ -14777,6 +15096,35 @@
}
}
},
"rightButton" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Right Button"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "鼠标右键"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "滑鼠右鍵"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "滑鼠右鍵"
}
}
}
},
"Roll factor: %.2f" : {
"extractionState" : "manual",
"localizations" : {
@@ -17618,35 +17966,6 @@
}
}
},
"verticalHorizontalScroll" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Scroll"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "横纵滚动"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "橫縱捲動"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "橫縱捲動"
}
}
}
},
"Velocity-based right stick pad" : {
"extractionState" : "manual",
"localizations" : {
@@ -17730,6 +18049,35 @@
},
"Version %@" : {
},
"verticalHorizontalScroll" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Scroll"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "横纵滚动"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "橫縱捲動"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "橫縱捲動"
}
}
}
},
"Video" : {
"extractionState" : "manual",
@@ -18514,4 +18862,4 @@
}
},
"version" : "1.1"
}
}
@@ -208,7 +208,9 @@ class HostCollectionViewController: UICollectionViewController, UICollectionView
if let host = items[indexPath.item] as? TemporaryHost {
cell.configure(with: host)
}
applyControllerNavigationHighlight(to: cell, highlighted: indexPath == controllerNavigationSelectedIndexPath)
if #available(iOS 13.0, *) {
applyControllerNavigationHighlight(to: cell, highlighted: indexPath == controllerNavigationSelectedIndexPath)
}
return cell
}
@@ -62,5 +62,6 @@
- (void)setMagnifierViewportInteractionEnabled:(BOOL)enabled;
- (void)resetMagnifierStreamViewWithAnimated:(BOOL)animated;
- (void)returnToMainFrame;
- (void)bringUpToolboxMenu;
@end
File diff suppressed because it is too large Load Diff
+1
View File
@@ -25,6 +25,7 @@ import UIKit
case more
case navigationSettings
case exit
case shortcuts
}
@objc public enum RadialMenuState:Int {
@@ -221,4 +221,16 @@ public final class WidgetPickerViewController: UIViewController {
hostViewController.setNeedsUpdateOfScreenEdgesDeferringSystemGestures()
hostViewController.setNeedsUpdateOfHomeIndicatorAutoHidden()
}
@objc func getNavigationElements() -> [ControllerNavigationElement] {
var elements: [ControllerNavigationElement] = []
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .rightStick : .leftStick, action: "focusNavigation"))
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "execute"))
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "doublePressPinExecute"))
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .y, action: "holdToReorder"))
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .y, action: "doublePressToDelete"))
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadLeft : .x, action: "addEntry"))
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadDown : .b, action: "exit"))
return elements
}
}