Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix iOS touch mapping #3590

Merged
merged 1 commit into from Jan 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -18,7 +18,7 @@

import java.io.File;

import org.robovm.apple.coregraphics.CGSize;
import org.robovm.apple.coregraphics.CGRect;
import org.robovm.apple.foundation.Foundation;
import org.robovm.apple.foundation.NSMutableDictionary;
import org.robovm.apple.foundation.NSObject;
Expand Down Expand Up @@ -102,6 +102,8 @@ public void willTerminate (UIApplication application) {
/** The display scale factor (1.0f for normal; 2.0f to use retina coordinates/dimensions). */
float displayScaleFactor;

private CGRect lastScreenBounds = null;

Array<Runnable> runnables = new Array<Runnable>();
Array<Runnable> executedRunnables = new Array<Runnable>();
Array<LifecycleListener> lifecycleListeners = new Array<LifecycleListener>();
Expand Down Expand Up @@ -152,7 +154,7 @@ final boolean didFinishLaunching (UIApplication uiApp, UIApplicationLaunchOption

// setup libgdx
this.input = new IOSInput(this);
this.graphics = new IOSGraphics(getBounds(null), scale, this, config, input, gl20);
this.graphics = new IOSGraphics(scale, this, config, input, gl20);
this.files = new IOSFiles();
this.audio = new IOSAudio(config);
this.net = new IOSNet(this);
Expand Down Expand Up @@ -190,57 +192,55 @@ public UIWindow getUIWindow () {
return uiWindow;
}

/** Returns our real display dimension based on screen orientation.
/** GL View spans whole screen, that is, even under the status bar. iOS can also rotate the screen, which is not handled
* consistently over iOS versions. This method returns, in pixels, rectangle in which libGDX draws.
*
* @param viewController The view controller.
* @return Or real display dimension. */
CGSize getBounds (UIViewController viewController) {
// or screen size (always portrait)
CGSize bounds = UIScreen.getMainScreen().getApplicationFrame().getSize();

// determine orientation and resulting width + height
UIInterfaceOrientation orientation;
if (viewController != null) {
orientation = viewController.getInterfaceOrientation();
} else if (config.orientationLandscape == config.orientationPortrait) {
/*
* if the app has orientation in any side then we can only check status bar orientation
*/
orientation = uiApp.getStatusBarOrientation();
} else if (config.orientationLandscape) {// is landscape true and portrait false
orientation = UIInterfaceOrientation.LandscapeRight;
} else {// is portrait true and landscape false
orientation = UIInterfaceOrientation.Portrait;
}
int width;
int height;
switch (orientation) {
* @return dimensions of space we draw to, adjusted for device orientation */
protected CGRect getBounds () {
final CGRect screenBounds = UIScreen.getMainScreen().getBounds();
final CGRect statusBarFrame = uiApp.getStatusBarFrame();
final UIInterfaceOrientation statusBarOrientation = uiApp.getStatusBarOrientation();

double statusBarHeight = Math.min(statusBarFrame.getWidth(), statusBarFrame.getHeight());

double screenWidth = screenBounds.getWidth();
double screenHeight = screenBounds.getHeight();

// Make sure that the orientation is consistent with ratios. Should be, but may not be on older iOS versions
switch (statusBarOrientation) {
case LandscapeLeft:
case LandscapeRight:
height = (int)bounds.getWidth();
width = (int)bounds.getHeight();
if (width < height) {
width = (int)bounds.getWidth();
height = (int)bounds.getHeight();
if (screenHeight > screenWidth) {
debug("IOSApplication", "Switching reported width and height (w=" + screenWidth + " h=" + screenHeight + ")");
double tmp = screenHeight;
// noinspection SuspiciousNameCombination
screenHeight = screenWidth;
screenWidth = tmp;
}
break;
default:
// assume portrait
width = (int)bounds.getWidth();
height = (int)bounds.getHeight();
}

Gdx.app.debug("IOSApplication", "Unscaled View: " + orientation.toString() + " " + width + "x" + height);

// update width/height depending on display scaling selected
width *= displayScaleFactor;
height *= displayScaleFactor;
screenWidth *= displayScaleFactor;
screenHeight *= displayScaleFactor;

// log screen dimensions
Gdx.app.debug("IOSApplication", "View: " + orientation.toString() + " " + width + "x" + height);
if (statusBarHeight != 0.0) {
debug("IOSApplication", "Status bar is visible (height = " + statusBarHeight + ")");
statusBarHeight *= displayScaleFactor;
screenHeight -= statusBarHeight;
} else {
debug("IOSApplication", "Status bar is not visible");
}

debug("IOSApplication", "Total computed bounds are w=" + screenWidth + " h=" + screenHeight);

return lastScreenBounds = new CGRect(0.0, statusBarHeight, screenWidth, screenHeight);
}

// return resulting view size (based on orientation)
return new CGSize(width, height);
protected CGRect getCachedBounds () {
if (lastScreenBounds == null)
return getBounds();
else
return lastScreenBounds;
}

final void didBecomeActive (UIApplication uiApp) {
Expand Down
Expand Up @@ -16,9 +16,7 @@

package com.badlogic.gdx.backends.iosrobovm;

import org.robovm.apple.coregraphics.CGPoint;
import org.robovm.apple.coregraphics.CGRect;
import org.robovm.apple.coregraphics.CGSize;
import org.robovm.apple.foundation.NSObject;
import org.robovm.apple.glkit.GLKView;
import org.robovm.apple.glkit.GLKViewController;
Expand Down Expand Up @@ -76,21 +74,6 @@ public void viewDidAppear (boolean animated) {
if (app.viewControllerListener != null) app.viewControllerListener.viewDidAppear(animated);
}

@Override
public void didRotate (UIInterfaceOrientation orientation) {
super.didRotate(orientation);
// get the view size and update graphics
// FIXME: supporting BOTH (landscape+portrait at same time) is
// currently not working correctly (needs fix)
// FIXME screen orientation needs to be stored for
// Input#getNativeOrientation
CGSize bounds = app.getBounds(this);
graphics.width = (int)bounds.getWidth();
graphics.height = (int)bounds.getHeight();
graphics.makeCurrent();
app.listener.resize(graphics.width, graphics.height);
}

@Override
public UIInterfaceOrientationMask getSupportedInterfaceOrientations () {
long mask = 0;
Expand Down Expand Up @@ -120,6 +103,17 @@ public boolean shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation or
}
}

@Override
public void viewDidLayoutSubviews () {
super.viewDidLayoutSubviews();
// get the view size and update graphics
CGRect bounds = app.getBounds();
graphics.width = (int)bounds.getWidth();
graphics.height = (int)bounds.getHeight();
graphics.makeCurrent();
app.listener.resize(graphics.width, graphics.height);
}

@Callback
@BindSelector("shouldAutorotateToInterfaceOrientation:")
private static boolean shouldAutorotateToInterfaceOrientation (IOSUIViewController self, Selector sel,
Expand Down Expand Up @@ -164,36 +158,36 @@ public IOSUIView (CGRect frame, EAGLContext context) {
GLKView view;
IOSUIViewController viewController;

public IOSGraphics (CGSize bounds, float scale, IOSApplication app, IOSApplicationConfiguration config, IOSInput input,
GL20 gl20) {
public IOSGraphics (float scale, IOSApplication app, IOSApplicationConfiguration config, IOSInput input, GL20 gl20) {
this.config = config;

final CGRect bounds = app.getBounds();
// setup view and OpenGL
width = (int)bounds.getWidth();
height = (int)bounds.getHeight();
app.debug(tag, bounds.getWidth() + "x" + bounds.getHeight() + ", " + scale);
this.gl20 = gl20;

context = new EAGLContext(EAGLRenderingAPI.OpenGLES2);

view = new GLKView(new CGRect(new CGPoint(0, 0), bounds), context) {
view = new GLKView(new CGRect(0, 0, bounds.getWidth(), bounds.getHeight()), context) {
@Method(selector = "touchesBegan:withEvent:")
public void touchesBegan (@Pointer long touches, UIEvent event) {
IOSGraphics.this.input.touchDown(touches, event);
IOSGraphics.this.input.onTouch(touches);
}

@Method(selector = "touchesCancelled:withEvent:")
public void touchesCancelled (@Pointer long touches, UIEvent event) {
IOSGraphics.this.input.touchUp(touches, event);
IOSGraphics.this.input.onTouch(touches);
}

@Method(selector = "touchesEnded:withEvent:")
public void touchesEnded (@Pointer long touches, UIEvent event) {
IOSGraphics.this.input.touchUp(touches, event);
IOSGraphics.this.input.onTouch(touches);
}

@Method(selector = "touchesMoved:withEvent:")
public void touchesMoved (@Pointer long touches, UIEvent event) {
IOSGraphics.this.input.touchMoved(touches, event);
IOSGraphics.this.input.onTouch(touches);
}

@Override
Expand Down
Expand Up @@ -26,10 +26,7 @@
import org.robovm.apple.uikit.UIAlertViewDelegate;
import org.robovm.apple.uikit.UIAlertViewDelegateAdapter;
import org.robovm.apple.uikit.UIAlertViewStyle;
import org.robovm.apple.uikit.UIApplication;
import org.robovm.apple.uikit.UIDevice;
import org.robovm.apple.uikit.UIEvent;
import org.robovm.apple.uikit.UIInterfaceOrientation;
import org.robovm.apple.uikit.UIKeyboardType;
import org.robovm.apple.uikit.UIReturnKeyType;
import org.robovm.apple.uikit.UITextAutocapitalizationType;
Expand All @@ -53,7 +50,6 @@
import com.badlogic.gdx.backends.iosrobovm.custom.UIAccelerometer;
import com.badlogic.gdx.backends.iosrobovm.custom.UIAccelerometerDelegate;
import com.badlogic.gdx.backends.iosrobovm.custom.UIAccelerometerDelegateAdapter;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.Pool;
Expand Down Expand Up @@ -562,19 +558,29 @@ public boolean isPeripheralAvailable (Peripheral peripheral) {

@Override
public int getRotation () {
UIInterfaceOrientation orientation = app.graphics.viewController != null ? app.graphics.viewController
.getInterfaceOrientation() : UIApplication.getSharedApplication().getStatusBarOrientation();
// we measure orientation counter clockwise, just like on Android
if (orientation == UIInterfaceOrientation.Portrait) return 0;
if (orientation == UIInterfaceOrientation.LandscapeLeft) return 270;
if (orientation == UIInterfaceOrientation.PortraitUpsideDown) return 180;
if (orientation == UIInterfaceOrientation.LandscapeRight) return 90;
return 0;
switch (app.uiApp.getStatusBarOrientation()) {
case LandscapeLeft:
return 270;
case PortraitUpsideDown:
return 180;
case LandscapeRight:
return 90;
case Portrait:
default:
return 0;
}
}

@Override
public Orientation getNativeOrientation () {
return Orientation.Portrait;
switch (app.uiApp.getStatusBarOrientation()) {
case LandscapeLeft:
case LandscapeRight:
return Orientation.Landscape;
default:
return Orientation.Portrait;
}
}

@Override
Expand All @@ -590,18 +596,8 @@ public boolean isCursorCatched () {
public void setCursorPosition (int x, int y) {
}

public void touchDown (long touches, UIEvent event) {
toTouchEvents(touches, event);
Gdx.graphics.requestRendering();
}

public void touchUp (long touches, UIEvent event) {
toTouchEvents(touches, event);
Gdx.graphics.requestRendering();
}

public void touchMoved (long touches, UIEvent event) {
toTouchEvents(touches, event);
protected void onTouch (long touches) {
toTouchEvents(touches);
Gdx.graphics.requestRendering();
}

Expand Down Expand Up @@ -658,18 +654,27 @@ private static class NSArrayExtensions extends NSExtensions {
public static native @MachineSizedUInt long count (@Pointer long thiz);
}

private void toTouchEvents (long touches, UIEvent uiEvent) {
private void toTouchEvents (long touches) {
long array = NSSetExtensions.allObjects(touches);
int length = (int)NSArrayExtensions.count(array);
for (int i = 0; i < length; i++) {
long touchHandle = NSArrayExtensions.objectAtIndex$(array, i);
UITouch touch = UI_TOUCH_WRAPPER.wrap(touchHandle);
CGPoint loc = touch.getLocationInView(touch.getView());
final int locX, locY;
// Get and map the location to our drawing space
{
CGPoint loc = touch.getLocationInView(touch.getWindow());
final CGRect bounds = app.getCachedBounds();
locX = (int)(loc.getX() * app.displayScaleFactor - bounds.getMinX());
locY = (int)(loc.getY() * app.displayScaleFactor - bounds.getMinY());
// app.debug("IOSInput","pos= "+loc+" bounds= "+bounds+" x= "+locX+" locY= "+locY);
}

synchronized (touchEvents) {
UITouchPhase phase = touch.getPhase();
TouchEvent event = touchEventPool.obtain();
event.x = (int)(loc.getX() * app.displayScaleFactor);
event.y = (int)(loc.getY() * app.displayScaleFactor);
event.x = locX;
event.y = locY;
event.phase = phase;
event.timestamp = (long)(touch.getTimestamp() * 1000000000);
touchEvents.add(event);
Expand Down