Android screen orientation issues (2.0.9)


#1

Hello! Sorry for my english, I am not native speaker.
Current code seems to contain several errors:

  1. SDL_GetDisplayOrientation( … ) returns 0 (UNKNOWN) after application start.
    I do not know why, but:

// Get our current screen orientation and pass it down.
mCurrentOrientation = SDLActivity.getCurrentOrientation();
SDLActivity.onNativeOrientationChanged(mCurrentOrientation);

in onCreate() doesn’t do anything. And later:

        if ( SDLActivity.mCurrentOrientation) { 
            SDLActivity.mCurrentOrientation = newOrientation;
            SDLActivity.onNativeOrientationChanged(newOrientation);
        }

mCurrentOrientation blocks event from C-code and it doesn’t see correct value of orientation until physical flip of device (generation of event after changed orientation).
I think it’s better to check cached value in C-code, not in Java.

  1. enum

typedef enum
{
SDL_ORIENTATION_UNKNOWN,
SDL_ORIENTATION_LANDSCAPE,
SDL_ORIENTATION_LANDSCAPE_FLIPPED,
SDL_ORIENTATION_PORTRAIT,
SDL_ORIENTATION_PORTRAIT_FLIPPED
} SDL_DisplayOrientation;

and (or?) it’s usage are misleading. These values are mapped to Android “rotation from default position” in SDLActivity.java:

    switch (display.getRotation()) {
        case Surface.ROTATION_0:
            result = SDL_ORIENTATION_PORTRAIT;
            break;

        case Surface.ROTATION_90:
            result = SDL_ORIENTATION_LANDSCAPE;
            break;

        case Surface.ROTATION_180:
            result = SDL_ORIENTATION_PORTRAIT_FLIPPED;
            break;

        case Surface.ROTATION_270:
            result = SDL_ORIENTATION_LANDSCAPE_FLIPPED;
            break;
    }

but this is wrong - default position (ROTATION_0) is vertical for smartphones and all these values become misleading. I think it’s better to change meaning of enum values to Android “rotation degrees” because this is important for accelerator orientation determination only.
Also mapping to joistick (also in SDLActivity.java):

        switch (mDisplay.getRotation()) {
            case Surface.ROTATION_90:
                x = -event.values[1];
                y = event.values[0];
                newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE;
                break;
            case Surface.ROTATION_270:
                x = event.values[1];
                y = -event.values[0];
                newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE_FLIPPED;
                break;
            case Surface.ROTATION_180:
                x = -event.values[1];
                y = -event.values[0];
                newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT_FLIPPED;
                break;
            default:
                x = event.values[0];
                y = event.values[1];
                newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT;
                break;
        }

is wrong for direction ROTATION_180 - it must be opposite of ROTATION_0 (default here) by signs only, but x and y are swapped also. This is incorrect. Must be:

            case Surface.ROTATION_180:
                x = -event.values[0];
                y = -event.values[1];

Hope this helps to improve next version of SDL2.
I very appreciate your work! Super great job! Thank you very much!


#2

Hi,
Can you put some log in the java getCurrentOrientation()
like:

Log.v(TAG, "SDL getCurrentOrientation: getRotation()=" + display.getRotation() + " result=" + result);

and also something similar in onSensorChanged()


#3

I’ve pushed your fix for ROTATION_180 thanks


#4

onSensorChanged() gets correct value of orientation, but it cannot pass it to C-code because in the start (onCreate) this correct value was cached in mCurrentOrientation and later it blocks by “if” inside onSensorChanged:

            if (  newOrientation != SDLActivity.mCurrentOrientation) { // no way
                SDLActivity.mCurrentOrientation = newOrientation;
                SDLActivity.onNativeOrientationChanged(newOrientation); // c-code is not called
            }

I think real problem is inside onCreate:

// Get our current screen orientation and pass it down.
mCurrentOrientation = SDLActivity.getCurrentOrientation();
SDLActivity.onNativeOrientationChanged(mCurrentOrientation);

And again - mCurrentOrientation gets correct value of current screen orientation.
But it looks like code inside onNativeOrientationChanged don’t apply it to C-variable at this point for some reason.
Maybe at this moment some inner structures of C-code are not initialized? I do not know.
I’l try to inspect it by myself, but I may have problems with understanding of inner structure of SDL.


#5

Well, I found it - first time screenOrientation is initialized in onCreate and it is passed to
SDLActivity.onNativeOrientationChanged:

 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeOrientationChanged)(
                                     JNIEnv *env, jclass jcls,
                                     jint orientation)
 {
     SDL_VideoDisplay *display = SDL_GetDisplay(0);
     SDL_SendDisplayEvent(display, SDL_DISPLAYEVENT_ORIENTATION, orientation);
 }

display gets nullptr and event is rejected inside SDL_SendDisplayEvent.
I suppose displays are not initialized at this point.
This is why cached values in C and Java differs after startup and after that cached value in Java blocks C-code from receiving correct value until device is physically flipped.
My temporary fix is not suitable for release product, so I hope this information will help to make it cool.


#6

Ok you aren’t using the latest SDL source code, because this has been fixed:


Get head by cloning with mercurial: https://hg.libsdl.org/SDL