"Touchpad mode" is a mode where the mouse cursor is moved based on touch
movements rather on clicks. The problem was that when "touchpad mode"
was enabled it was very hard to click on items because the cursor moved
on every single click.
Make the action occur based on the current pointer position rather on
the touch location when in "touchpad mode".
Make the movement more intuitive when in "touchpad mode" by calculating
the delta of locations of touches and update the pointerPosition based
on that. That will give a feeling of using a real touchpad where the
location of where the touch occur doesn't matter for the cursor.
This will solve issue #13917
Add support for Extended Gamepad controllers. What defines extended
gamepad controllers can be found here:
https://developer.apple.com/documentation/gamecontroller/gcextendedgamepad
Support has been added for controlling the pointer position using the
left thumbstick, left clicks using the A-button and right clicks using
the B-button. Also the Main menu can be accessed using the Home/Menu
button.
The thumbstick values are received when changed, however if holding the
thumbstick in the same position the valueChangedHandler will not be
called. Therefore store the X- and Y-axis values and begin to poll
readings of the stored values for as long as the thumbstick is out of
the center position.
Joystick actions are suitable for joysticks and gamepads where the
movements are updated by a controller stick. On gamepads that's usually
a thumbstick.
Add joystick events which can be triggered by each implemented
controller that should utilize the ScummVM Joystick events.
Add support for mouses using the GameController framework. This requires
iOS 14 and up. The trackpad on the magic keyboard to iPads is connected
as a mouse and of course other connected mouses.
The mouse movements triggers calls to the mouseMovedHandler code
block. The calls delivers delta movements on the X and Y axis from the
last pointer position. It doesn't keep track on where the pointer is in
the view. That's where pointerPosition property in the iPhoneView comes
into place.
Move touch inputs to a TouchController class to move some logic from the
iPhoneView class. Only do this for touches on screen since connected
trackpads can generate touches as well. The latter ones are of type
UITouchTypeIndirectPointer while touches on screen are of type
UITouchTypeDirect. They are separated thanks to the preference key
UIApplicationSupportsIndirectInputEvents set to YES in Info.plist.
Without the preference above, there is no way to distinguish touches
from screen from a trackpad.
Add a GameController base class which handles user inputs from a
controller. The input is either a pointer move or a button action.
If the input is a pointer move, make sure that the move is within
valid coordinates in the game (respecting the resolution which is
most probably lower than the view resolution).
Setting this property to true indicates the view controller’s preference
to lock the pointer, although the system may not honor the request.
For the system to consider locking the pointer:
The scene must be full screen, not in Split View or Slide Over, with no
other apps in Slide Over.
The scene must be in the UISceneActivationStateForegroundActive state.
The ScummVM iOS7 client fulfills the above so the pointer is locked.
Locking the pointer hides the OS cursor (the dot), however that's wanted
since the ScummVM engine draws its own pointer.
==3124361== Invalid write of size 8
==3124361== at 0x483F803: memmove (vg_replace_strmem.c:1270)
==3124361== by 0x4DBF61: SurfaceSdlGraphicsManager::grabOverlay(void*, int) const (surfacesdl-graphics.cpp:1753)
==3124361== by 0x482051: ModularGraphicsBackend::grabOverlay(void*, int) (modular-backend.cpp:215)
==3124361== by 0x434EE1: GUI::ThemeEngine::clearAll() (ThemeEngine.cpp:376)
==3124361== by 0x40128E: GUI::EventRecorder::preDrawOverlayGui() (EventRecorder.cpp:558)
==3124361== by 0x481DB2: ModularGraphicsBackend::updateScreen() (modular-backend.cpp:173)
==3124361== by 0x559967: Graphics::Screen::updateScreen() (screen.cpp:62)
==3124361== by 0x55991C: Graphics::Screen::update() (screen.cpp:56)
==3124361== by 0x38AFC7: TwinE::TwineScreen::update() (twine.cpp:126)
==3124361== by 0x3B8759: TwinE::Screens::adjustPalette(unsigned char, unsigned char, unsigned char, unsigned int const*, int) (screens.cpp:150)
==3124361== by 0x3B8A89: TwinE::Screens::fadeToPal(unsigned int const*) (screens.cpp:207)
==3124361== by 0x3B8403: TwinE::Screens::loadImage(int, int, bool) (screens.cpp:80)
==3124361== Address 0x31453050 is 16 bytes after a block of size 512,000 alloc'd
==3124361== at 0x483AB65: calloc (vg_replace_malloc.c:760)
==3124361== by 0x55B38C: Graphics::Surface::create(unsigned short, unsigned short, Graphics::PixelFormat const&) (surface.cpp:75)
==3124361== by 0x551111: Graphics::ManagedSurface::create(unsigned short, unsigned short, Graphics::PixelFormat const&) (managed_surface.cpp:153)
==3124361== by 0x4352D5: GUI::ThemeEngine::setGraphicsMode(GUI::ThemeEngine::GraphicsMode) (ThemeEngine.cpp:453)
==3124361== by 0x434A52: GUI::ThemeEngine::init() (ThemeEngine.cpp:324)
==3124361== by 0x43501B: GUI::ThemeEngine::refresh() (ThemeEngine.cpp:394)
==3124361== by 0x405780: GUI::GuiManager::screenChange() (gui-manager.cpp:603)
==3124361== by 0x405C6B: GUI::GuiManager::processEvent(Common::Event const&, GUI::Dialog*) (gui-manager.cpp:677)
==3124361== by 0x404EBA: GUI::GuiManager::runLoop() (gui-manager.cpp:429)
==3124361== by 0x3FD847: GUI::Dialog::runModal() (dialog.cpp:77)
==3124361== by 0x36D747: launcherDialog() (main.cpp:106)
==3124361== by 0x36FF92: scummvm_main (main.cpp:552)
It looks like the _videoMode.overlayHeight in SurfaceSdlGraphicsManager::grabOverlay and ThemeEngine::_backBuffer::h are somehow out of sync after
starting the game in a different resolution as the gui was started with. So the overlayHeight is updated - but the backbuffer (Surface) is not resized.
This is with event recorder being active - right after starting the game and switching the resolution.
This fixes an assert with the new GUI (bug #12578).
This also required changing the logic to handle the cursor key color
as the new GUI does not use that key color but use the alpha channel.
The logic in the iOS backend was overwriting the alpha channel
by checking the key color, removing all the transparency. Now the
two are combined (hopefully there is no case were it uses the key
color while also using a pixel format with alpha, but not setting
this alpha, because if there is, this will now result in a fully
transparent cursor).