Path: blob/master/platform/android/display_server_android.cpp
10277 views
/**************************************************************************/1/* display_server_android.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "display_server_android.h"3132#include "java_godot_io_wrapper.h"33#include "java_godot_wrapper.h"34#include "os_android.h"35#include "tts_android.h"3637#include "core/config/project_settings.h"3839#if defined(RD_ENABLED)40#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"41#include "servers/rendering/rendering_device.h"4243#if defined(VULKAN_ENABLED)44#include "rendering_context_driver_vulkan_android.h"45#endif46#endif4748#ifdef GLES3_ENABLED49#include "drivers/gles3/rasterizer_gles3.h"5051#include <EGL/egl.h>52#endif5354DisplayServerAndroid *DisplayServerAndroid::get_singleton() {55return static_cast<DisplayServerAndroid *>(DisplayServer::get_singleton());56}5758bool DisplayServerAndroid::has_feature(Feature p_feature) const {59switch (p_feature) {60#ifndef DISABLE_DEPRECATED61case FEATURE_GLOBAL_MENU: {62return (native_menu && native_menu->has_feature(NativeMenu::FEATURE_GLOBAL_MENU));63} break;64#endif65case FEATURE_NATIVE_DIALOG_FILE: {66String sdk_version = OS::get_singleton()->get_version().get_slicec('.', 0);67return sdk_version.to_int() >= 29;68} break;6970case FEATURE_CURSOR_SHAPE:71//case FEATURE_CUSTOM_CURSOR_SHAPE:72//case FEATURE_HIDPI:73//case FEATURE_ICON:74//case FEATURE_IME:75case FEATURE_MOUSE:76//case FEATURE_MOUSE_WARP:77case FEATURE_NATIVE_DIALOG:78case FEATURE_NATIVE_DIALOG_INPUT:79//case FEATURE_NATIVE_DIALOG_FILE_EXTRA:80case FEATURE_NATIVE_DIALOG_FILE_MIME:81//case FEATURE_NATIVE_ICON:82case FEATURE_WINDOW_TRANSPARENCY:83case FEATURE_CLIPBOARD:84case FEATURE_KEEP_SCREEN_ON:85case FEATURE_ORIENTATION:86case FEATURE_TOUCHSCREEN:87case FEATURE_VIRTUAL_KEYBOARD:88case FEATURE_TEXT_TO_SPEECH:89return true;90default:91return false;92}93}9495String DisplayServerAndroid::get_name() const {96return "Android";97}9899bool DisplayServerAndroid::tts_is_speaking() const {100return TTS_Android::is_speaking();101}102103bool DisplayServerAndroid::tts_is_paused() const {104return TTS_Android::is_paused();105}106107TypedArray<Dictionary> DisplayServerAndroid::tts_get_voices() const {108return TTS_Android::get_voices();109}110111void DisplayServerAndroid::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {112TTS_Android::speak(p_text, p_voice, p_volume, p_pitch, p_rate, p_utterance_id, p_interrupt);113}114115void DisplayServerAndroid::tts_pause() {116TTS_Android::pause();117}118119void DisplayServerAndroid::tts_resume() {120TTS_Android::resume();121}122123void DisplayServerAndroid::tts_stop() {124TTS_Android::stop();125}126127bool DisplayServerAndroid::is_dark_mode_supported() const {128GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();129ERR_FAIL_NULL_V(godot_java, false);130131return godot_java->is_dark_mode_supported();132}133134bool DisplayServerAndroid::is_dark_mode() const {135GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();136ERR_FAIL_NULL_V(godot_java, false);137138return godot_java->is_dark_mode();139}140141void DisplayServerAndroid::set_system_theme_change_callback(const Callable &p_callable) {142system_theme_changed = p_callable;143}144145void DisplayServerAndroid::emit_system_theme_changed() {146if (system_theme_changed.is_valid()) {147system_theme_changed.call_deferred();148}149}150151void DisplayServerAndroid::set_hardware_keyboard_connection_change_callback(const Callable &p_callable) {152hardware_keyboard_connection_changed = p_callable;153}154155void DisplayServerAndroid::emit_hardware_keyboard_connection_changed(bool p_connected) {156if (hardware_keyboard_connection_changed.is_valid()) {157hardware_keyboard_connection_changed.call_deferred(p_connected);158}159}160161void DisplayServerAndroid::clipboard_set(const String &p_text) {162GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();163ERR_FAIL_NULL(godot_java);164165if (godot_java->has_set_clipboard()) {166godot_java->set_clipboard(p_text);167} else {168DisplayServer::clipboard_set(p_text);169}170}171172String DisplayServerAndroid::clipboard_get() const {173GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();174ERR_FAIL_NULL_V(godot_java, String());175176if (godot_java->has_get_clipboard()) {177return godot_java->get_clipboard();178} else {179return DisplayServer::clipboard_get();180}181}182183bool DisplayServerAndroid::clipboard_has() const {184GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();185ERR_FAIL_NULL_V(godot_java, false);186187if (godot_java->has_has_clipboard()) {188return godot_java->has_clipboard();189} else {190return DisplayServer::clipboard_has();191}192}193194Error DisplayServerAndroid::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {195GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();196ERR_FAIL_NULL_V(godot_java, FAILED);197dialog_callback = p_callback;198return godot_java->show_dialog(p_title, p_description, p_buttons);199}200201void DisplayServerAndroid::emit_dialog_callback(int p_button_index) {202if (dialog_callback.is_valid()) {203dialog_callback.call_deferred(p_button_index);204}205}206207Error DisplayServerAndroid::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {208GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();209ERR_FAIL_NULL_V(godot_java, FAILED);210input_dialog_callback = p_callback;211return godot_java->show_input_dialog(p_title, p_description, p_partial);212}213214void DisplayServerAndroid::emit_input_dialog_callback(String p_text) {215if (input_dialog_callback.is_valid()) {216input_dialog_callback.call_deferred(p_text);217}218}219220Error DisplayServerAndroid::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) {221GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();222ERR_FAIL_NULL_V(godot_java, FAILED);223file_picker_callback = p_callback;224return godot_java->show_file_picker(p_current_directory, p_filename, p_mode, p_filters);225}226227void DisplayServerAndroid::emit_file_picker_callback(bool p_ok, const Vector<String> &p_selected_paths) {228if (file_picker_callback.is_valid()) {229file_picker_callback.call_deferred(p_ok, p_selected_paths, 0);230}231}232233Color DisplayServerAndroid::get_accent_color() const {234GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();235ERR_FAIL_NULL_V(godot_java, Color(0, 0, 0, 0));236return godot_java->get_accent_color();237}238239Color DisplayServerAndroid::get_base_color() const {240GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();241ERR_FAIL_NULL_V(godot_java, Color(0, 0, 0, 0));242return godot_java->get_base_color();243}244245TypedArray<Rect2> DisplayServerAndroid::get_display_cutouts() const {246GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();247ERR_FAIL_NULL_V(godot_io_java, Array());248return godot_io_java->get_display_cutouts();249}250251Rect2i DisplayServerAndroid::get_display_safe_area() const {252GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();253ERR_FAIL_NULL_V(godot_io_java, Rect2i());254return godot_io_java->get_display_safe_area();255}256257void DisplayServerAndroid::screen_set_keep_on(bool p_enable) {258GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();259ERR_FAIL_NULL(godot_java);260261godot_java->set_keep_screen_on(p_enable);262keep_screen_on = p_enable;263}264265bool DisplayServerAndroid::screen_is_kept_on() const {266return keep_screen_on;267}268269void DisplayServerAndroid::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) {270p_screen = _get_screen_index(p_screen);271int screen_count = get_screen_count();272ERR_FAIL_INDEX(p_screen, screen_count);273274GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();275ERR_FAIL_NULL(godot_io_java);276277godot_io_java->set_screen_orientation(p_orientation);278}279280DisplayServer::ScreenOrientation DisplayServerAndroid::screen_get_orientation(int p_screen) const {281p_screen = _get_screen_index(p_screen);282int screen_count = get_screen_count();283ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_LANDSCAPE);284285GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();286ERR_FAIL_NULL_V(godot_io_java, SCREEN_LANDSCAPE);287288const int orientation = godot_io_java->get_screen_orientation();289ERR_FAIL_INDEX_V_MSG(orientation, 7, SCREEN_LANDSCAPE, "Unrecognized screen orientation");290return (ScreenOrientation)orientation;291}292293int DisplayServerAndroid::get_display_rotation() const {294GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();295ERR_FAIL_NULL_V(godot_io_java, 0);296297return godot_io_java->get_display_rotation();298}299300int DisplayServerAndroid::get_screen_count() const {301return 1;302}303304int DisplayServerAndroid::get_primary_screen() const {305return 0;306}307308Point2i DisplayServerAndroid::screen_get_position(int p_screen) const {309p_screen = _get_screen_index(p_screen);310int screen_count = get_screen_count();311ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i());312313return Point2i(0, 0);314}315316Size2i DisplayServerAndroid::screen_get_size(int p_screen) const {317p_screen = _get_screen_index(p_screen);318int screen_count = get_screen_count();319ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i());320321return OS_Android::get_singleton()->get_display_size();322}323324Rect2i DisplayServerAndroid::screen_get_usable_rect(int p_screen) const {325p_screen = _get_screen_index(p_screen);326int screen_count = get_screen_count();327ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i());328329Size2i display_size = OS_Android::get_singleton()->get_display_size();330return Rect2i(0, 0, display_size.width, display_size.height);331}332333int DisplayServerAndroid::screen_get_dpi(int p_screen) const {334p_screen = _get_screen_index(p_screen);335int screen_count = get_screen_count();336ERR_FAIL_INDEX_V(p_screen, screen_count, 160);337338GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();339ERR_FAIL_NULL_V(godot_io_java, 160);340341return godot_io_java->get_screen_dpi();342}343344float DisplayServerAndroid::screen_get_scale(int p_screen) const {345p_screen = _get_screen_index(p_screen);346int screen_count = get_screen_count();347ERR_FAIL_INDEX_V(p_screen, screen_count, 1.0f);348349GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();350ERR_FAIL_NULL_V(godot_io_java, 1.0f);351352float screen_scale = godot_io_java->get_scaled_density();353354// Update the scale to avoid cropping.355Size2i screen_size = screen_get_size(p_screen);356if (screen_size != Size2i()) {357float width_scale = screen_size.width / (float)OS_Android::DEFAULT_WINDOW_WIDTH;358float height_scale = screen_size.height / (float)OS_Android::DEFAULT_WINDOW_HEIGHT;359screen_scale = MIN(screen_scale, MIN(width_scale, height_scale));360}361362return screen_scale;363}364365float DisplayServerAndroid::screen_get_refresh_rate(int p_screen) const {366p_screen = _get_screen_index(p_screen);367int screen_count = get_screen_count();368ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK);369370GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();371if (!godot_io_java) {372ERR_PRINT("An error occurred while trying to get the screen refresh rate.");373return SCREEN_REFRESH_RATE_FALLBACK;374}375376return godot_io_java->get_screen_refresh_rate(SCREEN_REFRESH_RATE_FALLBACK);377}378379bool DisplayServerAndroid::is_touchscreen_available() const {380return true;381}382383void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {384GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();385ERR_FAIL_NULL(godot_io_java);386387if (godot_io_java->has_vk()) {388godot_io_java->show_vk(p_existing_text, (int)p_type, p_max_length, p_cursor_start, p_cursor_end);389} else {390ERR_PRINT("Virtual keyboard not available");391}392}393394void DisplayServerAndroid::virtual_keyboard_hide() {395GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();396ERR_FAIL_NULL(godot_io_java);397398if (godot_io_java->has_vk()) {399godot_io_java->hide_vk();400} else {401ERR_PRINT("Virtual keyboard not available");402}403}404405int DisplayServerAndroid::virtual_keyboard_get_height() const {406GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();407ERR_FAIL_NULL_V(godot_io_java, 0);408409return godot_io_java->get_vk_height();410}411412bool DisplayServerAndroid::has_hardware_keyboard() const {413GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();414ERR_FAIL_NULL_V(godot_io_java, false);415416return godot_io_java->has_hardware_keyboard();417}418419void DisplayServerAndroid::window_set_window_event_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {420window_event_callback = p_callable;421}422423void DisplayServerAndroid::window_set_input_event_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {424input_event_callback = p_callable;425}426427void DisplayServerAndroid::window_set_input_text_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {428input_text_callback = p_callable;429}430431void DisplayServerAndroid::window_set_rect_changed_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {432rect_changed_callback = p_callable;433}434435void DisplayServerAndroid::window_set_drop_files_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {436// Not supported on Android.437}438439void DisplayServerAndroid::_window_callback(const Callable &p_callable, const Variant &p_arg, bool p_deferred) const {440if (p_callable.is_valid()) {441if (p_deferred) {442p_callable.call_deferred(p_arg);443} else {444p_callable.call(p_arg);445}446}447}448449void DisplayServerAndroid::send_window_event(DisplayServer::WindowEvent p_event, bool p_deferred) const {450_window_callback(window_event_callback, int(p_event), p_deferred);451}452453void DisplayServerAndroid::send_input_event(const Ref<InputEvent> &p_event) const {454_window_callback(input_event_callback, p_event);455}456457void DisplayServerAndroid::send_input_text(const String &p_text) const {458_window_callback(input_text_callback, p_text);459}460461void DisplayServerAndroid::_dispatch_input_events(const Ref<InputEvent> &p_event) {462DisplayServerAndroid::get_singleton()->send_input_event(p_event);463}464465Vector<DisplayServer::WindowID> DisplayServerAndroid::get_window_list() const {466Vector<WindowID> ret;467ret.push_back(MAIN_WINDOW_ID);468return ret;469}470471DisplayServer::WindowID DisplayServerAndroid::get_window_at_screen_position(const Point2i &p_position) const {472return MAIN_WINDOW_ID;473}474475int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const {476ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0);477switch (p_handle_type) {478case WINDOW_HANDLE: {479return reinterpret_cast<int64_t>(static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity());480}481case WINDOW_VIEW: {482return 0; // Not supported.483}484#ifdef GLES3_ENABLED485case DISPLAY_HANDLE: {486if (rendering_driver == "opengl3") {487return reinterpret_cast<int64_t>(eglGetCurrentDisplay());488}489return 0;490}491case OPENGL_CONTEXT: {492if (rendering_driver == "opengl3") {493return reinterpret_cast<int64_t>(eglGetCurrentContext());494}495return 0;496}497case EGL_DISPLAY: {498// @todo Find a way to get this from the Java side.499return 0;500}501case EGL_CONFIG: {502// @todo Find a way to get this from the Java side.503return 0;504}505#endif506default: {507return 0;508}509}510}511512void DisplayServerAndroid::window_attach_instance_id(ObjectID p_instance, DisplayServer::WindowID p_window) {513window_attached_instance_id = p_instance;514}515516ObjectID DisplayServerAndroid::window_get_attached_instance_id(DisplayServer::WindowID p_window) const {517return window_attached_instance_id;518}519520void DisplayServerAndroid::window_set_title(const String &p_title, DisplayServer::WindowID p_window) {521// Not supported on Android.522}523524int DisplayServerAndroid::window_get_current_screen(DisplayServer::WindowID p_window) const {525ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, INVALID_SCREEN);526return 0;527}528529void DisplayServerAndroid::window_set_current_screen(int p_screen, DisplayServer::WindowID p_window) {530// Not supported on Android.531}532533Point2i DisplayServerAndroid::window_get_position(DisplayServer::WindowID p_window) const {534return Point2i();535}536537Point2i DisplayServerAndroid::window_get_position_with_decorations(DisplayServer::WindowID p_window) const {538return Point2i();539}540541void DisplayServerAndroid::window_set_position(const Point2i &p_position, DisplayServer::WindowID p_window) {542// Not supported on Android.543}544545void DisplayServerAndroid::window_set_transient(DisplayServer::WindowID p_window, DisplayServer::WindowID p_parent) {546// Not supported on Android.547}548549void DisplayServerAndroid::window_set_max_size(const Size2i p_size, DisplayServer::WindowID p_window) {550// Not supported on Android.551}552553Size2i DisplayServerAndroid::window_get_max_size(DisplayServer::WindowID p_window) const {554return Size2i();555}556557void DisplayServerAndroid::window_set_min_size(const Size2i p_size, DisplayServer::WindowID p_window) {558// Not supported on Android.559}560561Size2i DisplayServerAndroid::window_get_min_size(DisplayServer::WindowID p_window) const {562return Size2i();563}564565void DisplayServerAndroid::window_set_size(const Size2i p_size, DisplayServer::WindowID p_window) {566// Not supported on Android.567}568569Size2i DisplayServerAndroid::window_get_size(DisplayServer::WindowID p_window) const {570return OS_Android::get_singleton()->get_display_size();571}572573Size2i DisplayServerAndroid::window_get_size_with_decorations(DisplayServer::WindowID p_window) const {574return OS_Android::get_singleton()->get_display_size();575}576577void DisplayServerAndroid::window_set_mode(DisplayServer::WindowMode p_mode, DisplayServer::WindowID p_window) {578OS_Android::get_singleton()->get_godot_java()->enable_immersive_mode(p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN);579}580581DisplayServer::WindowMode DisplayServerAndroid::window_get_mode(DisplayServer::WindowID p_window) const {582if (OS_Android::get_singleton()->get_godot_java()->is_in_immersive_mode()) {583return WINDOW_MODE_FULLSCREEN;584} else {585return WINDOW_MODE_MAXIMIZED;586}587}588589bool DisplayServerAndroid::window_is_maximize_allowed(DisplayServer::WindowID p_window) const {590return false;591}592593void DisplayServerAndroid::window_set_flag(DisplayServer::WindowFlags p_flag, bool p_enabled, DisplayServer::WindowID p_window) {594// Not supported on Android.595}596597bool DisplayServerAndroid::window_get_flag(DisplayServer::WindowFlags p_flag, DisplayServer::WindowID p_window) const {598ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, false);599switch (p_flag) {600case WindowFlags::WINDOW_FLAG_TRANSPARENT:601return is_window_transparency_available();602603default:604return false;605}606}607608void DisplayServerAndroid::window_request_attention(DisplayServer::WindowID p_window) {609// Not supported on Android.610}611612void DisplayServerAndroid::window_move_to_foreground(DisplayServer::WindowID p_window) {613// Not supported on Android.614}615616bool DisplayServerAndroid::window_is_focused(WindowID p_window) const {617return true;618}619620bool DisplayServerAndroid::window_can_draw(DisplayServer::WindowID p_window) const {621return true;622}623624bool DisplayServerAndroid::can_any_window_draw() const {625return true;626}627628void DisplayServerAndroid::process_events() {629Input::get_singleton()->flush_buffered_events();630}631632Vector<String> DisplayServerAndroid::get_rendering_drivers_func() {633Vector<String> drivers;634635#ifdef GLES3_ENABLED636drivers.push_back("opengl3");637#endif638#ifdef VULKAN_ENABLED639drivers.push_back("vulkan");640#endif641642return drivers;643}644645DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) {646DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, p_parent_window, r_error));647if (r_error != OK) {648if (p_rendering_driver == "vulkan") {649OS::get_singleton()->alert(650"Your device seems not to support the required Vulkan version.\n\n"651"Please try exporting your game using the 'gl_compatibility' renderer.",652"Unable to initialize Vulkan video driver");653} else {654OS::get_singleton()->alert(655"Your device seems not to support the required OpenGL ES 3.0 version.",656"Unable to initialize OpenGL video driver");657}658}659return ds;660}661662void DisplayServerAndroid::register_android_driver() {663register_create_function("android", create_func, get_rendering_drivers_func);664}665666void DisplayServerAndroid::reset_window() {667#if defined(RD_ENABLED)668if (rendering_context) {669if (rendering_device) {670rendering_device->screen_free(MAIN_WINDOW_ID);671}672673VSyncMode last_vsync_mode = rendering_context->window_get_vsync_mode(MAIN_WINDOW_ID);674rendering_context->window_destroy(MAIN_WINDOW_ID);675676union {677#ifdef VULKAN_ENABLED678RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan;679#endif680} wpd;681#ifdef VULKAN_ENABLED682if (rendering_driver == "vulkan") {683ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();684ERR_FAIL_NULL(native_window);685wpd.vulkan.window = native_window;686}687#endif688689if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {690ERR_PRINT(vformat("Failed to reset %s window.", rendering_driver));691memdelete(rendering_context);692rendering_context = nullptr;693return;694}695696Size2i display_size = OS_Android::get_singleton()->get_display_size();697rendering_context->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height);698rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, last_vsync_mode);699700if (rendering_device) {701rendering_device->screen_create(MAIN_WINDOW_ID);702}703}704#endif705}706707void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {708if (rect_changed_callback.is_valid()) {709rect_changed_callback.call(Rect2i(0, 0, p_width, p_height));710}711}712713DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) {714rendering_driver = p_rendering_driver;715716keep_screen_on = GLOBAL_GET("display/window/energy_saving/keep_screen_on");717718native_menu = memnew(NativeMenu);719720#if defined(RD_ENABLED)721rendering_context = nullptr;722rendering_device = nullptr;723724#if defined(VULKAN_ENABLED)725if (rendering_driver == "vulkan") {726rendering_context = memnew(RenderingContextDriverVulkanAndroid);727}728#endif729730if (rendering_context) {731if (rendering_context->initialize() != OK) {732memdelete(rendering_context);733rendering_context = nullptr;734#if defined(GLES3_ENABLED)735bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");736if (fallback_to_opengl3 && rendering_driver != "opengl3") {737WARN_PRINT("Your device does not seem to support Vulkan, switching to OpenGL 3.");738rendering_driver = "opengl3";739OS::get_singleton()->set_current_rendering_method("gl_compatibility");740OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);741} else742#endif743{744ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));745r_error = ERR_UNAVAILABLE;746return;747}748}749}750751if (rendering_context) {752union {753#ifdef VULKAN_ENABLED754RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan;755#endif756} wpd;757#ifdef VULKAN_ENABLED758if (rendering_driver == "vulkan") {759ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();760ERR_FAIL_NULL(native_window);761wpd.vulkan.window = native_window;762}763#endif764765if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {766ERR_PRINT(vformat("Failed to create %s window.", rendering_driver));767memdelete(rendering_context);768rendering_context = nullptr;769r_error = ERR_UNAVAILABLE;770return;771}772773Size2i display_size = OS_Android::get_singleton()->get_display_size();774rendering_context->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height);775rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, p_vsync_mode);776777rendering_device = memnew(RenderingDevice);778if (rendering_device->initialize(rendering_context, MAIN_WINDOW_ID) != OK) {779rendering_device = nullptr;780memdelete(rendering_context);781rendering_context = nullptr;782r_error = ERR_UNAVAILABLE;783return;784}785rendering_device->screen_create(MAIN_WINDOW_ID);786787RendererCompositorRD::make_current();788}789#endif790791#if defined(GLES3_ENABLED)792if (rendering_driver == "opengl3") {793RasterizerGLES3::make_current(false);794}795#endif796797Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);798799r_error = OK;800}801802DisplayServerAndroid::~DisplayServerAndroid() {803if (native_menu) {804memdelete(native_menu);805native_menu = nullptr;806}807808#if defined(RD_ENABLED)809if (rendering_device) {810memdelete(rendering_device);811}812if (rendering_context) {813memdelete(rendering_context);814}815#endif816}817818void DisplayServerAndroid::process_accelerometer(const Vector3 &p_accelerometer) {819Input::get_singleton()->set_accelerometer(p_accelerometer);820}821822void DisplayServerAndroid::process_gravity(const Vector3 &p_gravity) {823Input::get_singleton()->set_gravity(p_gravity);824}825826void DisplayServerAndroid::process_magnetometer(const Vector3 &p_magnetometer) {827Input::get_singleton()->set_magnetometer(p_magnetometer);828}829830void DisplayServerAndroid::process_gyroscope(const Vector3 &p_gyroscope) {831Input::get_singleton()->set_gyroscope(p_gyroscope);832}833834void DisplayServerAndroid::_mouse_update_mode() {835MouseMode wanted_mouse_mode = mouse_mode_override_enabled836? mouse_mode_override837: mouse_mode_base;838839if (!OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_update_pointer_icon() || !OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_capture_pointer()) {840return;841}842if (mouse_mode == wanted_mouse_mode) {843return;844}845846if (wanted_mouse_mode == MouseMode::MOUSE_MODE_HIDDEN) {847OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(CURSOR_TYPE_NULL);848} else {849cursor_set_shape(cursor_shape);850}851852if (wanted_mouse_mode == MouseMode::MOUSE_MODE_CAPTURED) {853OS_Android::get_singleton()->get_godot_java()->get_godot_view()->request_pointer_capture();854} else {855OS_Android::get_singleton()->get_godot_java()->get_godot_view()->release_pointer_capture();856}857858mouse_mode = wanted_mouse_mode;859}860861void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) {862ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX);863if (p_mode == mouse_mode_base) {864return;865}866mouse_mode_base = p_mode;867_mouse_update_mode();868}869870DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode() const {871return mouse_mode;872}873874void DisplayServerAndroid::mouse_set_mode_override(MouseMode p_mode) {875ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX);876if (p_mode == mouse_mode_override) {877return;878}879mouse_mode_override = p_mode;880_mouse_update_mode();881}882883DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode_override() const {884return mouse_mode_override;885}886887void DisplayServerAndroid::mouse_set_mode_override_enabled(bool p_override_enabled) {888mouse_mode_override_enabled = p_override_enabled;889_mouse_update_mode();890}891892bool DisplayServerAndroid::mouse_is_mode_override_enabled() const {893return mouse_mode_override_enabled;894}895896Point2i DisplayServerAndroid::mouse_get_position() const {897return Input::get_singleton()->get_mouse_position();898}899900BitField<MouseButtonMask> DisplayServerAndroid::mouse_get_button_state() const {901return Input::get_singleton()->get_mouse_button_mask();902}903904void DisplayServerAndroid::_cursor_set_shape_helper(CursorShape p_shape, bool force) {905if (!OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_update_pointer_icon()) {906return;907}908if (cursor_shape == p_shape && !force) {909return;910}911912cursor_shape = p_shape;913914if (mouse_mode == MouseMode::MOUSE_MODE_VISIBLE || mouse_mode == MouseMode::MOUSE_MODE_CONFINED) {915OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(android_cursors[cursor_shape]);916}917}918919void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) {920ERR_FAIL_INDEX(p_shape, CURSOR_MAX);921_cursor_set_shape_helper(p_shape);922}923924DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {925return cursor_shape;926}927928void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {929ERR_FAIL_INDEX(p_shape, CURSOR_MAX);930String cursor_path = p_cursor.is_valid() ? p_cursor->get_path() : "";931if (!cursor_path.is_empty()) {932cursor_path = ProjectSettings::get_singleton()->globalize_path(cursor_path);933}934OS_Android::get_singleton()->get_godot_java()->get_godot_view()->configure_pointer_icon(android_cursors[cursor_shape], cursor_path, p_hotspot);935_cursor_set_shape_helper(p_shape, true);936}937938void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {939#if defined(RD_ENABLED)940if (rendering_context) {941rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);942}943#endif944}945946DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const {947#if defined(RD_ENABLED)948if (rendering_context) {949return rendering_context->window_get_vsync_mode(p_window);950}951#endif952return DisplayServer::VSYNC_ENABLED;953}954955void DisplayServerAndroid::reset_swap_buffers_flag() {956swap_buffers_flag = false;957}958959bool DisplayServerAndroid::should_swap_buffers() const {960return swap_buffers_flag;961}962963void DisplayServerAndroid::swap_buffers() {964swap_buffers_flag = true;965}966967void DisplayServerAndroid::set_native_icon(const String &p_filename) {968// NOT SUPPORTED969}970971void DisplayServerAndroid::set_icon(const Ref<Image> &p_icon) {972// NOT SUPPORTED973}974975bool DisplayServerAndroid::is_window_transparency_available() const {976return GLOBAL_GET_CACHED(bool, "display/window/per_pixel_transparency/allowed");977}978979980