BUG : Touches screwed on iOS 6 landscape

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

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.

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.

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.