From cb2cc58f98d566f5efa20f6ce5d6b0a65d3c8e5a Mon Sep 17 00:00:00 2001 From: yoshisuga Date: Mon, 21 Aug 2023 20:05:34 -1000 Subject: [PATCH] iOS: Support a helper bar button to lock the current orientation (#15633) * iOS: Support a helper bar button to lock the current orientation * Moved init of shouldLockCurrentInterfaceOrientation property to iOS specific #if --- pkg/apple/HelperBar/CocoaView+HelperBar.swift | 17 ++++++++++++++ pkg/apple/HelperBar/HelperBarItem.swift | 23 +++++++++++++++++++ .../HelperBar/HelperBarViewController.swift | 6 +++++ pkg/apple/HelperBar/HelperBarViewModel.swift | 3 ++- ui/drivers/cocoa/cocoa_common.h | 3 +++ ui/drivers/cocoa/cocoa_common.m | 23 +++++++++++++++++-- 6 files changed, 72 insertions(+), 3 deletions(-) diff --git a/pkg/apple/HelperBar/CocoaView+HelperBar.swift b/pkg/apple/HelperBar/CocoaView+HelperBar.swift index 8f20e94ebb..483e428b91 100644 --- a/pkg/apple/HelperBar/CocoaView+HelperBar.swift +++ b/pkg/apple/HelperBar/CocoaView+HelperBar.swift @@ -10,8 +10,10 @@ protocol HelperBarActionDelegate: AnyObject { func keyboardButtonTapped() func mouseButtonTapped() func helpButtonTapped() + func orientationLockButtonTapped() var isKeyboardEnabled: Bool { get } var isMouseEnabled: Bool { get } + var isOrientationLocked: Bool { get } } extension CocoaView { @@ -47,6 +49,17 @@ extension CocoaView: HelperBarActionDelegate { func helpButtonTapped() { } + func orientationLockButtonTapped() { + shouldLockCurrentInterfaceOrientation.toggle() + if shouldLockCurrentInterfaceOrientation { + let currentOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? UIInterfaceOrientation.portrait + self.lockInterfaceOrientation = currentOrientation + } + if #available(iOS 16, *) { + setNeedsUpdateOfSupportedInterfaceOrientations() + } + } + var isKeyboardEnabled: Bool { !keyboardController.view.isHidden } @@ -54,4 +67,8 @@ extension CocoaView: HelperBarActionDelegate { var isMouseEnabled: Bool { mouseHandler.enabled } + + var isOrientationLocked: Bool { + shouldLockCurrentInterfaceOrientation + } } diff --git a/pkg/apple/HelperBar/HelperBarItem.swift b/pkg/apple/HelperBar/HelperBarItem.swift index bb79da79a1..dce782b999 100644 --- a/pkg/apple/HelperBar/HelperBarItem.swift +++ b/pkg/apple/HelperBar/HelperBarItem.swift @@ -9,12 +9,17 @@ protocol HelperBarItem { var image: UIImage? { get } var selectedImage: UIImage? { get } + var tintColorOnSelection: UIColor? { get } var isSelected: Bool { get } var shortDescription: String { get } var longDescription: String? { get } func action() } +extension HelperBarItem { + var tintColorOnSelection: UIColor? { nil } +} + struct KeyboardBarItem: HelperBarItem { let image = UIImage(systemName: "keyboard") let selectedImage = UIImage(systemName: "keyboard.fill") @@ -53,3 +58,21 @@ struct MouseBarItem: HelperBarItem { actionDelegate?.mouseButtonTapped() } } + +struct LockOrientationBarItem: HelperBarItem { + let image = UIImage(systemName: "lock.rotation") + let selectedImage = UIImage(systemName: "lock.rotation") + var tintColorOnSelection: UIColor? { .red } + var isSelected: Bool { actionDelegate?.isOrientationLocked ?? false } + let shortDescription = NSLocalizedString("Lock the current screen orientation", comment: "Description for orientation lock item on helper bar") + var longDescription: String? { nil } + weak var actionDelegate: HelperBarActionDelegate? + + init(actionDelegate: HelperBarActionDelegate?) { + self.actionDelegate = actionDelegate + } + + func action() { + actionDelegate?.orientationLockButtonTapped() + } +} diff --git a/pkg/apple/HelperBar/HelperBarViewController.swift b/pkg/apple/HelperBar/HelperBarViewController.swift index ab3d86a985..7ffe1585af 100644 --- a/pkg/apple/HelperBar/HelperBarViewController.swift +++ b/pkg/apple/HelperBar/HelperBarViewController.swift @@ -88,8 +88,14 @@ class HelperBarViewController: UIViewController { } if helperBarItem.isSelected { barButtonItem.image = helperBarItem.selectedImage + if let tintColor = helperBarItem.tintColorOnSelection { + barButtonItem.tintColor = tintColor + } else { + barButtonItem.tintColor = nil + } } else { barButtonItem.image = helperBarItem.image + barButtonItem.tintColor = nil } } } diff --git a/pkg/apple/HelperBar/HelperBarViewModel.swift b/pkg/apple/HelperBar/HelperBarViewModel.swift index c2186e90bc..97c03bb202 100644 --- a/pkg/apple/HelperBar/HelperBarViewModel.swift +++ b/pkg/apple/HelperBar/HelperBarViewModel.swift @@ -23,7 +23,8 @@ class HelperBarViewModel { lazy var barItems: [HelperBarItem] = [ KeyboardBarItem(actionDelegate: actionDelegate), - MouseBarItem(actionDelegate: actionDelegate) + MouseBarItem(actionDelegate: actionDelegate), + LockOrientationBarItem(actionDelegate: actionDelegate) ] var barItemMapping = [UIBarButtonItem: HelperBarItem]() diff --git a/ui/drivers/cocoa/cocoa_common.h b/ui/drivers/cocoa/cocoa_common.h index db99657fbd..eadcd7546a 100644 --- a/ui/drivers/cocoa/cocoa_common.h +++ b/ui/drivers/cocoa/cocoa_common.h @@ -68,6 +68,9 @@ @property(nonatomic,strong) UIView *helperBarView; #endif +@property(readwrite) BOOL shouldLockCurrentInterfaceOrientation; +@property(readwrite) UIInterfaceOrientation lockInterfaceOrientation; + + (CocoaView*)get; @end diff --git a/ui/drivers/cocoa/cocoa_common.m b/ui/drivers/cocoa/cocoa_common.m index dbc2506a40..f497e5d8a7 100644 --- a/ui/drivers/cocoa/cocoa_common.m +++ b/ui/drivers/cocoa/cocoa_common.m @@ -53,7 +53,6 @@ void *glkitview_init(void); ,EmulatorTouchMouseHandlerDelegate #endif > - @end #endif @@ -106,6 +105,10 @@ void *glkitview_init(void); */ self.controllerUserInteractionEnabled = YES; #endif + +#if TARGET_OS_IOS + self.shouldLockCurrentInterfaceOrientation = NO; +#endif return self; } @@ -417,7 +420,23 @@ void *glkitview_init(void); /* NOTE: This version runs on iOS6+. */ - (UIInterfaceOrientationMask)supportedInterfaceOrientations { - return (UIInterfaceOrientationMask)apple_frontend_settings.orientation_flags; + if (@available(iOS 16, *)) { + if (self.shouldLockCurrentInterfaceOrientation) { + return 1 << self.lockInterfaceOrientation; + } else { + return (UIInterfaceOrientationMask)apple_frontend_settings.orientation_flags; + } + } else { + return (UIInterfaceOrientationMask)apple_frontend_settings.orientation_flags; + } +} + +/* NOTE: This does not run on iOS 16+ */ +-(BOOL)shouldAutorotate { + if (self.shouldLockCurrentInterfaceOrientation) { + return NO; + } + return YES; } /* NOTE: This version runs on iOS2-iOS5, but not iOS6+. */