From ab1075e2961107a9f9d411d4afc0f4fe144dec36 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 17 Jan 2022 09:26:37 -0700 Subject: [PATCH] DisplaySettings: Show DPI for selected resolution This uses the EDID provided by the connected display to show the pixel density of a selected resolution. --- .../DisplaySettings/CMakeLists.txt | 2 +- .../DisplaySettings/MonitorSettings.gml | 7 +++ .../DisplaySettings/MonitorSettingsWidget.cpp | 49 ++++++++++++++++--- .../DisplaySettings/MonitorSettingsWidget.h | 3 +- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/Userland/Applications/DisplaySettings/CMakeLists.txt b/Userland/Applications/DisplaySettings/CMakeLists.txt index c1ab36a1c2..84c88b9987 100644 --- a/Userland/Applications/DisplaySettings/CMakeLists.txt +++ b/Userland/Applications/DisplaySettings/CMakeLists.txt @@ -23,4 +23,4 @@ set(SOURCES ) serenity_app(DisplaySettings ICON app-display-settings) -target_link_libraries(DisplaySettings LibDesktop LibGUI LibConfig LibMain) +target_link_libraries(DisplaySettings LibDesktop LibGUI LibConfig LibMain LibEDID) diff --git a/Userland/Applications/DisplaySettings/MonitorSettings.gml b/Userland/Applications/DisplaySettings/MonitorSettings.gml index 653f9b8731..fc15a4d8d8 100644 --- a/Userland/Applications/DisplaySettings/MonitorSettings.gml +++ b/Userland/Applications/DisplaySettings/MonitorSettings.gml @@ -54,6 +54,13 @@ @GUI::ComboBox { name: "resolution_combo" } + + @GUI::Label { + name: "display_dpi" + text: "96 dpi" + text_alignment: "CenterMiddle" + fixed_width: 50 + } } @GUI::Widget { diff --git a/Userland/Applications/DisplaySettings/MonitorSettingsWidget.cpp b/Userland/Applications/DisplaySettings/MonitorSettingsWidget.cpp index 74ba0e84ab..079a017a70 100644 --- a/Userland/Applications/DisplaySettings/MonitorSettingsWidget.cpp +++ b/Userland/Applications/DisplaySettings/MonitorSettingsWidget.cpp @@ -7,10 +7,12 @@ #include "MonitorSettingsWidget.h" #include +#include #include #include #include #include +#include #include #include #include @@ -58,7 +60,7 @@ void MonitorSettingsWidget::create_frame() m_screen_combo->set_model(*GUI::ItemListModel::create(m_screens)); m_screen_combo->on_change = [this](auto&, const GUI::ModelIndex& index) { m_selected_screen_index = index.row(); - selected_screen_index_changed(); + selected_screen_index_or_resolution_changed(); }; m_resolution_combo = *find_descendant_of_type_named("resolution_combo"); @@ -69,8 +71,7 @@ void MonitorSettingsWidget::create_frame() selected_screen.resolution = m_resolutions.at(index.row()); // Try to auto re-arrange things if there are overlaps or disconnected screens m_screen_layout.normalize(); - m_monitor_widget->set_desktop_resolution(selected_screen.resolution); - m_monitor_widget->update(); + selected_screen_index_or_resolution_changed(); }; m_display_scale_radio_1x = *find_descendant_of_type_named("scale_1x"); @@ -95,6 +96,8 @@ void MonitorSettingsWidget::create_frame() m_monitor_widget->update(); } }; + + m_dpi_label = *find_descendant_of_type_named("display_dpi"); } void MonitorSettingsWidget::load_current_settings() @@ -110,12 +113,42 @@ void MonitorSettingsWidget::load_current_settings() } m_selected_screen_index = m_screen_layout.main_screen_index; m_screen_combo->set_selected_index(m_selected_screen_index); - selected_screen_index_changed(); + selected_screen_index_or_resolution_changed(); } -void MonitorSettingsWidget::selected_screen_index_changed() +void MonitorSettingsWidget::selected_screen_index_or_resolution_changed() { auto& screen = m_screen_layout.screens[m_selected_screen_index]; + + // Let's attempt to find the current resolution based on the screen layout settings + auto index = m_resolutions.find_first_index(screen.resolution).value_or(0); + Gfx::IntSize current_resolution = m_resolutions.at(index); + + Optional screen_dpi; + String screen_dpi_tooltip; + if (auto edid = EDID::Parser::from_framebuffer_device(screen.device, 0); !edid.is_error()) { // TODO: multihead + if (auto screen_size = edid.value().screen_size(); screen_size.has_value()) { + float x_cm = screen_size.value().horizontal_cm(); + float y_cm = screen_size.value().vertical_cm(); + float diagonal_inch = sqrtf(x_cm * x_cm + y_cm * y_cm) / 2.54f; + float diagonal_pixels = sqrtf(current_resolution.width() * current_resolution.width() + current_resolution.height() * current_resolution.height()); + if (diagonal_pixels != 0.0f) { + screen_dpi = diagonal_pixels / diagonal_inch; + screen_dpi_tooltip = String::formatted("{} inch display ({}cm x {}cm)", roundf(diagonal_inch), x_cm, y_cm); + } + } + } else { + dbgln("Error getting EDID from device {}: {}", screen.device, edid.error()); + } + + if (screen_dpi.has_value()) { + m_dpi_label->set_tooltip(screen_dpi_tooltip); + m_dpi_label->set_text(String::formatted("{} dpi", screen_dpi.value())); + m_dpi_label->set_visible(true); + } else { + m_dpi_label->set_visible(false); + } + if (screen.scale_factor != 1 && screen.scale_factor != 2) { dbgln("unexpected ScaleFactor {}, setting to 1", screen.scale_factor); screen.scale_factor = 1; @@ -123,9 +156,7 @@ void MonitorSettingsWidget::selected_screen_index_changed() (screen.scale_factor == 1 ? m_display_scale_radio_1x : m_display_scale_radio_2x)->set_checked(true); m_monitor_widget->set_desktop_scale_factor(screen.scale_factor); - // Let's attempt to find the current resolution and select it! - auto index = m_resolutions.find_first_index(screen.resolution).value_or(0); - Gfx::IntSize current_resolution = m_resolutions.at(index); + // Select the current selected resolution as it may differ m_monitor_widget->set_desktop_resolution(current_resolution); m_resolution_combo->set_selected_index(index); @@ -140,6 +171,8 @@ void MonitorSettingsWidget::apply_settings() if (m_screen_layout != current_layout) { auto result = GUI::WindowServerConnection::the().set_screen_layout(m_screen_layout, false); if (result.success()) { + load_current_settings(); // Refresh + auto box = GUI::MessageBox::construct(window(), String::formatted("Do you want to keep the new settings? They will be reverted after 10 seconds."), "Apply new screen layout", GUI::MessageBox::Type::Question, GUI::MessageBox::InputType::YesNo); box->set_icon(window()->icon()); diff --git a/Userland/Applications/DisplaySettings/MonitorSettingsWidget.h b/Userland/Applications/DisplaySettings/MonitorSettingsWidget.h index a74401e01b..909624fecb 100644 --- a/Userland/Applications/DisplaySettings/MonitorSettingsWidget.h +++ b/Userland/Applications/DisplaySettings/MonitorSettingsWidget.h @@ -39,7 +39,7 @@ private: void create_frame(); void create_resolution_list(); void load_current_settings(); - void selected_screen_index_changed(); + void selected_screen_index_or_resolution_changed(); size_t m_selected_screen_index { 0 }; @@ -52,6 +52,7 @@ private: RefPtr m_resolution_combo; RefPtr m_display_scale_radio_1x; RefPtr m_display_scale_radio_2x; + RefPtr m_dpi_label; bool m_showing_screen_numbers { false }; };