TouchScreenMode Fix

Made some fixes to touchscreen control detection:

* TouchScreenMode is activated on the first SDL2 FingerDown
* TouchScreenMode deactivates after the last finger is removed, and a
  mouse event happens at least 5 ticks later.
This commit is contained in:
Noah 2024-04-19 22:42:47 -07:00
parent 5b3121171e
commit b8665c8b8d
8 changed files with 63 additions and 47 deletions

View File

@ -19,7 +19,6 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/chatbot" "git.kirsle.net/SketchyMaze/doodle/pkg/chatbot"
"git.kirsle.net/SketchyMaze/doodle/pkg/gamepad" "git.kirsle.net/SketchyMaze/doodle/pkg/gamepad"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/bootstrap" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/bootstrap"
"git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
@ -251,7 +250,7 @@ func main() {
// Log some basic environment details. // Log some basic environment details.
w, h := engine.WindowSize() w, h := engine.WindowSize()
log.Info("Has touchscreen? %+v Window size: %dx%d", native.HasTouchscreen(engine), w, h) log.Info("Window size: %dx%d", w, h)
game.Run() game.Run()
return nil return nil

View File

@ -25,7 +25,7 @@ var NoCursor = &Cursor{}
// Draw the cursor on screen. NOTE: Does not draw on touchscreen devices. // Draw the cursor on screen. NOTE: Does not draw on touchscreen devices.
func Draw(e render.Engine) { func Draw(e render.Engine) {
if native.IsTouchScreenMode { if native.IsTouchScreenMode() {
return return
} }

View File

@ -141,25 +141,14 @@ func (d *Doodle) Run() error {
} }
d.event = ev d.event = ev
// If they have touched a touch screen, set the touchscreen mode boolean. This
// will hide the mouse cursor until they let up off the screen.
if !native.IsTouchScreenMode {
if ev.IsFingerDown {
log.Debug("TouchScreenMode ON!")
native.IsTouchScreenMode = true
}
} else {
if !ev.IsFingerDown {
log.Debug("TouchScreenMode OFF")
native.IsTouchScreenMode = false
}
}
// Always have an accurate idea of the window size. // Always have an accurate idea of the window size.
if ev.WindowResized { if ev.WindowResized {
d.width, d.height = d.Engine.WindowSize() d.width, d.height = d.Engine.WindowSize()
} }
// Update touch screen control (mainly whether to show the mouse cursor).
native.UpdateTouchScreenMode(ev)
// Let the gamepad controller check for events, if it's in MouseMode // Let the gamepad controller check for events, if it's in MouseMode
// it will fake the mouse cursor. // it will fake the mouse cursor.
gamepad.Loop(ev) gamepad.Loop(ev)

View File

@ -19,17 +19,6 @@ import (
// Native render engine functions (SDL2 edition), // Native render engine functions (SDL2 edition),
// not for JavaScript/WASM yet. // not for JavaScript/WASM yet.
// HasTouchscreen checks if the device has at least one SDL_GetNumTouchDevices.
//
// Note: SDL2 GetNumTouchDevices will sometimes return 0 until a touch device is actually touched. On Macbooks,
// the trackpad counts as a touch device and on first touch, HasTouchscreen may begin returning true.
func HasTouchscreen(e render.Engine) bool {
if _, ok := e.(*sdl.Renderer); ok {
return sdl2.GetNumTouchDevices() > 0
}
return false
}
// CopyToClipboard puts some text on your clipboard. // CopyToClipboard puts some text on your clipboard.
func CopyToClipboard(text string) error { func CopyToClipboard(text string) error {
if _, ok := shmem.CurrentRenderEngine.(*sdl.Renderer); ok { if _, ok := shmem.CurrentRenderEngine.(*sdl.Renderer); ok {

View File

@ -10,10 +10,6 @@ import (
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
) )
func HasTouchscreen(e render.Engine) bool {
return false
}
func TextToImage(e render.Engine, text render.Text) (image.Image, error) { func TextToImage(e render.Engine, text render.Text) (image.Image, error) {
return nil, errors.New("not supported on WASM") return nil, errors.New("not supported on WASM")
} }

View File

@ -1,12 +1,60 @@
package native package native
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
"git.kirsle.net/go/render/event"
)
// Common code to handle basic touch screen detection. // Common code to handle basic touch screen detection.
/* var (
IsTouchScreenMode is set to true when the user has touched the screen, and false when the mouse is moved. isTouchScreenMode bool
lastFingerDownTick uint64
)
This informs the game's control scheme: if the user has a touch screen and they've touched it, // IsTouchScreenMode is activated when the user has touched the screen, and false when the mouse is moved.
the custom mouse cursor is hidden (as it becomes distracting) and if they then move a real mouse func IsTouchScreenMode() bool {
over the window, the custom cursor appears again and we assume non-touchscreen mode once more. return isTouchScreenMode
}
/*
UpdateTouchScreenMode evaluates whether the primary game input is a touch screen rather than a mouse cursor.
The game always hides the OS cursor (if it exists) and may draw its own custom mouse cursor.
On a touch screen device (such as a mobile), the custom mouse cursor should not be drawn, either, as
it would jump around to wherever the user last touched and be distracting.
TouchScreenMode is activated when a touch event has been triggered (at least one finger was down).
TouchScreenMode deactivates and shows the mouse cursor when no finger is held down, and then a mouse
event has occurred. So if the user has a touch screen laptop, wiggling the actual mouse input will
bring the cursor back.
*/ */
var IsTouchScreenMode bool func UpdateTouchScreenMode(ev *event.State) {
// If a finger is presently down, record the current tick.
if ev.IsFingerDown {
lastFingerDownTick = shmem.Tick
}
if !isTouchScreenMode {
// We are NOT in touch screen mode. Touching the screen will change this.
if ev.IsFingerDown {
log.Info("TouchScreenMode ON")
isTouchScreenMode = true
}
} else {
// We ARE in touch screen mode. Wait for all fingers to be lifted.
if !ev.IsFingerDown {
// If we have registered a mouse event a few ticks after the finger was
// removed, it is a real mouse cursor and we exit touch screen mode.
if ev.IsMouseEvent && shmem.Tick-lastFingerDownTick > 5 {
log.Info("TouchScreenMode OFF")
isTouchScreenMode = false
}
}
}
}

View File

@ -5,6 +5,7 @@ import (
"git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/balance"
"git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/usercfg" "git.kirsle.net/SketchyMaze/doodle/pkg/usercfg"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
"git.kirsle.net/go/render/event" "git.kirsle.net/go/render/event"
@ -119,7 +120,9 @@ func (s *PlayScene) LoopTouchable(ev *event.State) {
// DrawTouchable draws any UI elements if needed for the touch UI. // DrawTouchable draws any UI elements if needed for the touch UI.
func (s *PlayScene) DrawTouchable() { func (s *PlayScene) DrawTouchable() {
if usercfg.Current.HideTouchHints { // If we are not in touch mode (user has not touched their screen at all), don't
// show the hints - mouse & keyboard mode. And user opt-out setting.
if !native.IsTouchScreenMode() || usercfg.Current.HideTouchHints {
return return
} }

View File

@ -18,8 +18,6 @@ import (
"path/filepath" "path/filepath"
"time" "time"
"git.kirsle.net/SketchyMaze/doodle/pkg/native"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
"git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
) )
@ -57,12 +55,6 @@ var Current = Defaults()
// Defaults returns sensible default user settings. // Defaults returns sensible default user settings.
func Defaults() *Settings { func Defaults() *Settings {
settings := &Settings{} settings := &Settings{}
// If not a touchscreen device, disable touchscreen hints as default.
if !native.HasTouchscreen(shmem.CurrentRenderEngine) {
settings.HideTouchHints = true
}
return settings return settings
} }