From d8a2ee253e94c95d4a7744472ba643caa555f67d Mon Sep 17 00:00:00 2001 From: Jamie Vital Date: Wed, 23 Aug 2023 15:45:10 -0400 Subject: [PATCH] Initial work on auto DPI awareness (Android borked) --- android/app/src/main/java/MainActivity.kt | 4 +++ android/loading_screen.cpp | 6 ++-- android/loading_screen.h | 3 +- android/main.cpp | 39 ++++++++++++++++++++--- src-core/core/style.cpp | 29 ++++++++--------- src-core/core/style.h | 5 +-- src-interface/loader/loader.cpp | 26 +++++++-------- src-interface/loader/loader.h | 2 +- src-interface/main_ui.cpp | 34 ++++++++++---------- src-interface/main_ui.h | 3 +- src-ui/loading_screen.cpp | 5 +-- src-ui/loading_screen.h | 3 +- src-ui/main.cpp | 20 ++++++++++-- 13 files changed, 116 insertions(+), 63 deletions(-) diff --git a/android/app/src/main/java/MainActivity.kt b/android/app/src/main/java/MainActivity.kt index e4dfc7e9c..1de902e38 100644 --- a/android/app/src/main/java/MainActivity.kt +++ b/android/app/src/main/java/MainActivity.kt @@ -155,6 +155,10 @@ class MainActivity : NativeActivity(), TextWatcher { return getApplicationInfo().nativeLibraryDir; } + public fun get_dpi() : float { + return getResources().getDisplayMetrics().density; + } + fun showSoftInput() { val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager inputMethodManager.showSoftInput(editText, 0) diff --git a/android/loading_screen.cpp b/android/loading_screen.cpp index f47448c0c..3926e8000 100644 --- a/android/loading_screen.cpp +++ b/android/loading_screen.cpp @@ -8,7 +8,9 @@ namespace satdump { - LoadingScreenSink::LoadingScreenSink(EGLDisplay *g_EglDisplay, EGLSurface *g_EglSurface) : g_EglDisplay{g_EglDisplay}, g_EglSurface{g_EglSurface} + LoadingScreenSink::LoadingScreenSink(EGLDisplay *g_EglDisplay, EGLSurface *g_EglSurface, float scale) : g_EglDisplay{g_EglDisplay}, + g_EglSurface{g_EglSurface}, + scale{scale} { image::Image image; image.load_png(resources::getResourcePath("icon.png")); @@ -59,7 +61,7 @@ namespace satdump ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplAndroid_NewFrame(); - draw_loader(width, height, &image_texture, str); + draw_loader(width, height, scale, &image_texture, str); glViewport(0, 0, (int)width, (int)height); glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); diff --git a/android/loading_screen.h b/android/loading_screen.h index 1dc392296..bc97fc18d 100644 --- a/android/loading_screen.h +++ b/android/loading_screen.h @@ -9,7 +9,7 @@ namespace satdump class LoadingScreenSink : public slog::LoggerSink { public: - LoadingScreenSink(EGLDisplay *g_EglDisplay, EGLSurface *g_EglSurface); + LoadingScreenSink(EGLDisplay *g_EglDisplay, EGLSurface *g_EglSurface, float scale); ~LoadingScreenSink(); protected: void receive(slog::LogMsg log); @@ -18,5 +18,6 @@ namespace satdump EGLDisplay *g_EglDisplay; EGLSurface *g_EglSurface; GLuint image_texture; + float scale; }; } diff --git a/android/main.cpp b/android/main.cpp index 2a8068735..26bb4ef6a 100644 --- a/android/main.cpp +++ b/android/main.cpp @@ -28,7 +28,6 @@ static int GetAssetData(const char *filename, void **out_data); #include "main_ui.h" #include "loading_screen.h" #include "core/style.h" -#include "core/module.h" bool was_init = false; @@ -97,15 +96,15 @@ void init(struct android_app *app) // ImGui::StyleColorsDark(); // ImGui::StyleColorsClassic(); - ui_scale = 2.0; + float display_scale = get_dpi(app); initLogger(); - style::setFonts(); - std::shared_ptr loading_screen_sink = std::make_shared(&g_EglDisplay, &g_EglSurface); + style::setFonts(display_scale); + std::shared_ptr loading_screen_sink = std::make_shared(&g_EglDisplay, &g_EglSurface, display_scale); logger->add_sink(loading_screen_sink); satdump::tle_do_update_on_init = false; satdump::initSatdump(); - satdump::initMainUI(); + satdump::initMainUI(display_scale); //Shut down loading screen logger->del_sink(loading_screen_sink); @@ -297,6 +296,36 @@ std::string getPluginsDir(struct android_app *app) return str; } +float get_dpi(struct android_app* app) +{ + JavaVM* java_vm = app->activity->vm; + JNIEnv* java_env = NULL; + + jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6); + if (jni_return == JNI_ERR) + throw std::runtime_error("Could not get JNI environement"); + + jni_return = java_vm->AttachCurrentThread(&java_env, NULL); + if (jni_return != JNI_OK) + throw std::runtime_error("Could not attach to thread"); + + jclass native_activity_clazz = java_env->GetObjectClass(app->activity->clazz); + if (native_activity_clazz == NULL) + throw std::runtime_error("Could not get MainActivity class"); + + jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "get_dpi", "()Ljava/lang/float;"); + if (method_id == NULL) + throw std::runtime_error("Could not get methode ID"); + + float jflt = (float)java_env->CallFloatMethod(app->activity->clazz, method_id); + + jni_return = java_vm->DetachCurrentThread(); + if (jni_return != JNI_OK) + throw std::runtime_error("Could not detach from thread"); + + return jflt; +} + #include void bindImageTextureFunctions(); diff --git a/src-core/core/style.cpp b/src-core/core/style.cpp index 4a066f3c0..e7d4974c9 100644 --- a/src-core/core/style.cpp +++ b/src-core/core/style.cpp @@ -18,7 +18,7 @@ namespace style bool setDefaultStyle() { - float round = 2.0f; + float round = pow(2.0f, ui_scale); ImGui::GetStyle().WindowRounding = round; ImGui::GetStyle().ChildRounding = round; ImGui::GetStyle().FrameRounding = round; @@ -32,9 +32,9 @@ namespace style return true; } - bool setLightStyle(float dpi_scaling) + bool setLightStyle() { - float round = 2.0f; + float round = pow(2.0f, ui_scale); ImGui::GetStyle().WindowRounding = round; ImGui::GetStyle().ChildRounding = round; ImGui::GetStyle().FrameRounding = round; @@ -91,15 +91,12 @@ namespace style colors[ImGuiCol_NavHighlight] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);*/ - ImGui::GetStyle().ScaleAllSizes(dpi_scaling); - ui_scale = dpi_scaling; - return true; } - bool setDarkStyle(float dpi_scaling) + bool setDarkStyle() { - float round = 2.0f; + float round = pow(2.0f, ui_scale); ImGui::GetStyle().WindowRounding = round; ImGui::GetStyle().ChildRounding = round; ImGui::GetStyle().FrameRounding = round; @@ -156,9 +153,6 @@ namespace style colors[ImGuiCol_NavHighlight] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); - ImGui::GetStyle().ScaleAllSizes(dpi_scaling); - ui_scale = dpi_scaling; - return true; } @@ -177,21 +171,26 @@ namespace style } void setFonts() + { + setFonts(ui_scale); + } + + void setFonts(float dpi_scaling) { ImGui::GetIO().Fonts->Clear(); ImFontGlyphRangesBuilder builder; static const ImWchar def[] = {0x20, 0x2300, 0}; //default range static ImFontConfig config; - baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(resources::getResourcePath("fonts/Roboto-Medium.ttf").c_str(), 16.0f * ui_scale, &config, def); + baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(resources::getResourcePath("fonts/Roboto-Medium.ttf").c_str(), 16.0f * dpi_scaling, &config, def); config.MergeMode = true; static const ImWchar list[6][3] = {{0xf000, 0xf0ff, 0}, {0xf400, 0xf4ff, 0}, {0xf800, 0xf8ff, 0}, {0xfc00, 0xfcff, 0}, {0xea00, 0xeaff, 0}, {0xf200, 0xf2ff, 0}}; for (int i = 0; i < 6; i++) - baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(resources::getResourcePath("fonts/font.ttf").c_str(), 16.0f * ui_scale, &config, list[i]); + baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(resources::getResourcePath("fonts/font.ttf").c_str(), 16.0f * dpi_scaling, &config, list[i]); config.MergeMode = false; - bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(resources::getResourcePath("fonts/Roboto-Medium.ttf").c_str(), 45.0f * ui_scale); //, &config, ranges); - //hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(resources::getResourcePath("fonts/Roboto-Medium.ttf").c_str(), 128.0f * ui_scale); //, &config, ranges); + bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(resources::getResourcePath("fonts/Roboto-Medium.ttf").c_str(), 45.0f * dpi_scaling); //, &config, ranges); + //hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(resources::getResourcePath("fonts/Roboto-Medium.ttf").c_str(), 128.0f * dpi_scaling); //, &config, ranges); ImGui::GetIO().Fonts->Build(); } } \ No newline at end of file diff --git a/src-core/core/style.h b/src-core/core/style.h index eafa6ece3..722eabe92 100644 --- a/src-core/core/style.h +++ b/src-core/core/style.h @@ -10,9 +10,10 @@ namespace style SATDUMP_DLL extern ImFont *hugeFont; bool setDefaultStyle(); - bool setLightStyle(float dpi_scaling = 1.0f); - bool setDarkStyle(float dpi_scaling = 1.0f); + bool setLightStyle(); + bool setDarkStyle(); void beginDisabled(); void endDisabled(); void setFonts(); + void setFonts(float dpi_scaling); } \ No newline at end of file diff --git a/src-interface/loader/loader.cpp b/src-interface/loader/loader.cpp index ce4bb9952..c5bff2a2b 100644 --- a/src-interface/loader/loader.cpp +++ b/src-interface/loader/loader.cpp @@ -5,7 +5,7 @@ namespace satdump { - void draw_loader(int width, int height, GLuint *image_texture, std::string str) + void draw_loader(int width, int height, float scale, GLuint *image_texture, std::string str) { const std::string title = "SatDump"; const std::string slogan = "General Purpose Satellite Data Processor"; @@ -17,33 +17,33 @@ namespace satdump if(width > height) { - ImVec2 reference_pos = { (float)width * 0.2f, ((float)height * 0.5f) - 125 }; + ImVec2 reference_pos = { (float)width * 0.2f, ((float)height * 0.5f) - (125 * scale)}; ImGui::SetCursorPos(reference_pos); - ImGui::Image((void*)(intptr_t)(*image_texture), ImVec2(200, 200)); - ImGui::SetCursorPos({ reference_pos.x + 230, reference_pos.y + 40 }); + ImGui::Image((void*)(intptr_t)(*image_texture), ImVec2(200 * scale, 200 * scale)); + ImGui::SetCursorPos({ reference_pos.x + (230 * scale), reference_pos.y + (40 * scale) }); ImGui::PushFont(style::bigFont); ImGui::TextUnformatted(title.c_str()); ImGui::PopFont(); - ImGui::SetCursorPos({ reference_pos.x + 230, reference_pos.y + 87 }); + ImGui::SetCursorPos({ reference_pos.x + (230 * scale), reference_pos.y + (87 * scale) }); ImGui::TextUnformatted(slogan.c_str()); - ImGui::GetWindowDrawList()->AddLine({reference_pos.x + 230, reference_pos.y + 112}, {reference_pos.x + 490, reference_pos.y + 112}, IM_COL32(155, 155, 155, 255)); - ImGui::SetCursorPos({ reference_pos.x + 230, reference_pos.y + 120 }); + ImGui::GetWindowDrawList()->AddLine({reference_pos.x + (230 * scale), reference_pos.y + (112 * scale)}, {reference_pos.x + (490 * scale), reference_pos.y + (112 * scale)}, IM_COL32(155, 155, 155, 255)); + ImGui::SetCursorPos({ reference_pos.x + (230 * scale), reference_pos.y + (120 * scale) }); } else { ImGui::PushFont(style::bigFont); ImVec2 title_size = ImGui::CalcTextSize(title.c_str()); - ImGui::SetCursorPos({((float)width / 2) - 150, ((float)height / 2) - title_size.y - 315}); - ImGui::Image((void*)(intptr_t)(*image_texture), ImVec2(300, 300)); + ImGui::SetCursorPos({((float)width / 2) - (150 * scale), ((float)height / 2) - title_size.y - (315 * scale)}); + ImGui::Image((void*)(intptr_t)(*image_texture), ImVec2(300 * scale, 300 * scale)); ImGui::SetCursorPos({((float)width / 2) - (title_size.x / 2), ((float)height / 2) - title_size.y}); ImGui::TextUnformatted(title.c_str()); ImGui::PopFont(); ImVec2 slogan_size = ImGui::CalcTextSize(slogan.c_str()); - ImGui::SetCursorPos({ ((float)width / 2) - (slogan_size.x / 2), ((float)height / 2) + 10 }); + ImGui::SetCursorPos({ ((float)width / 2) - (slogan_size.x / 2), ((float)height / 2) + (10 * scale) }); ImGui::TextUnformatted(slogan.c_str()); - ImGui::GetWindowDrawList()->AddLine({((float)width / 2) - (slogan_size.x / 2), ((float)height / 2) + 20 + slogan_size.y}, - {((float)width / 2) + (slogan_size.x / 2), ((float)height / 2) + 20 + slogan_size.y}, IM_COL32(155, 155, 155, 255)); - ImGui::SetCursorPos({((float)width / 2) - (ImGui::CalcTextSize(str.c_str()).x / 2), ((float)height / 2) + 25 + slogan_size.y}); + ImGui::GetWindowDrawList()->AddLine({((float)width / 2) - (slogan_size.x / 2), ((float)height / 2) + (20 * scale) + slogan_size.y}, + {((float)width / 2) + (slogan_size.x / 2), ((float)height / 2) + (20 * scale) + slogan_size.y}, IM_COL32(155, 155, 155, 255)); + ImGui::SetCursorPos({((float)width / 2) - (ImGui::CalcTextSize(str.c_str()).x / 2), ((float)height / 2) + (25 * scale) + slogan_size.y}); } ImGui::TextDisabled("%s", str.c_str()); diff --git a/src-interface/loader/loader.h b/src-interface/loader/loader.h index 166f5d295..1363a4923 100644 --- a/src-interface/loader/loader.h +++ b/src-interface/loader/loader.h @@ -7,5 +7,5 @@ namespace satdump { - void draw_loader(int width, int height, GLuint *image_texture, std::string str); + void draw_loader(int width, int height, float scale, GLuint *image_texture, std::string str); } \ No newline at end of file diff --git a/src-interface/main_ui.cpp b/src-interface/main_ui.cpp index d38fcae7b..1d703cf9d 100644 --- a/src-interface/main_ui.cpp +++ b/src-interface/main_ui.cpp @@ -36,28 +36,14 @@ namespace satdump std::shared_ptr notify_logger_sink; std::shared_ptr status_logger_sink; - void initMainUI() + void initMainUI(float device_scale) { audio::registerSinks(); - offline::setup(); settings::setup(); - light_theme = config::main_cfg["user_interface"]["light_theme"]["value"].get(); - float manual_dpi_scaling = config::main_cfg["user_interface"]["manual_dpi_scaling"]["value"].get(); - -#ifdef __ANDROID__ - manual_dpi_scaling *= 3; // Otherwise it's just too small by default! -#endif - - ui_scale = manual_dpi_scaling; - - // Setup Theme - - if (light_theme) - style::setLightStyle(manual_dpi_scaling); - else - style::setDarkStyle(manual_dpi_scaling); + // Setup DPI/Theme + updateUI(device_scale); // Load credits MD std::ifstream ifs(resources::getResourcePath("credits.md")); @@ -81,6 +67,20 @@ namespace satdump logger->add_sink(status_logger_sink); } + void updateUI(float device_scale) + { + light_theme = config::main_cfg["user_interface"]["light_theme"]["value"].get(); + float manual_dpi_scaling = config::main_cfg["user_interface"]["manual_dpi_scaling"]["value"].get(); + ui_scale = device_scale * manual_dpi_scaling; + ImGui::GetStyle() = ImGuiStyle::ImGuiStyle(); + ImGui::GetStyle().ScaleAllSizes(ui_scale); + + if (light_theme) + style::setLightStyle(); + else + style::setDarkStyle(); + } + void exitMainUI() { viewer_app.reset(); diff --git a/src-interface/main_ui.h b/src-interface/main_ui.h index e75cf2d36..274864bd1 100644 --- a/src-interface/main_ui.h +++ b/src-interface/main_ui.h @@ -19,7 +19,8 @@ namespace satdump extern std::shared_ptr recorder_app; extern std::shared_ptr viewer_app; - void initMainUI(); + void initMainUI(float device_scale); + void updateUI(float device_scale); void exitMainUI(); void renderMainUI(int wwidth, int wheight); } \ No newline at end of file diff --git a/src-ui/loading_screen.cpp b/src-ui/loading_screen.cpp index c444314d0..0d33c1635 100644 --- a/src-ui/loading_screen.cpp +++ b/src-ui/loading_screen.cpp @@ -6,7 +6,8 @@ namespace satdump { - LoadingScreenSink::LoadingScreenSink(GLFWwindow* window, GLFWimage* img) : window{window} + LoadingScreenSink::LoadingScreenSink(GLFWwindow* window, float scale, GLFWimage* img) : window{window}, + scale{scale} { glGenTextures(1, &image_texture); glBindTexture(GL_TEXTURE_2D, image_texture); @@ -35,7 +36,7 @@ namespace satdump ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); - draw_loader(display_w, display_h, &image_texture, str); + draw_loader(display_w, display_h, scale, &image_texture, str); glViewport(0, 0, display_w, display_h); glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f); diff --git a/src-ui/loading_screen.h b/src-ui/loading_screen.h index 066fe1be3..6c6167219 100644 --- a/src-ui/loading_screen.h +++ b/src-ui/loading_screen.h @@ -8,12 +8,13 @@ namespace satdump class LoadingScreenSink : public slog::LoggerSink { public: - LoadingScreenSink(GLFWwindow* window, GLFWimage* img); + LoadingScreenSink(GLFWwindow* window, float scale, GLFWimage* img); ~LoadingScreenSink(); protected: void receive(slog::LogMsg log); private: void push_frame(std::string str); + float scale; GLFWwindow* window; GLuint image_texture; }; diff --git a/src-ui/main.cpp b/src-ui/main.cpp index 35e26ae90..100be7051 100644 --- a/src-ui/main.cpp +++ b/src-ui/main.cpp @@ -22,6 +22,14 @@ static void glfw_error_callback(int error, const char *description) logger->error("Glfw Error " + std::to_string(error) + ": " + description); } +void window_content_scale_callback(GLFWwindow* window, float xscale, float yscale) +{ + satdump::updateUI(xscale); + style::setFonts(); + ImGui_ImplOpenGL3_DestroyFontsTexture(); + ImGui_ImplOpenGL3_CreateFontsTexture(); +} + void bindImageTextureFunctions(); // OpenGL versions to try to start @@ -69,6 +77,7 @@ int main(int argc, char *argv[]) // Initialize GLFW GLFWwindow *window = nullptr; int final_gl_version = 0; + glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); #ifdef __APPLE__ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); @@ -209,11 +218,16 @@ int main(int argc, char *argv[]) } glfwSetWindowIcon(window, 1, &img); + //Handle DPI changes + float display_scale; + glfwSetWindowContentScaleCallback(window, window_content_scale_callback); + glfwGetWindowContentScale(window, &display_scale, nullptr); + //Set font - style::setFonts(); + style::setFonts(display_scale); // Init Loading Screen - std::shared_ptr loading_screen_sink = std::make_shared(window, &img); + std::shared_ptr loading_screen_sink = std::make_shared(window, display_scale, &img); logger->add_sink(loading_screen_sink); // Init SatDump @@ -221,7 +235,7 @@ int main(int argc, char *argv[]) satdump::initSatdump(); // Init UI - satdump::initMainUI(); + satdump::initMainUI(display_scale); //Shut down loading screen logger->del_sink(loading_screen_sink);