Incorrect screen coordinates on iphone html5 mobile (DEF-3526) (SOLVED)

“action.screen_y” passed to “on_input” becomes incorrect if we move a touch for some distance

Test app:
http://dev.low-entropy.com/static/demos/defold_coors_bug_2/

Steps:

  1. Open test app in safari or chrome on an iPhone
  2. Touch app close to screen top, you will see coors like, action.screen_x,y = 480, 1090
  3. Then touch app close to screen bottom and slowly move it to the same top position, you will see coors like 480, 800
  4. 1090 - is correct “y” coordinate and 800 is incorrect “y” coordinate
  5. for horizontal “x” coor all seem fine for some reason…

Code from test app:

panel.gui_script

function on_input(self, action_id, action)	
	local coors_str = "action.x,y = " .. math.round(action.x) .. ", " .. math.round(action.y)
	local coors_str_2 = "action.screen_x,y = " .. math.round(action.screen_x) .. ", " .. math.round(action.screen_y)
	gui.set_text(gui.get_node("coors_text"), coors_str)
	gui.set_text(gui.get_node("coors_text_2"), coors_str_2)
end

defold version: 1.2.136
Device: iPhone 6
iOS 11.3.1
browser: Safari

2 Likes

Nice find, very strange! Added an issue for this: DEF-3526

Thanks!

Seem I have found the reason of the issue and possible solution.

We had to investigate the issue because our game targets Facebook Instant games (html5) and actively uses touch moves.

I was able to reproduce same issued in simple html5 page, without defold engine involved - and saw the same issue for distant vertical moving:

http://dev.low-entropy.com/static/demos/touch_test/test_touches.html

I might have noticed that we blocked page scrolling using css:

body {
position: fixed;
}

And although page content is not scrolled, Y coordinates behave like invisible scroll still happen, and it shifts coordinates.

So we added “event.preventDefault();” is the end of touch handler functions, and it fixed the issue

A page with a fix:

http://dev.low-entropy.com/static/demos/touch_test/test_touches_fix.html

Do you have ideas how to workaround the issue?
We need to release the game in few weeks, so it would be cool to any solution.

2 Likes

We already call event.preventDefault() for “touchstart”, “touchend”, “touchmove” and from what I can tell it should do the same for “mousemove”.

Or am I reading the code wrong @sven?

1 Like

@britzl Yes, looks like we already have event.preventDefault() for touch methods… Which handler function did you change @loobnin?

1 Like

I haven’t found how to change anything inside defold generated html code, if you mean that…
But I made simple page with no defold to test (see below)
This will reproduce same issue on iphone, and it has no preventDefault in the handler.
If you uncomment preventDefault line in the handler function - issue will be gone

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
	<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->

	<title>test touch</title>
	<style>
			
		
	/* Disable user selection to avoid strange bug in Chrome on Windows:
	* Selecting a text outside the canvas, then clicking+draging would
	* drag the selected text but block mouse down/up events to the engine.
	*/
	
	body {		
		background-color: rgb(255, 200, 200);
		position: fixed;
	}

	.canvas-app-container {
		background: rgb(200,255,200);
	}
				
	</style>

	
</head>

<body>
	test toches with issue 1
	<div id="div_debug">nothing</div>
	<div id="app-container" class="canvas-app-container">
		<canvas id="canvas" class="canvas-app-canvas" tabindex="1" width="640" height="1136"></canvas>
	</div>
	
	<script type='text/javascript'>	
		
	var touchzone = document.getElementById("app-container");
	touchzone.addEventListener("mousedown", touchHandler, true);
	touchzone.addEventListener("mousemove", touchHandler, true);
	touchzone.addEventListener("touchstart", touchHandler, true);
	touchzone.addEventListener("touchmove", touchHandler, true);
	console.log("!!!TEST CONSOLE LOG!!!");
	
	function touchHandler(event) {
		if (!event.touches) {
			var xx = event.screenX;
			var yy = event.screenY;
		} else {
			var xx = (event.touches[0].screenX);
			var yy = (event.touches[0].screenY);	  
		}
		
		document.getElementById('div_debug').innerHTML = xx + ", " + yy;
	
//		event.preventDefault();	
	}
	

	</script>
</body>
</html>

Fixed in 1.2.149

1 Like