From c9cd4818c7e8e15e48f1f88e6a29af9f1a2f5182 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 6 May 2019 18:28:23 +0200 Subject: [PATCH] Improvements of High DPI scaling on Windows. --- src/slic3r/GUI/GUI_App.cpp | 16 ++++++++++------ src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/GUI_Utils.cpp | 4 +++- src/slic3r/GUI/GUI_Utils.hpp | 27 +++++++++++++++------------ src/slic3r/GUI/MainFrame.cpp | 19 ++++++++++--------- src/slic3r/GUI/Plater.cpp | 2 ++ src/slic3r/GUI/ProgressStatusBar.cpp | 1 + src/slic3r/GUI/Tab.cpp | 1 + src/slic3r/GUI/wxExtensions.cpp | 6 +++++- 9 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 47141a664..4eb6c5aa8 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -340,15 +340,19 @@ void GUI_App::init_fonts() #endif /*__WXMAC__*/ } -void GUI_App::update_fonts() +void GUI_App::update_fonts(const MainFrame *main_frame) { /* Only normal and bold fonts are used for an application rescale, * because of under MSW small and normal fonts are the same. * To avoid same rescaling twice, just fill this values * from rescaled MainFrame */ - m_normal_font = mainframe->normal_font(); - m_bold_font = mainframe->normal_font().Bold(); + if (main_frame == nullptr) + main_frame = this->mainframe; + m_normal_font = main_frame->normal_font(); + m_small_font = m_normal_font; + m_bold_font = main_frame->normal_font().Bold(); + m_em_unit = main_frame->em_unit(); } void GUI_App::set_label_clr_modified(const wxColour& clr) { @@ -773,14 +777,14 @@ void GUI_App::add_config_menu(wxMenuBar *menu) // to notify the user whether he is aware that some preset changes will be lost. bool GUI_App::check_unsaved_changes() { - std::string dirty; + wxString dirty; PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology(); for (Tab *tab : tabs_list) if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty()) if (dirty.empty()) - dirty = tab->name(); + dirty = _(tab->name()); else - dirty += std::string(", ") + tab->name(); + dirty += wxString(", ") + _(tab->name()); if (dirty.empty()) // No changes, the application may close or reload presets. return true; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 3a6a443f0..5c2ead49c 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -100,7 +100,7 @@ public: void init_label_colours(); void update_label_colours_from_appconfig(); void init_fonts(); - void update_fonts(); + void update_fonts(const MainFrame *main_frame = nullptr); void set_label_clr_modified(const wxColour& clr); void set_label_clr_sys(const wxColour& clr); diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp index 6dc5c5b4c..754e69351 100644 --- a/src/slic3r/GUI/GUI_Utils.cpp +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -64,6 +64,7 @@ template typename F::FN winapi_get_function(const wchar_t *dll, const c } #endif +// If called with nullptr, a DPI for the primary monitor is returned. int get_dpi_for_window(wxWindow *window) { #ifdef _WIN32 @@ -82,7 +83,8 @@ int get_dpi_for_window(wxWindow *window) static auto GetDpiForWindow_fn = winapi_get_function(L"User32.dll", "GetDpiForWindow"); static auto GetDpiForMonitor_fn = winapi_get_function(L"Shcore.dll", "GetDpiForMonitor"); - const HWND hwnd = window->GetHandle(); + // Desktop Window is the window of the primary monitor. + const HWND hwnd = (window == nullptr) ? ::GetDesktopWindow() : window->GetHandle(); if (GetDpiForWindow_fn != nullptr) { // We're on Windows 10, we have per-screen DPI settings diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index 25cf25b16..8cefb68d0 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -59,13 +59,16 @@ public: : P(parent, id, title, pos, size, style, name) { m_scale_factor = (float)get_dpi_for_window(this) / (float)DPI_DEFAULT; - m_normal_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + m_prev_scale_factor = m_scale_factor; + float scale_primary_display = (float)get_dpi_for_window(nullptr) / (float)DPI_DEFAULT; + m_normal_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + if (std::abs(m_scale_factor - scale_primary_display) > 1e-6) + m_normal_font = m_normal_font.Scale(m_scale_factor / scale_primary_display); + // An analog of em_unit value from GUI_App. m_em_unit = std::max(10, 10 * m_scale_factor); - m_prev_scale_factor = m_scale_factor; - - recalc_font(); +// recalc_font(); this->Bind(EVT_DPI_CHANGED, [this](const DpiChangedEvent &evt) { m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT; @@ -107,7 +110,7 @@ public: float prev_scale_factor() const { return m_prev_scale_factor; } int em_unit() const { return m_em_unit; } - int font_size() const { return m_font_size; } +// int font_size() const { return m_font_size; } const wxFont& normal_font() const { return m_normal_font; } protected: @@ -116,19 +119,19 @@ protected: private: float m_scale_factor; int m_em_unit; - int m_font_size; +// int m_font_size; wxFont m_normal_font; float m_prev_scale_factor; bool m_can_rescale{ true }; - void recalc_font() - { - wxClientDC dc(this); - const auto metrics = dc.GetFontMetrics(); - m_font_size = metrics.height; +// void recalc_font() +// { +// wxClientDC dc(this); +// const auto metrics = dc.GetFontMetrics(); +// m_font_size = metrics.height; // m_em_unit = metrics.averageWidth; - } +// } // check if new scale is differ from previous bool is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; } diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index fd63889fc..cf5cd416d 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -36,6 +36,12 @@ MainFrame::MainFrame() : DPIFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"), m_printhost_queue_dlg(new PrintHostQueueDialog(this)) { + // Fonts were created by the DPIFrame constructor for the monitor, on which the window opened. + wxGetApp().update_fonts(this); + this->SetFont(this->normal_font()); + // initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window. + wxGetApp().set_em_unit(std::max(10, GetTextExtent("m").x - 1)); + // Load the icon either from the exe, or from the ico file. #if _WIN32 { @@ -54,11 +60,6 @@ DPIFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAU SLIC3R_VERSION + _(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"))); - - // initialize default width_unit according to the width of the one symbol ("x") of the current system font - const wxSize size = GetTextExtent("m"); - wxGetApp().set_em_unit(std::max(10, size.x - 1)); - /* Load default preset bitmaps before a tabpanel initialization, * but after filling of an em_unit value */ @@ -141,6 +142,7 @@ void MainFrame::init_tabpanel() // wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10 // with multiple high resolution displays connected. m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); + m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font()); m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxEvent&) { auto panel = m_tabpanel->GetCurrentPage(); @@ -278,10 +280,9 @@ bool MainFrame::can_delete_all() const void MainFrame::on_dpi_changed(const wxRect &suggested_rect) { wxGetApp().update_fonts(); - - // _strange_ workaround for correct em_unit calculation - const int new_em_unit = scale_factor() * 10; - wxGetApp().set_em_unit(std::max(10, new_em_unit)); + this->SetFont(this->normal_font()); + // initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window. + wxGetApp().set_em_unit(std::max(10, GetTextExtent("m").x - 1)); /* Load default preset bitmaps before a tabpanel initialization, * but after filling of an em_unit value diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2d44237bd..8130990f0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1377,6 +1377,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , view_toolbar(GLToolbar::Radio) #endif // ENABLE_SVG_ICONS { + this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + arranging = false; rotoptimizing = false; background_process.set_fff_print(&fff_print); diff --git a/src/slic3r/GUI/ProgressStatusBar.cpp b/src/slic3r/GUI/ProgressStatusBar.cpp index 83c5e5b24..2f1937623 100644 --- a/src/slic3r/GUI/ProgressStatusBar.cpp +++ b/src/slic3r/GUI/ProgressStatusBar.cpp @@ -32,6 +32,7 @@ ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id): m_prog->Hide(); m_cancelbutton->Hide(); + self->SetFont(GUI::wxGetApp().normal_font()); self->SetFieldsCount(3); int w[] = {-1, 150, 155}; self->SetStatusWidths(3, w); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index add192770..b97623648 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -42,6 +42,7 @@ Tab::Tab(wxNotebook* parent, const wxString& title, const char* name) : m_parent(parent), m_title(title), m_name(name) { Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL, name); + this->SetFont(Slic3r::GUI::wxGetApp().normal_font()); set_type(); m_compatible_printers.type = Preset::TYPE_PRINTER; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 124af56ce..bb6ab1e16 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -299,9 +299,13 @@ int em_unit(wxWindow* win) { if (win) { - Slic3r::GUI::DPIDialog* dlg = dynamic_cast(Slic3r::GUI::find_toplevel_parent(win)); + wxTopLevelWindow *toplevel = Slic3r::GUI::find_toplevel_parent(win); + Slic3r::GUI::DPIDialog* dlg = dynamic_cast(toplevel); if (dlg) return dlg->em_unit(); + Slic3r::GUI::DPIFrame* frame = dynamic_cast(toplevel); + if (frame) + return frame->em_unit(); } return Slic3r::GUI::wxGetApp().em_unit();