There are memory leakages when returning to the ScummVM iOS
application if it has been running in background.
The reason for the memory leaks is that the system calls the
keyCommands function every time the keyboard view became the
first responder.
Since the overloaded keys are loaded into allocated arrays
each time the keyCommands function is called they are never
released. Since the keyCommands is running in an autorelease
block, make the allocation to autorelease.
This is required since we don't utilize ARC.
The default behavior when pressing the Return key in an iOS
application is that the keyboard is dismissed. This cause
problems in games like Grim Fandango which is played using a
keyboard instead of a mouse. If the user press the Return key
the keyboard is dismissed which makes it impossible for the
user to press other keys.
Do not dismiss the keyboard when Return key is pressed.
Use the helper function to create an array of UIKeyCommands for the
END, HOME, PAGE UP, PAGE DOWN and the ESC keys. Add a generic handler
function that decides which action for which key.
This allows the application to register key presses of these keys,
however some of them requires iOS 13.4 or later.
Use the helper function to create an array of UIKeyCommands for the
Fn keys. Add a generic handler function that decides which action
for which key.
This allows the application to register key presses of the Fn keys,
however only supoorted in iOS 13.4 and later.
Use the helper function to create an array of UIKeyCommands for the
number keys. Add a generic handler function that decides which action
for which key.
Since not all keyboards have the function keys, Fn1-Fn12, e.g. the
Apple Magic Keyboard for iPads, map these keys to the number keys
when pressed together with the CMD modifier key. Fn11 and Fn12
requires CMD + Shift as modifier keys.
Use the helper function to create an array of UIKeyCommands for the
roman letter keys. Since most of the games supports input of roman
letters, overload these keys. Keys with other characters than these
are not overloaded and will therefore trigger the call to the
delegate function:
"textField:shouldChangeCharactersInRange:replacementString:"
and will therefore still be passed to the IOS7 event handler.
However no modifier flags will be passed for those and they will not
support repeated presses.
Add a generic handler function that decides which action
for which key.
Use the helper function to create an array of UIKeyCommands for the
arrow keys. Add a generic handler function that decides which action
for which key.
Since not all keyboards have the PAGE UP/DOWN nor HOME/END keys,
e.g. the Apple Magic Keyboard for iPads, map these keys to the arrow
keys when pressed together with the CMD modifier key.
Currently the key inputs are sent to the IOS7 event handler on calls
to the delegate function:
"textField:shouldChangeCharactersInRange:replacementString:"
So when typing on either the software keyboard or a connected HW
keyboard the input is handled by the hidden textfield that is in
focus. The delegate is called on each key input and the character
typed is passed to the IOS7 event handler.
Doing as above has the drawback that if they user holds down a key,
common in games when shooting or moving, the key event is only sent
once. The delegate function is only called once per distinct key
press.
By implementing the keyCommands function and create UIKeyCommands
for a set of keys, the system will call a defined callback function.
This also enables repeatedly calls as long as the key is held down.
Modifier keys can also be configured to create UIKeyCommands to
trigger custom actions. This way we can overload the key functions
when they are pressed at the same time as a modifier key.
Add helper funtions that can be used to create UIKeyCommands for
a set of keys. Keys are represented by their input, e.g. the key
for the character 'c' is defined as a string with only one char,
the 'c', while special keys are represeented by strings defined
by the OS.
Register UIKeyCommands for all types of modifier keys and add a
function that can convert system modifier flags to flags used by
ScummVM.
There is an option to show/hide the inputAccessoryView contataing
special buttons not present on the iOS system keyboard, nor the
Apple iPad Magic keyboard.
Make sure the parent frame size is resized properly depending on
the option setting and if HW keyboards are connected.
The soft keyboard is enabled by calling showKeyboard which will set
the inputView, which is a UITextField, to become the first responder.
This will trigger the software keyboard to pop up. The showKeyboard
function is either called by the GUI when clicking into an editable
box, by the engine when keyboard input is required or when the user
forces it to be shown by a gesture or pressing the on-screen control
button..
The keyboard handling above suits the software keyboard but no HW
keyboards since if the inputView is not the first responder no key
presses are registered. One can expect that key button presses on a
HW keyboard should be registered without enabling the soft keyboard.
Implement handling to enable the inputView when HW keyboards are
connected.
The accessory view can be configured to be shown or not. When it is
configured to be shown the screen size has to be adjusted according
to the height of the accessory view, also in the case when a HW
keyboard is connected.
It was noted that the screen size was not properly restored when
disabling the keyboard input. The screen size was only adjusted when
the keyboard input became enabled. The reason for that was that when
disabling the keyboard input the accessory also became hidden. So
the screen size was not updated.
Make sure to always reset the screen size when the accessory view
is configured to be visible.
When having a hardware keyboard connected to the iOS device the
software keyboard is not shown. However when using stage manager
the notification that the keyboard is shown is still triggered.
This results in that the game screen is resized even though no
keyboard is visible in the area below.
This is some kind of workaround for that where a check for any
connected hardware keyboard is made. If a keyboard is connected
then the screen is not resized, except if the accessory bar should
be shown. In that case the screen is resized only for the height
of the accessory bar.
Some games have some actions mapped to the numeric keyboard, e.g.
Indiana Jones and the last crusade fight scenes.
The alphabetical keyboard doesn't have the numeric button row so
it's a bit tricky to play these scenes without holding the "number
button switch" at the same time you need to press the correct number
button being showed.
Make it possible to switch between an alphabetical keyboard layout
to a numpad layout by adding a button to the toolbar.
The UITextField protocol function:
"textField: shouldChangeCharactersInRange: replacementString:"
was sometimes called with empty replacementStrings on key press
releases on keyboard. That triggered a backspace keyboard char to
be sent which caused problems when trying to remap actions to
other keyboard keys. No matter which key you were pressing the
resulting key would always be the backspace key.
Only handle text input using the UITextField protocol function
when the replacement string isn't empty. Handle all deletes through
the UITextInput protocol function "deleteBackword".
This has been tested in both cases when the UITextField is empty
(but GUI text field has text) and when the UITextField has text
(which has been added using the SoftKeyboard).
It has also been tested on Apple TV where a software keyboard is
shown with a big text field.
It's important that the main frame, displaying the OpenGL rendered
graphics, has the proper dimensions and depending on the device
orientation. It's also important that the frame is not covered by
the iOS keyboard.
This commit calculates the frame size depening on the orientation
and the keyboard status. The keyboard knows its parent view and
can resize it when the keyboard becomes visible or hidden.
There are multiple scenarios where the frame size is changed.
- When the keyboard is hidden/shown which can be automatically
change depending on the device orientation
- If the system demands the keyboard to get visible or hidden
- When rotating the device
- When suspending/resuming the application
There can also be combination of the scenarios above, e.g. if
suspending the application in landscape mode and resume it in
portrait mode.
A lot of effort has been put into testing different scenarios to
verify that the screen size becomes correct. However there might
be some scenario which has not been covered.
This was used in the past to make sure the code can be compiled
with old compilers that do not support using @available. But we
already dropped support for those old compilers, and in many
places already used @available without checking first that it can
be used.
The keyboard can be presented and dismissed without being triggered by
the showKeyboard/hideKeyboard functions e.g. by pressing the menu button
on the Apple TV remote while the keyboard is shown.
If the keyboard visibility is not set entirely by the showKeyboard/
hideKeyboard functions that means that the _keyboardVisible state
variable can be out of sync.
Check if the keyboard is shown based on if the inputView is the first
responder or not. The check has to be made on the main thread.
The inputAccessoryView is only shown if no hardware keyboard is
connected. Some hardware keyboards doesn't necessary have all keys,
e.g. the Apple magic keyboard to the iPads which lacks the escape
key and all function keys.
To give the user the possibility to use these buttons, always show
the inputAccessoryView.
There's a difference between UITextFields and UITextViews that the
delegate function textView:shouldChangeTextInRange:replacementText:
is called when pressing the backward button on a keyboard also when
the textView is empty. This is not the case for UITextFields, the
function textField:shouldChangeTextInRange:replacementText: is not
called if the textField is empty which is problematic in the cases
where there's already text in the open dialog (e.g. the save dialog
when the user wants to overwrite an existing slot). There's currently
no possibility to propagate existing text elements from dialog into
the textField. To be able to handle the cases where the user wants to
delete existing texts when the textField is empty the inputView has
to implement the UITextInput protocol function deleteBackward that is
called every time the backward key is pressed.
The UITextView is becoming focused by default in iOS and brings up the
keyboard for user input. This is not the case in tvOS. UITextView in
tvOS is not becoming focused by default and if manually setting it to
focused it will still not bring up the keyboard screen.
The UITextField is however becoming focused in both iOS and tvOS and
requires basically the same implementation. So the UITextView is
replaced with UITextField to bring up keyboard in both iOS and tvOS.
The UIToolbar class is not supported in tvOS. Instead implement the
toolbar as a UITabBar. The UITabBar is set directly as the
inputAccessoryView to the keyboard view in tvOS while in iOS it's put in
a UIScrollView (as the previous UIToolbar) to be able to scale the
inputAccessoryView better for small screens.
The UITabBar behaves a little bit different on iOS and tvOS where in
tvOS the delegate function
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
is called when navigated to a specific toolbar item, while in iOS called
when clicking on an item. To get the tvOS to trigger action on presses,
add a gesture recognizer to handle touch events.
Since the keyboard view on Apple TV always full screen prompted texts
gets hidden behind the keyboard. Delay the showing of the keyboard to
allow the user to understand what's requested as input.
iOS and tvOS shares a lot of code. However some there are parts that are
specific to iOS, for instance handling of UI device orientation and
certain types of gestures.
Currently there are also some limitations on the Apple TV that needs to
be flagged to the engine. There is no support for virtual keyboard, no
clipboard support and no possibility to open URLs.
Put code specific for iOS within the ObjC platfrom macro TARGET_OS_IOS.
The code specific for tvOS are put within the macro TARGET_OS_TV.
The code provided for Smartkeyboard on IPad Pro seems to be broken, so
am making minor changes to try to fix this.
The following should still function, but this will need testing by an
IOS user with this hardware, if it compiles.
These have not been compiled or otherwise tested, but are cleaned up
version of code changes from forum user "dottostring" in thread:
http://forums.scummvm.org/viewtopic.php?t=14524
This should add Fake ESC key support replacing the '`' key and add full
support for the Arrow keys.