openFrameworks icon indicating copy to clipboard operation
openFrameworks copied to clipboard

iOS Orientation - Physical vs Screen content orientation

Open dimitre opened this issue 3 years ago • 7 comments

There is some issues related to iOS orientation, physical vs. screen I've seen in different issues, some I've experienced and now begining to understand better.

There is the fact that if you want to keep the content in the upright position, when screen is rotated physically to the left, you want to rotate content to the right.

  • https://github.com/openframeworks/openFrameworks/issues/6053

other confusions arise from the lack of separation between physical orientation and screen orientation. so some functions are not very clear, like ofGetOrientation

  • https://github.com/openframeworks/openFrameworks/issues/5612
  • https://github.com/openframeworks/openFrameworks/issues/4508

And finally the fact the auto rotation is broken (I've opened this issue in 2018). I can fix this one with a PR

  • https://github.com/openframeworks/openFrameworks/issues/6076

I think this can be fixed with one PR in ofAppiOSWindow.mm (line 232 - 235) Maybe another in ofAppGLFWWindow if needed (returning { x, y } or { y, x } when rotated)

And maybe better documentation, example or even a function to get physical orientation.

Other related issues:

  • https://github.com/openframeworks/openFrameworks/issues/4154
  • https://github.com/openframeworks/openFrameworks/issues/3130
  • https://github.com/openframeworks/openFrameworks/issues/6723

dimitre avatar May 07 '22 03:05 dimitre

Hah, I was just about to open an issue regarding this as well. Your notes are much better than mine so this is good 😄 100% The current state of orientation handling is very confusing.

Here's some of my notes when I was debugging it (it was a few months ago and I am just getting back to it so apologies for it being vague):

  • If you set Startup Orientation to 90 right, the screen orientation will be incorrect unless you hold the device at 90 left at startup
  • If you disable hardware orientation and start the app in portrait, the screen will be upside down
  • The UI orientation in ofxiOS seem to be swapped?
  • The screen will flash when orienting

I was able to hack a semi-fix by disabling lines 241-245 in ofappioswindow::setorientation, which caused the hardware orientation on the device to work again. However, apps will still start with the OF app running in portrait mode, even if that orientation is disabled via Xcode. i.e. If you're holding the device in landscape, the app starts in portrait, renders in landscape, but the device will still be in portrait.

I also looked at:

  • #6317
  • #3865

aefreedman avatar May 10 '22 14:05 aefreedman

Great! I think those have to be switched one to another. What is your fix? https://github.com/openframeworks/openFrameworks/blob/f90003b4a5cc54531f02682d74309188cd3da6b1/addons/ofxiOS/src/app/ofAppiOSWindow.mm#L231-L236

dimitre avatar May 10 '22 14:05 dimitre

I removed this block to restore hardware orientation, to not skip the block that follows. It doesn't entirely make sense to me, however, as the comment there seems like it would be true, but the app also does not crash.

https://github.com/openframeworks/openFrameworks/blob/f90003b4a5cc54531f02682d74309188cd3da6b1/addons/ofxiOS/src/app/ofAppiOSWindow.mm#L241-L245

aefreedman avatar May 10 '22 14:05 aefreedman

Going to add @danoli3 to this!

For historical context, the reason this is different ( and seems incorrect ):

 case OF_ORIENTATION_90_RIGHT: 
     interfaceOrientation = UIInterfaceOrientationLandscapeLeft; 
     break; 
 case OF_ORIENTATION_90_LEFT: 
     interfaceOrientation = UIInterfaceOrientationLandscapeRight; 
     break; 

Is because OF_ORIENTATION_90_LEFT is referring to the rotation of the OpenGL context and this existed separately from the iOS stuff before we used it for both. ofSetOrientation referred to changing the orientation of the OF context so OF_ORIENTATION_90_LEFT means rotate the context 90 degrees to the left.

ie: If you rotated your laptop onto its right side, and wanted to have the OF top left be the screen top left you would do: ofSetOrientation(OF_ORIENTATION_90_LEFT);

All this to say that the code above is intended this way. I think separately the hardware orientation on iOS might be broken, but I don't think the highlighted code above is the cause.

ofTheo avatar May 10 '22 18:05 ofTheo

Yeah I think two different things were tried to merge as one, but they are different in nature. And since you can get and set Rotation it will be very confusing when it start to mix physical and screen rotation automatically. Because when tilted right and left the physical and context should be crossed one with another.

dimitre avatar May 10 '22 20:05 dimitre

about iosOrientationExample: there is a curiosity there. the deviceOrientationChanged returns an integer which is an UIDeviceOrientation result. but it is interpreted as ofOrientation enum, does the two follow the same order? I think approximately. Even this way the screen has to be rotated the opposite as physical direction, this is why it is upside down when tilted left or right. ofWindowSettings.h

enum ofOrientation: short{
	/// \brief Represents the default screen orientation.
	OF_ORIENTATION_DEFAULT = 1,
	/// \brief Represents a screen rotated 180 degrees, also known as upside-down.
	OF_ORIENTATION_180 = 2,
	/// \brief Represents a screen rotated 90 degrees clockwise.
	OF_ORIENTATION_90_LEFT = 3,
	/// \brief Represents a screen rotated 90 degrees counter-clockwise.
	OF_ORIENTATION_90_RIGHT = 4,
	/// \brief Represents an unknown orientation.
	OF_ORIENTATION_UNKNOWN = 5
};
enum UIDeviceOrientation : Int {
 case Unknown
 case Portrait
 case PortraitUpsideDown
 case LandscapeLeft
 case LandscapeRight
 case FaceUp
 case FaceDown
}

dimitre avatar May 10 '22 20:05 dimitre

I think physical screen rotation and content (opengl context) rotation should be independent one to another.

You as a user can set orientation to any screen, lets say you want to make an installation with the screen tilted or upside down. You use ofSetOrientation

You want to know which orientation you set previously you use ofGetOrientation All good until now.

Now imagine we had another function to get the physical rotation, something like ofGetPhysicalOrientation, or ofGetDeviceOrientation or ofGetHardwareOrientation.

we can parse the two states individually because if we program something to orientate upside automatically it will have to cross, like When physical orientation is OF_ORIENTATION_90_LEFT the content orientation is OF_ORIENTATION_90_RIGHT and vice versa

If we don't separate we don't know what we are talking about and there will always be one case when the setters or getters are inverted.

ping: @ofTheo @danoli3

dimitre avatar May 10 '22 22:05 dimitre

@dimitre I'm wondering about the use case of having 2 orientations -- I would prefer to have none! I mean: setting up an iPad in an odd position requiring a different orientation than what gravity gives (say for example VLC playing a movie in an ambiguous table-top horizontal position) I don't expect VLC to do anything but to respond to the OS, so I will lock the rotation in the desired position within iOS, and expect VLC to display the movie in the locked orientation as the rest of the system.

I expect the same from an OF app: within the allowed orientations (defined in the app's Xcode project General tab) I expect the iOS to rotate the app, and the app will be as adaptive as it's programmed to consider a screen that shrinks/grows (if allowed to rotate both in landscape and portrait).

It may have some value to query the system to know if the iPad physical orientation matches the actual render (i.e. deduce if the user locked orientation) but in no cases should the touch coordinates be different from the draw coordinates.

(so in essence I'm not sure about setOrientation() -- it breaks the relationship with the OS.)

artificiel avatar Feb 09 '23 04:02 artificiel