Added the concept of display natural orientation

Also renamed SDL_GetDisplayOrientation() SDL_GetDisplayCurrentOrientation()

The natural orientation of the primary display is the frame of reference for accelerometer and gyro sensor readings.
This commit is contained in:
Sam Lantinga
2023-06-17 00:52:40 -07:00
parent 8de6ce7e92
commit e6d1ba2a17
20 changed files with 213 additions and 79 deletions

View File

@@ -155,10 +155,14 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
JNIEnv *env, jclass cls,
jstring name, jstring value);
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeOrientationChanged)(
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetNaturalOrientation)(
JNIEnv *env, jclass cls,
jint orientation);
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeRotationChanged)(
JNIEnv *env, jclass cls,
jint rotation);
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeAddTouch)(
JNIEnv *env, jclass cls,
jint touchId, jstring name);
@@ -202,7 +206,8 @@ static JNINativeMethod SDLActivity_tab[] = {
{ "nativeGetHint", "(Ljava/lang/String;)Ljava/lang/String;", SDL_JAVA_INTERFACE(nativeGetHint) },
{ "nativeGetHintBoolean", "(Ljava/lang/String;Z)Z", SDL_JAVA_INTERFACE(nativeGetHintBoolean) },
{ "nativeSetenv", "(Ljava/lang/String;Ljava/lang/String;)V", SDL_JAVA_INTERFACE(nativeSetenv) },
{ "onNativeOrientationChanged", "(I)V", SDL_JAVA_INTERFACE(onNativeOrientationChanged) },
{ "nativeSetNaturalOrientation", "(I)V", SDL_JAVA_INTERFACE(nativeSetNaturalOrientation) },
{ "onNativeRotationChanged", "(I)V", SDL_JAVA_INTERFACE(onNativeRotationChanged) },
{ "nativeAddTouch", "(ILjava/lang/String;)V", SDL_JAVA_INTERFACE(nativeAddTouch) },
{ "nativePermissionResult", "(IZ)V", SDL_JAVA_INTERFACE(nativePermissionResult) },
{ "nativeAllowRecreateActivity", "()Z", SDL_JAVA_INTERFACE(nativeAllowRecreateActivity) },
@@ -369,7 +374,8 @@ static jmethodID midHapticRun;
static jmethodID midHapticStop;
/* Accelerometer data storage */
static SDL_DisplayOrientation displayOrientation;
static SDL_DisplayOrientation displayNaturalOrientation;
static SDL_DisplayOrientation displayCurrentOrientation;
static float fLastAccelerometer[3];
static SDL_bool bHasNewData;
@@ -934,17 +940,44 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
SDL_UnlockMutex(Android_ActivityMutex);
}
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeOrientationChanged)(
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetNaturalOrientation)(
JNIEnv *env, jclass jcls,
jint orientation)
{
displayNaturalOrientation = (SDL_DisplayOrientation)orientation;
}
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeRotationChanged)(
JNIEnv *env, jclass jcls,
jint rotation)
{
SDL_LockMutex(Android_ActivityMutex);
displayOrientation = (SDL_DisplayOrientation)orientation;
if (displayNaturalOrientation == SDL_ORIENTATION_LANDSCAPE) {
rotation += 90;
}
switch (rotation % 360) {
case 0:
displayCurrentOrientation = SDL_ORIENTATION_PORTRAIT;
break;
case 90:
displayCurrentOrientation = SDL_ORIENTATION_LANDSCAPE;
break;
case 180:
displayCurrentOrientation = SDL_ORIENTATION_PORTRAIT_FLIPPED;
break;
case 270:
displayCurrentOrientation = SDL_ORIENTATION_LANDSCAPE_FLIPPED;
break;
default:
displayCurrentOrientation = SDL_ORIENTATION_UNKNOWN;
break;
}
if (Android_Window) {
SDL_VideoDisplay *display = SDL_GetVideoDisplay(SDL_GetPrimaryDisplay());
SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, orientation);
SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, displayCurrentOrientation);
}
SDL_UnlockMutex(Android_ActivityMutex);
@@ -1706,9 +1739,14 @@ int Android_JNI_OpenAudioDevice(int iscapture, int device_id, SDL_AudioSpec *spe
return 0;
}
SDL_DisplayOrientation Android_JNI_GetDisplayOrientation(void)
SDL_DisplayOrientation Android_JNI_GetDisplayNaturalOrientation(void)
{
return displayOrientation;
return displayNaturalOrientation;
}
SDL_DisplayOrientation Android_JNI_GetDisplayCurrentOrientation(void)
{
return displayCurrentOrientation;
}
void *Android_JNI_GetAudioBuffer(void)

View File

@@ -43,7 +43,8 @@ extern void Android_JNI_HideTextInput(void);
extern SDL_bool Android_JNI_IsScreenKeyboardShown(void);
extern ANativeWindow *Android_JNI_GetNativeWindow(void);
extern SDL_DisplayOrientation Android_JNI_GetDisplayOrientation(void);
extern SDL_DisplayOrientation Android_JNI_GetDisplayNaturalOrientation(void);
extern SDL_DisplayOrientation Android_JNI_GetDisplayCurrentOrientation(void);
/* Audio support */
extern void Android_DetectDevices(void);

View File

@@ -166,7 +166,7 @@ SDL3_0.0.0 {
SDL_GetDisplayForPoint;
SDL_GetDisplayForRect;
SDL_GetDisplayName;
SDL_GetDisplayOrientation;
SDL_GetDisplayCurrentOrientation;
SDL_GetDisplayUsableBounds;
SDL_GetError;
SDL_GetErrorMsg;
@@ -866,6 +866,7 @@ SDL3_0.0.0 {
SDL_hid_get_report_descriptor;
SDL_HasWindowSurface;
SDL_DestroyWindowSurface;
SDL_GetDisplayNaturalOrientation;
# extra symbols go here (don't modify this line)
local: *;
};

View File

@@ -190,7 +190,7 @@
#define SDL_GetDisplayForPoint SDL_GetDisplayForPoint_REAL
#define SDL_GetDisplayForRect SDL_GetDisplayForRect_REAL
#define SDL_GetDisplayName SDL_GetDisplayName_REAL
#define SDL_GetDisplayOrientation SDL_GetDisplayOrientation_REAL
#define SDL_GetDisplayCurrentOrientation SDL_GetDisplayCurrentOrientation_REAL
#define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL
#define SDL_GetError SDL_GetError_REAL
#define SDL_GetErrorMsg SDL_GetErrorMsg_REAL
@@ -892,3 +892,4 @@
#define SDL_hid_get_report_descriptor SDL_hid_get_report_descriptor_REAL
#define SDL_HasWindowSurface SDL_HasWindowSurface_REAL
#define SDL_DestroyWindowSurface SDL_DestroyWindowSurface_REAL
#define SDL_GetDisplayNaturalOrientation SDL_GetDisplayNaturalOrientation_REAL

View File

@@ -265,7 +265,7 @@ SDL_DYNAPI_PROC(int,SDL_GetDisplayBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),re
SDL_DYNAPI_PROC(SDL_DisplayID,SDL_GetDisplayForPoint,(const SDL_Point *a),(a),return)
SDL_DYNAPI_PROC(SDL_DisplayID,SDL_GetDisplayForRect,(const SDL_Rect *a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_GetDisplayName,(SDL_DisplayID a),(a),return)
SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetDisplayOrientation,(SDL_DisplayID a),(a),return)
SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetDisplayCurrentOrientation,(SDL_DisplayID a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return)
SDL_DYNAPI_PROC(const char*,SDL_GetError,(void),(),return)
SDL_DYNAPI_PROC(char*,SDL_GetErrorMsg,(char *a, int b),(a,b),return)
@@ -937,3 +937,4 @@ SDL_DYNAPI_PROC(SDL_hid_device_info*,SDL_hid_get_device_info,(SDL_hid_device *a)
SDL_DYNAPI_PROC(int,SDL_hid_get_report_descriptor,(SDL_hid_device *a, unsigned char *b, size_t c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_HasWindowSurface,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_DestroyWindowSurface,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetDisplayNaturalOrientation,(SDL_DisplayID a),(a),return)

View File

@@ -33,10 +33,10 @@ int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent,
}
switch (displayevent) {
case SDL_EVENT_DISPLAY_ORIENTATION:
if (data1 == SDL_ORIENTATION_UNKNOWN || data1 == display->orientation) {
if (data1 == SDL_ORIENTATION_UNKNOWN || data1 == display->current_orientation) {
return 0;
}
display->orientation = (SDL_DisplayOrientation)data1;
display->current_orientation = (SDL_DisplayOrientation)data1;
break;
default:
break;

View File

@@ -2464,8 +2464,13 @@ void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, fl
textY += lineHeight;
}
(void)SDL_snprintf(text, sizeof(text), "SDL_GetDisplayOrientation: ");
SDLTest_PrintDisplayOrientation(text, sizeof(text), SDL_GetDisplayOrientation(windowDisplayID));
(void)SDL_snprintf(text, sizeof(text), "SDL_GetDisplayNaturalOrientation: ");
SDLTest_PrintDisplayOrientation(text, sizeof(text), SDL_GetDisplayNaturalOrientation(windowDisplayID));
SDLTest_DrawString(renderer, 0.0f, textY, text);
textY += lineHeight;
(void)SDL_snprintf(text, sizeof(text), "SDL_GetDisplayCurrentOrientation: ");
SDLTest_PrintDisplayOrientation(text, sizeof(text), SDL_GetDisplayCurrentOrientation(windowDisplayID));
SDLTest_DrawString(renderer, 0.0f, textY, text);
textY += lineHeight;

View File

@@ -145,7 +145,8 @@ struct SDL_VideoDisplay
SDL_DisplayMode *fullscreen_modes;
SDL_DisplayMode desktop_mode;
const SDL_DisplayMode *current_mode;
SDL_DisplayOrientation orientation;
SDL_DisplayOrientation natural_orientation;
SDL_DisplayOrientation current_orientation;
float content_scale;
SDL_Window *fullscreen_window;

View File

@@ -889,13 +889,32 @@ int SDL_GetDisplayUsableBounds(SDL_DisplayID displayID, SDL_Rect *rect)
return SDL_GetDisplayBounds(displayID, rect);
}
SDL_DisplayOrientation SDL_GetDisplayOrientation(SDL_DisplayID displayID)
SDL_DisplayOrientation SDL_GetDisplayNaturalOrientation(SDL_DisplayID displayID)
{
SDL_VideoDisplay *display = SDL_GetVideoDisplay(displayID);
CHECK_DISPLAY_MAGIC(display, SDL_ORIENTATION_UNKNOWN);
return display->orientation;
if (display->natural_orientation != SDL_ORIENTATION_UNKNOWN) {
return display->natural_orientation;
} else {
/* Default to landscape if the driver hasn't set it */
return SDL_ORIENTATION_LANDSCAPE;
}
}
SDL_DisplayOrientation SDL_GetDisplayCurrentOrientation(SDL_DisplayID displayID)
{
SDL_VideoDisplay *display = SDL_GetVideoDisplay(displayID);
CHECK_DISPLAY_MAGIC(display, SDL_ORIENTATION_UNKNOWN);
if (display->current_orientation != SDL_ORIENTATION_UNKNOWN) {
return display->current_orientation;
} else {
/* Default to landscape if the driver hasn't set it */
return SDL_ORIENTATION_LANDSCAPE;
}
}
void SDL_SetDisplayContentScale(SDL_VideoDisplay *display, float scale)

View File

@@ -189,7 +189,8 @@ int Android_VideoInit(SDL_VideoDevice *_this)
return -1;
}
display = SDL_GetVideoDisplay(displayID);
display->orientation = Android_JNI_GetDisplayOrientation();
display->natural_orientation = Android_JNI_GetDisplayNaturalOrientation();
display->current_orientation = Android_JNI_GetDisplayCurrentOrientation();
display->content_scale = Android_ScreenDensity;
Android_InitTouch();

View File

@@ -220,6 +220,17 @@ int UIKit_AddDisplay(UIScreen *uiscreen, SDL_bool send_event)
}
SDL_zero(display);
#if !TARGET_OS_TV
if (uiscreen == [UIScreen mainScreen]) {
/* The natural orientation (used by sensors) is portrait */
display.natural_orientation = SDL_ORIENTATION_PORTRAIT;
} else
#endif
if (UIKit_IsDisplayLandscape(uiscreen)) {
display.natural_orientation = SDL_ORIENTATION_LANDSCAPE;
} else {
display.natural_orientation = SDL_ORIENTATION_PORTRAIT;
}
display.desktop_mode = mode;
/* Allocate the display data */

View File

@@ -594,7 +594,12 @@ static void display_handle_done(void *data,
if (driverdata->display == 0) {
/* First time getting display info, create the VideoDisplay */
SDL_bool send_event = driverdata->videodata->initializing ? SDL_FALSE : SDL_TRUE;
driverdata->placeholder.orientation = driverdata->orientation;
if (driverdata->physical_width >= driverdata->physical_height) {
driverdata->placeholder.natural_orientation = SDL_ORIENTATION_LANDSCAPE;
} else {
driverdata->placeholder.natural_orientation = SDL_ORIENTATION_PORTRAIT;
}
driverdata->placeholder.current_orientation = driverdata->orientation;
driverdata->placeholder.driverdata = driverdata;
driverdata->display = SDL_AddVideoDisplay(&driverdata->placeholder, send_event);
SDL_free(driverdata->placeholder.name);

View File

@@ -102,7 +102,7 @@ static void WIN_UpdateDisplayMode(SDL_VideoDevice *_this, LPCWSTR deviceName, DW
}
}
static SDL_DisplayOrientation WIN_GetDisplayOrientation(DEVMODE *mode)
static SDL_DisplayOrientation WIN_GetNaturalOrientation(DEVMODE *mode)
{
int width = mode->dmPelsWidth;
int height = mode->dmPelsHeight;
@@ -115,6 +115,15 @@ static SDL_DisplayOrientation WIN_GetDisplayOrientation(DEVMODE *mode)
}
if (width >= height) {
return SDL_ORIENTATION_LANDSCAPE;
} else {
return SDL_ORIENTATION_PORTRAIT;
}
}
static SDL_DisplayOrientation WIN_GetDisplayOrientation(DEVMODE *mode)
{
if (WIN_GetNaturalOrientation(mode) == SDL_ORIENTATION_LANDSCAPE) {
switch (mode->dmDisplayOrientation) {
case DMDO_DEFAULT:
return SDL_ORIENTATION_LANDSCAPE;
@@ -182,7 +191,7 @@ static float WIN_GetContentScale(SDL_VideoDevice *_this, HMONITOR hMonitor)
return dpi / 96.0f;
}
static SDL_bool WIN_GetDisplayMode(SDL_VideoDevice *_this, HMONITOR hMonitor, LPCWSTR deviceName, DWORD index, SDL_DisplayMode *mode, SDL_DisplayOrientation *orientation)
static SDL_bool WIN_GetDisplayMode(SDL_VideoDevice *_this, HMONITOR hMonitor, LPCWSTR deviceName, DWORD index, SDL_DisplayMode *mode, SDL_DisplayOrientation *natural_orientation, SDL_DisplayOrientation *current_orientation)
{
SDL_DisplayModeData *data;
DEVMODE devmode;
@@ -210,8 +219,11 @@ static SDL_bool WIN_GetDisplayMode(SDL_VideoDevice *_this, HMONITOR hMonitor, LP
/* Fill in the mode information */
WIN_UpdateDisplayMode(_this, deviceName, index, mode);
if (orientation) {
*orientation = WIN_GetDisplayOrientation(&devmode);
if (natural_orientation) {
*natural_orientation = WIN_GetNaturalOrientation(&devmode);
}
if (current_orientation) {
*current_orientation = WIN_GetDisplayOrientation(&devmode);
}
return SDL_TRUE;
@@ -324,14 +336,15 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI
SDL_VideoDisplay display;
SDL_DisplayData *displaydata;
SDL_DisplayMode mode;
SDL_DisplayOrientation orientation;
SDL_DisplayOrientation natural_orientation;
SDL_DisplayOrientation current_orientation;
float content_scale = WIN_GetContentScale(_this, hMonitor);
#ifdef DEBUG_MODES
SDL_Log("Display: %s\n", WIN_StringToUTF8W(info->szDevice));
#endif
if (!WIN_GetDisplayMode(_this, hMonitor, info->szDevice, ENUM_CURRENT_SETTINGS, &mode, &orientation)) {
if (!WIN_GetDisplayMode(_this, hMonitor, info->szDevice, ENUM_CURRENT_SETTINGS, &mode, &natural_orientation, &current_orientation)) {
return;
}
@@ -371,7 +384,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI
if (moved || changed_bounds) {
SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_MOVED, 0);
}
SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_ORIENTATION, orientation);
SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_ORIENTATION, current_orientation);
SDL_SetDisplayContentScale(existing_display, content_scale);
}
goto done;
@@ -398,7 +411,8 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI
}
display.desktop_mode = mode;
display.orientation = orientation;
display.natural_orientation = natural_orientation;
display.current_orientation = current_orientation;
display.content_scale = content_scale;
display.device = _this;
display.driverdata = displaydata;
@@ -514,7 +528,7 @@ int WIN_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
SDL_DisplayMode mode;
for (i = 0;; ++i) {
if (!WIN_GetDisplayMode(_this, data->MonitorHandle, data->DeviceName, i, &mode, NULL)) {
if (!WIN_GetDisplayMode(_this, data->MonitorHandle, data->DeviceName, i, &mode, NULL, NULL)) {
break;
}
if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {