BUG : Touches screwed on iOS 6 landscape


#1

Latest tip, Juce Demo, iOS 6 debug or release build.

In landscape, touches with an x value greater than about 309(?) don’t work properly on iOS 6. On an iOS 5 device, everything’s fine. This is easily observable in the Juce demo:

  • Run Juce demo on iOS 6 in landscape
  • Select the Widgets demo
  • Hold the rels slider and drag all the way to the right
  • Everything’s OK up until x=309, and then it starts sending continuous mouse up/down messages in the wrong positions rather than a drag as it should

My suspicion is the new iOS 6 orientation API (which Apple like to change every half an hour) but the 309 (rather than 320) has me puzzled - could be status bar related, but I think that would most like account for a 20 pixel difference.

I’d be very grateful for a fix, I’ve already spent a fair amount of time wading in this far. I’ve uncommented some logging functions in juce_MouseInputSource.cpp to give you a better idea of what’s going on.

Case #1:

A single tap with x<309:

Mouse 0 move: 5, 5 - Comp: 1dd2ff70
Mouse 0 down: 5, 5 - Comp: 1dd2ff70
Mouse 0 up: 3, 5 - Comp: 1dd2ff70
Mouse 0 move: 3, 5 - Comp: 1dd2ff70 <-- All seems OK

A single tap with x>309:

Mouse 0 move: 461, 1 - Comp: 1dd68e40
Mouse 0 down: 461, 1 - Comp: 1dd68e40
Mouse 0 up: 320, -2 - Comp: 1dd68e40
Mouse 0 move: 320, 24 - Comp: 1f06691c <-- The move and down seem correct, but the up and move have been clamped to 320

Case #2:

Dragging a touch from the left to the right:

Mouse 0 move: 42, 14 - Comp: 1dd117c0 <-- Starts dragging from left to right as expected
Mouse 0 down: 42, 14 - Comp: 1dd117c0
Mouse 0 drag: 42, 15 - Comp: 1dd117c0
Mouse 0 drag: 43, 15 - Comp: 1dd117c0
Mouse 0 drag: 44, 15 - Comp: 1dd117c0

Mouse 0 drag: 306, -24 - Comp: 1dd117c0 <-- Almost at x=309
Mouse 0 drag: 306, -25 - Comp: 1dd117c0
Mouse 0 drag: 307, -25 - Comp: 1dd117c0
Mouse 0 drag: 308, -25 - Comp: 1dd117c0
Mouse 0 drag: 309, -25 - Comp: 1dd117c0
Mouse 0 drag: 309, -26 - Comp: 1dd117c0
Mouse 0 drag: 309, -27 - Comp: 1dd117c0
Mouse 0 drag: 309, -28 - Comp: 1dd117c0
Mouse 0 drag: 309, -29 - Comp: 1dd117c0
Mouse 0 drag: 309, -30 - Comp: 1dd117c0
Mouse 0 drag: 309, -31 - Comp: 1dd117c0
Mouse 0 drag: 309, -32 - Comp: 1dd117c0 <-- Further drags stay at 309
Mouse 0 up: 309, -32 - Comp: 1dd117c0
Mouse 0 move: 340, 38 - Comp: 1e432a00 <-- until we reach here and it starts sending move/up/down messages with the wrong coordinates
Mouse 0 down: 340, 38 - Comp: 1e432a00
Mouse 0 up: 320, 38 - Comp: 1e432a00
Mouse 0 move: 320, 38 - Comp: 1e432a00
Mouse 0 move: 341, 38 - Comp: 1e432a00
Mouse 0 down: 341, 38 - Comp: 1e432a00
Mouse 0 up: 320, 37 - Comp: 1e432a00
Mouse 0 move: 320, 37 - Comp: 1e432a00
Mouse 0 move: 342, 37 - Comp: 1e432a00
Mouse 0 down: 342, 37 - Comp: 1e432a00
Mouse 0 up: 320, 37 - Comp: 1e432a00
Mouse 0 move: 320, 37 - Comp: 1e432a00
Mouse 0 move: 342, 37 - Comp: 1e432a00
Mouse 0 down: 342, 37 - Comp: 1e432a00


#2

Bit of a mystery, because there’s no code anywhere that would restrict the coords that get returned. You’re probably looking in the wrong place though - if you want to get to the root of the problem, UIViewComponentPeer::handleTouches is where the events actually arrive. In there you can see the coords arriving directly from the OS.


#3

I’ve gone deeper and it seems to be coming from the OS. Inserting this code in UIViewComponentPeer::handleTouches:

    DBG ("UIViewComponentPeer::handleTouches(pos = {" + String ((int)p.x) + ", " + String ((int)p.y) + "}, isDown = " + String(isDown) + ", isUp = " + String(isUp) + ", isCancel = " + String(isCancel) + ");");

… results in:

Tap with x < 320:

UIViewComponentPeer::handleTouches(pos = {78, 115}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {76, 109}, isDown = 0, isUp = 1, isCancel = 0);

Tap with x > 320:

IViewComponentPeer::handleTouches(pos = {419, 137}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 128}, isDown = 0, isUp = 1, isCancel = 0); <-- What could be causing x to be 320 in landscape?

Horizontal drag from x = 48 to x = 463:

UIViewComponentPeer::handleTouches(pos = {48, 142}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {61, 137}, isDown = 0, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {64, 137}, isDown = 0, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {67, 137}, isDown = 0, isUp = 0, isCancel = 0);

UIViewComponentPeer::handleTouches(pos = {258, 128}, isDown = 0, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {271, 128}, isDown = 0, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {288, 128}, isDown = 0, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {302, 129}, isDown = 0, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {318, 130}, isDown = 0, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 132}, isDown = 0, isUp = 0, isCancel = 0); <-- Note how isUp/IsDown start toggling when x > 320
UIViewComponentPeer::handleTouches(pos = {320, 133}, isDown = 0, isUp = 1, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {365, 135}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 137}, isDown = 0, isUp = 1, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {390, 138}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 139}, isDown = 0, isUp = 1, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {410, 139}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 140}, isDown = 0, isUp = 1, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {430, 141}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 142}, isDown = 0, isUp = 1, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {444, 142}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 144}, isDown = 0, isUp = 1, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {454, 146}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 147}, isDown = 0, isUp = 1, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {459, 148}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 149}, isDown = 0, isUp = 1, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {463, 150}, isDown = 1, isUp = 0, isCancel = 0);
UIViewComponentPeer::handleTouches(pos = {320, 150}, isDown = 0, isUp = 1, isCancel = 0);

Therefore I’d suspect it’s some dodgy rotation/transfom on the UIView, or iOS not thinking we’re in the rotation we think we are, or something along those lines. The fact it works fine on iOS 5 made start thinking it could be due to API differences between that and iOS 6. I tried implementing UIViewController::should Autorotate() to return true but it appeared to make no difference.


#4

Very odd… It does indeed look like iOS is just getting it wrong, but it seems unlikely in such a commonly-used function… Can’t think of any suggestions right now, but will ponder on it.