add setting for screen orientation, with initial android implementation

This commit is contained in:
Brad Parker 2019-02-21 00:31:55 -05:00
parent bc387a5848
commit f5f492845f
21 changed files with 285 additions and 4 deletions

View File

@ -1715,6 +1715,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
SETTING_UINT("video_max_swapchain_images", &settings->uints.video_max_swapchain_images, true, max_swapchain_images, false);
SETTING_UINT("video_swap_interval", &settings->uints.video_swap_interval, true, swap_interval, false);
SETTING_UINT("video_rotation", &settings->uints.video_rotation, true, ORIENTATION_NORMAL, false);
SETTING_UINT("screen_orientation", &settings->uints.screen_orientation, true, ORIENTATION_NORMAL, false);
SETTING_UINT("aspect_ratio_index", &settings->uints.video_aspect_ratio_idx, true, aspect_ratio_idx, false);
#ifdef HAVE_NETWORKING
SETTING_UINT("netplay_ip_port", &settings->uints.netplay_port, true, RARCH_DEFAULT_PORT, false);

View File

@ -404,6 +404,7 @@ typedef struct settings
unsigned video_viwidth;
unsigned video_aspect_ratio_idx;
unsigned video_rotation;
unsigned screen_orientation;
unsigned video_msg_bgcolor_red;
unsigned video_msg_bgcolor_green;
unsigned video_msg_bgcolor_blue;

View File

@ -2032,6 +2032,8 @@ static void frontend_unix_init(void *data)
"getBatteryLevel", "()I");
GET_METHOD_ID(env, android_app->setSustainedPerformanceMode, class,
"setSustainedPerformanceMode", "(Z)V");
GET_METHOD_ID(env, android_app->setScreenOrientation, class,
"setScreenOrientation", "(I)V");
CALL_OBJ_METHOD(env, obj, android_app->activity->clazz,
android_app->getIntent);

View File

@ -162,6 +162,7 @@ struct android_app
jmethodID getPowerstate;
jmethodID getBatteryLevel;
jmethodID setSustainedPerformanceMode;
jmethodID setScreenOrientation;
};
enum

View File

@ -0,0 +1,70 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include "../video_display_server.h"
#include "../../frontend/drivers/platform_unix.h"
static void* android_display_server_init(void)
{
return NULL;
}
static void android_display_server_destroy(void *data)
{
(void)data;
}
static bool android_display_server_set_window_opacity(void *data, unsigned opacity)
{
(void)data;
(void)opacity;
return true;
}
static bool android_display_server_set_window_progress(void *data, int progress, bool finished)
{
(void)data;
(void)progress;
(void)finished;
return true;
}
static void android_display_server_set_screen_orientation(enum rotation rotation)
{
JNIEnv *env = jni_thread_getenv();
if (!env || !g_android)
return;
if (g_android->setScreenOrientation)
CALL_VOID_METHOD_PARAM(env, g_android->activity->clazz,
g_android->setScreenOrientation, rotation);
}
const video_display_server_t dispserv_android = {
android_display_server_init,
android_display_server_destroy,
android_display_server_set_window_opacity,
android_display_server_set_window_progress,
NULL, /* set_window_decorations */
NULL, /* set_resolution */
NULL, /* get_resolution_list */
NULL, /* get_output_options */
android_display_server_set_screen_orientation,
"android"
};

View File

@ -52,5 +52,6 @@ const video_display_server_t dispserv_null = {
NULL, /* set_resolution */
NULL, /* get_resolution_list */
NULL, /* get_output_options */
NULL, /* set_screen_orientation */
"null"
};

View File

@ -355,5 +355,6 @@ const video_display_server_t dispserv_win32 = {
win32_display_server_set_resolution,
win32_display_server_get_resolution_list,
NULL, /* get_output_options */
NULL, /* set_screen_orientation */
"win32"
};

View File

@ -358,6 +358,11 @@ const char *x11_display_server_get_output_options(void *data)
#endif
}
static void x11_display_server_set_screen_orientation(enum rotation rotation)
{
(void)rotation;
}
const video_display_server_t dispserv_x11 = {
x11_display_server_init,
x11_display_server_destroy,
@ -367,5 +372,6 @@ const video_display_server_t dispserv_x11 = {
x11_display_server_set_resolution,
NULL, /* get_resolution_list */
x11_display_server_get_output_options,
x11_display_server_set_screen_orientation,
"x11"
};

View File

@ -49,7 +49,11 @@ void* video_display_server_init(void)
#endif
break;
default:
#if defined(ANDROID)
current_display_server = &dispserv_android;
#else
current_display_server = &dispserv_null;
#endif
break;
}
@ -110,3 +114,19 @@ const char *video_display_server_get_output_options(void)
return current_display_server->get_output_options(current_display_server_data);
return NULL;
}
void video_display_server_set_screen_orientation(enum rotation rotation)
{
if (current_display_server && current_display_server->set_screen_orientation)
{
RARCH_LOG("[Video]: Setting screen orientation to %d.\n", rotation);
current_display_server->set_screen_orientation(rotation);
}
}
bool video_display_server_can_set_screen_orientation(void)
{
if (current_display_server && current_display_server->set_screen_orientation)
return true;
return false;
}

View File

@ -21,6 +21,8 @@
#include <retro_common_api.h>
#include <boolean.h>
#include "video_defines.h"
RETRO_BEGIN_DECLS
typedef struct video_display_config
@ -45,6 +47,7 @@ typedef struct video_display_server
void *(*get_resolution_list)(void *data,
unsigned *size);
const char *(*get_output_options)(void *data);
void (*set_screen_orientation)(enum rotation rotation);
const char *ident;
} video_display_server_t;
@ -68,8 +71,13 @@ const char *video_display_server_get_output_options(void);
const char *video_display_server_get_ident(void);
void video_display_server_set_screen_orientation(enum rotation rotation);
bool video_display_server_can_set_screen_orientation(void);
extern const video_display_server_t dispserv_win32;
extern const video_display_server_t dispserv_x11;
extern const video_display_server_t dispserv_android;
extern const video_display_server_t dispserv_null;
RETRO_END_DECLS

View File

@ -1114,6 +1114,9 @@ static bool video_driver_init_internal(bool *video_is_threaded)
video_display_server_init();
if ((enum rotation)settings->uints.screen_orientation != ORIENTATION_NORMAL)
video_display_server_set_screen_orientation((enum rotation)settings->uints.screen_orientation);
command_event(CMD_EVENT_SHADER_DIR_INIT, NULL);
return true;

View File

@ -222,6 +222,7 @@ VIDEO CONTEXT
#include "../gfx/drivers_context/ps3_ctx.c"
#elif defined(ANDROID)
#include "../gfx/drivers_context/android_ctx.c"
#include "../gfx/display_servers/dispserv_android.c"
#elif defined(__QNX__)
#include "../gfx/drivers_context/qnx_ctx.c"
#elif defined(EMSCRIPTEN)

View File

@ -1253,6 +1253,8 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_POLLED,
"video_refresh_rate_polled")
MSG_HASH(MENU_ENUM_LABEL_VIDEO_ROTATION,
"video_rotation")
MSG_HASH(MENU_ENUM_LABEL_SCREEN_ORIENTATION,
"screen_orientation")
MSG_HASH(MENU_ENUM_LABEL_VIDEO_SCALE,
"video_scale")
MSG_HASH(MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER,

View File

@ -3492,7 +3492,11 @@ MSG_HASH(
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION,
"Rotation"
"Video Rotation"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_SCREEN_ORIENTATION,
"Screen Orientation"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_SCALE,
@ -5289,7 +5293,11 @@ MSG_HASH(
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_ROTATION,
"Forces a certain rotation of the screen. The rotation is added to rotations which the core sets."
"Forces a certain rotation of the video. The rotation is added to rotations which the core sets."
)
MSG_HASH(
MENU_ENUM_SUBLABEL_SCREEN_ORIENTATION,
"Forces a certain orientation of the screen from the operating system."
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_FORCE_SRGB_DISABLE,

View File

@ -212,6 +212,7 @@ default_sublabel_macro(action_bind_sublabel_content_collection_list, MENU_
default_sublabel_macro(action_bind_sublabel_video_scale_integer, MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER)
default_sublabel_macro(action_bind_sublabel_video_gpu_screenshot, MENU_ENUM_SUBLABEL_VIDEO_GPU_SCREENSHOT)
default_sublabel_macro(action_bind_sublabel_video_rotation, MENU_ENUM_SUBLABEL_VIDEO_ROTATION)
default_sublabel_macro(action_bind_sublabel_screen_orientation, MENU_ENUM_SUBLABEL_SCREEN_ORIENTATION)
default_sublabel_macro(action_bind_sublabel_video_force_srgb_enable, MENU_ENUM_SUBLABEL_VIDEO_FORCE_SRGB_DISABLE)
default_sublabel_macro(action_bind_sublabel_video_fullscreen, MENU_ENUM_SUBLABEL_VIDEO_FULLSCREEN)
default_sublabel_macro(action_bind_sublabel_video_windowed_fullscreen, MENU_ENUM_SUBLABEL_VIDEO_WINDOWED_FULLSCREEN)
@ -1754,6 +1755,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_VIDEO_ROTATION:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_rotation);
break;
case MENU_ENUM_LABEL_SCREEN_ORIENTATION:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_screen_orientation);
break;
case MENU_ENUM_LABEL_VIDEO_GPU_SCREENSHOT:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_gpu_screenshot);
break;

View File

@ -6736,6 +6736,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
info->need_push = true;
break;
case DISPLAYLIST_VIDEO_SETTINGS_LIST:
{
settings_t *settings = config_get_ptr();
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_CRT_SWITCHRES_SETTINGS,
@ -6840,6 +6842,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_VIDEO_ROTATION,
PARSE_ONLY_UINT, false);
if (video_display_server_can_set_screen_orientation())
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_SCREEN_ORIENTATION,
PARSE_ONLY_UINT, false);
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_VIDEO_THREADED,
PARSE_ONLY_BOOL, false);
@ -6887,6 +6893,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
info->need_refresh = true;
info->need_push = true;
break;
}
case DISPLAYLIST_CORE_SETTINGS_LIST:
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
menu_displaylist_parse_settings_enum(menu, info,

View File

@ -71,7 +71,6 @@
#include "../paths.h"
#include "../dynamic.h"
#include "../list_special.h"
#include "../verbosity.h"
#include "../camera/camera_driver.h"
#include "../wifi/wifi_driver.h"
#include "../location/location_driver.h"
@ -1982,6 +1981,24 @@ static void setting_get_string_representation_uint_video_rotation(rarch_setting_
}
}
static void setting_get_string_representation_uint_screen_orientation(rarch_setting_t *setting,
char *s, size_t len)
{
if (setting)
{
char rotation_lut[4][32] =
{
"Normal",
"90 deg",
"180 deg",
"270 deg"
};
strlcpy(s, rotation_lut[*setting->value.target.unsigned_integer],
len);
}
}
static void setting_get_string_representation_uint_aspect_ratio_index(
rarch_setting_t *setting,
char *s, size_t len)
@ -3195,6 +3212,15 @@ void general_write_handler(rarch_setting_t *setting)
system->rotation) % 4);
}
break;
case MENU_ENUM_LABEL_SCREEN_ORIENTATION:
{
#ifndef ANDROID
/* FIXME: Changing at runtime on Android causes setting to somehow be incremented again, many times */
video_display_server_set_screen_orientation(
(enum rotation)(*setting->value.target.unsigned_integer));
#endif
}
break;
case MENU_ENUM_LABEL_AUDIO_VOLUME:
audio_set_float(AUDIO_ACTION_VOLUME_GAIN, *setting->value.target.fraction);
break;
@ -6025,6 +6051,23 @@ static bool setting_append_list(
&setting_get_string_representation_uint_video_rotation;
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ADVANCED);
CONFIG_UINT(
list, list_info,
&settings->uints.screen_orientation,
MENU_ENUM_LABEL_SCREEN_ORIENTATION,
MENU_ENUM_LABEL_VALUE_SCREEN_ORIENTATION,
0,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_uint_screen_orientation;
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ADVANCED);
END_SUB_GROUP(list, list_info, parent_group);
START_SUB_GROUP(
list,

View File

@ -802,6 +802,7 @@ enum msg_hash_enums
MENU_LABEL(VIDEO_FULLSCREEN_Y),
MENU_LABEL(VIDEO_FORCE_SRGB_DISABLE),
MENU_LABEL(VIDEO_ROTATION),
MENU_LABEL(SCREEN_ORIENTATION),
MENU_LABEL(VIDEO_SCALE),
MENU_LABEL(VIDEO_RECORD_THREADS),
MENU_LABEL(VIDEO_SMOOTH),

View File

@ -206,6 +206,7 @@ public class RetroActivityCamera extends RetroActivityCommon
edit.apply();
camera_service_running = false;
}
super.onResume();
}

View File

@ -4,8 +4,12 @@ import com.retroarch.browser.preferences.util.UserPreferences;
import android.annotation.TargetApi;
import android.content.res.Configuration;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.view.Surface;
import android.view.WindowManager;
import android.app.UiModeManager;
import android.os.BatteryManager;
import android.os.Build;
@ -24,7 +28,12 @@ public class RetroActivityCommon extends RetroActivityLocation
public static int FRONTEND_POWERSTATE_CHARGING = 2;
public static int FRONTEND_POWERSTATE_CHARGED = 3;
public static int FRONTEND_POWERSTATE_ON_POWER_SOURCE = 4;
public static int FRONTEND_ORIENTATION_0 = 0;
public static int FRONTEND_ORIENTATION_90 = 1;
public static int FRONTEND_ORIENTATION_180 = 2;
public static int FRONTEND_ORIENTATION_270 = 3;
public boolean sustainedPerformanceMode = true;
public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
// Exiting cleanly from NDK seems to be nearly impossible.
// Have to use exit(0) to avoid weird things happening, even with runOnUiThread() approaches.
@ -34,6 +43,70 @@ public class RetroActivityCommon extends RetroActivityLocation
finish();
}
// https://stackoverflow.com/questions/4553650/how-to-check-device-natural-default-orientation-on-android-i-e-get-landscape/4555528#4555528
public int getDeviceDefaultOrientation() {
WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
Configuration config = getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|| ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
config.orientation == Configuration.ORIENTATION_PORTRAIT))
{
return Configuration.ORIENTATION_LANDSCAPE;
}else{
return Configuration.ORIENTATION_PORTRAIT;
}
}
public void setScreenOrientation(int orientation)
{
int naturalOrientation = getDeviceDefaultOrientation();
int newOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
// We assume no device has a natural orientation that is reversed
switch (naturalOrientation) {
case Configuration.ORIENTATION_PORTRAIT:
{
if (orientation == FRONTEND_ORIENTATION_0) {
newOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
}else if (orientation == FRONTEND_ORIENTATION_90) {
newOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
}else if (orientation == FRONTEND_ORIENTATION_180) {
newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
}else if (orientation == FRONTEND_ORIENTATION_270) {
newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}
break;
}
case Configuration.ORIENTATION_LANDSCAPE:
{
if (orientation == FRONTEND_ORIENTATION_0) {
newOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
}else if (orientation == FRONTEND_ORIENTATION_90) {
newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
}else if (orientation == FRONTEND_ORIENTATION_180) {
newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}else if (orientation == FRONTEND_ORIENTATION_270) {
newOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
}
break;
}
}
screenOrientation = newOrientation;
Log.i("RetroActivity", "setting new orientation to " + screenOrientation);
runOnUiThread(new Runnable() {
@Override
public void run() {
setRequestedOrientation(screenOrientation);
}
});
}
@TargetApi(24)
public void setSustainedPerformanceMode(boolean on)
{
@ -137,4 +210,27 @@ public class RetroActivityCommon extends RetroActivityLocation
return false;
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
int oldOrientation = 0;
boolean hasOldOrientation = false;
super.onConfigurationChanged(newConfig);
Log.i("RetroActivity", "onConfigurationChanged: orientation is now " + newConfig.orientation);
SharedPreferences prefs = UserPreferences.getPreferences(this);
SharedPreferences.Editor edit = prefs.edit();
hasOldOrientation = prefs.contains("ORIENTATION");
if (hasOldOrientation)
oldOrientation = prefs.getInt("ORIENTATION", 0);
edit.putInt("ORIENTATION", newConfig.orientation);
edit.apply();
Log.i("RetroActivity", "hasOldOrientation? " + hasOldOrientation + " newOrientation: " + newConfig.orientation + " oldOrientation: " + oldOrientation);
}
}

View File

@ -274,11 +274,15 @@
# This is useful for vertically oriented content where one manually rotates the monitor.
# video_allow_rotate = true
# Forces a certain rotation of the screen.
# Forces a certain rotation of the video.
# The rotation is added to rotations which the libretro core sets (see video_allow_rotate).
# The angle is <value> * 90 degrees counter-clockwise.
# video_rotation = 0
# Forces a certain orientation of the screen from the operating system.
# The angle is <value> * 90 degrees counter-clockwise.
# screen_orientation = 0
#### Audio
# Enable audio.