diff --git a/PlayTools/Controls/ControlMode.swift b/PlayTools/Controls/ControlMode.swift index f690406c..f99ed3c1 100644 --- a/PlayTools/Controls/ControlMode.swift +++ b/PlayTools/Controls/ControlMode.swift @@ -14,6 +14,7 @@ public class ControlMode { public var keyboardMapped = true public static func trySwap() -> Bool { + // this function is called from `AKPlugin` when `option` is pressed. if PlayInput.shouldLockCursor { mode.show(!mode.visible) return true @@ -24,16 +25,24 @@ public class ControlMode { func setMapping(_ mapped: Bool) { if mapped { + // `parseKeymap` and `invalidate` roughly do the opposite thing PlayInput.shared.parseKeymap() } else { - show(true) + // to avoid infinite recursion + if !visible { + show(true) + } PlayInput.shared.invalidate() } keyboardMapped = mapped } func show(_ show: Bool) { - if keyboardMapped { + // special cases where function of `option` should be temparorily disabled. + // if the new auto keymapping feature is enabled, it could cause problems to switch + // cursor show state while typing. + if (!PlaySettings.shared.noKMOnInput && !editor.editorMode) + || (PlaySettings.shared.noKMOnInput && keyboardMapped) { if show { if !visible { NotificationCenter.default.post(name: NSNotification.Name.playtoolsCursorWillShow, @@ -55,6 +64,11 @@ public class ControlMode { } Toucher.writeLog(logMessage: "cursor show switched to \(show)") visible = show + if !PlaySettings.shared.noKMOnInput { + // we want to set keymapping as the reverse of curosr show status, not always false. + // as well as do some logic along with it + setMapping(!show) + } } } } diff --git a/PlayTools/Controls/PlayInput.swift b/PlayTools/Controls/PlayInput.swift index d9866252..754f2b51 100644 --- a/PlayTools/Controls/PlayInput.swift +++ b/PlayTools/Controls/PlayInput.swift @@ -16,12 +16,14 @@ class PlayInput { joystickHandler: [String: (CGFloat, CGFloat) -> Void] = [:] func invalidate() { + // this is called whenever keymapping disabled, to release all mapping resource for action in self.actions { action.invalidate() } } static public func registerButton(key: String, handler: @escaping (Bool) -> Void) { + // this function is called when setting up `button` type of mapping if "LMB" == key { PlayInput.shouldLockCursor = true } @@ -34,7 +36,13 @@ class PlayInput { func parseKeymap() { actions = [PlayMice.shared] PlayInput.buttonHandlers.removeAll(keepingCapacity: true) - PlayInput.shouldLockCursor = false + // `shouldLockCursor` is used to disable `option` toggle when there is no mouse mapping + // but in the case this new feature disabled, `option` should always function. + // this variable is initilized here to be checked for mouse mapping later. + // intialize it to the reverse of the new feature's enable state makes + // it always true if the new feature is disabled, as it won't be set false in + // any case anywhere else in this case. + PlayInput.shouldLockCursor = !PlaySettings.shared.noKMOnInput for button in keymap.keymapData.buttonModels { actions.append(ButtonAction(data: button)) } @@ -65,6 +73,8 @@ class PlayInput { Toucher.writeLog(logMessage: "editor opened? \(show)") if show { self.invalidate() + // there is no special reason to use GC API for editor, instead of NSEvents. + // just voider did this and I'm not changing it yet. if let keyboard = GCKeyboard.coalesced!.keyboardInput { keyboard.keyChangedHandler = { _, _, keyCode, pressed in PlayKeyboard.handleEditorEvent(keyCode: keyCode, pressed: pressed) @@ -154,13 +164,18 @@ class PlayKeyboard { public static func initialize() { let centre = NotificationCenter.default let main = OperationQueue.main - centre.addObserver(forName: UIApplication.keyboardDidHideNotification, object: nil, queue: main) { _ in - mode.setMapping(true) - Toucher.writeLog(logMessage: "virtual keyboard did hide") - } - centre.addObserver(forName: UIApplication.keyboardWillShowNotification, object: nil, queue: main) { _ in + if PlaySettings.shared.noKMOnInput { + centre.addObserver(forName: UIApplication.keyboardDidHideNotification, object: nil, queue: main) { _ in + mode.setMapping(true) + Toucher.writeLog(logMessage: "virtual keyboard did hide") + } + centre.addObserver(forName: UIApplication.keyboardWillShowNotification, object: nil, queue: main) { _ in + mode.setMapping(false) + Toucher.writeLog(logMessage: "virtual keyboard will show") + } + } else { + // we want to initialize keymapping to false mode.setMapping(false) - Toucher.writeLog(logMessage: "virtual keyboard will show") } AKInterface.shared!.setupKeyboard(keyboard: {keycode, pressed, isRepeat in if !mode.keyboardMapped { @@ -172,7 +187,8 @@ class PlayKeyboard { } let mapped = PlayKeyboard.handleEvent(keycode, pressed) return mapped - }, + }, // passing the function to be called when `option` pressed. + // return `true` meaning this key press is consumed, `false` dispatching it to the App swapMode: ControlMode.trySwap) } } diff --git a/PlayTools/Controls/PlayMice.swift b/PlayTools/Controls/PlayMice.swift index 487090db..d56c9a19 100644 --- a/PlayTools/Controls/PlayMice.swift +++ b/PlayTools/Controls/PlayMice.swift @@ -38,6 +38,7 @@ public class PlayMice: Action { var fakedMousePressed: Bool {fakedMouseTouchPointId != nil} public func mouseMovementMapped() -> Bool { + // this is called from `parseKeymap` to set `shouldLockCursor`'s value for handler in [PlayInput.cameraMoveHandler, PlayInput.joystickHandler] where handler[PlayMice.elementName] != nil { return true @@ -220,6 +221,9 @@ class CameraAction: Action { func invalidate() { PlayInput.cameraMoveHandler.removeValue(forKey: key) + // when noKMOnInput is false, swipe/pan gesture handler would be invalidated when keymapping disabled. + // as it's just a temporary toggle, not fixing it. + // but should remove that toggle as long as new feature considered stable. PlayInput.cameraScaleHandler[PlayMice.elementName] = nil swipeMove.invalidate() swipeScale1.invalidate() diff --git a/PlayTools/PlaySettings.swift b/PlayTools/PlaySettings.swift index 0fab777e..2f10eb37 100644 --- a/PlayTools/PlaySettings.swift +++ b/PlayTools/PlaySettings.swift @@ -71,6 +71,8 @@ let settings = PlaySettings.shared @objc lazy var customScaler = settingsData.customScaler @objc lazy var rootWorkDir = settingsData.rootWorkDir + + @objc lazy var noKMOnInput = settingsData.noKMOnInput } struct AppSettingsData: Codable { @@ -93,4 +95,5 @@ struct AppSettingsData: Codable { var inverseScreenValues = false var windowFixMethod = 0 var rootWorkDir = true + var noKMOnInput = false }