From 567bdd9b9d4f51de1d2784664238a769e29abed5 Mon Sep 17 00:00:00 2001 From: John Beard <john.j.beard@gmail.com> Date: Fri, 22 Mar 2019 21:15:26 +0000 Subject: [PATCH] Add configuration of Hi-DPI canvas scaling in OpenGL First, add automatic detection of toolkit DPI scaling options. For now, this is, in order, * Check the GDK_SCALE option under GTK+ (users can set this to force the scaling) * Check the value from WX's GetContentScalingFactor(). This will start to work correctly from WX 3.1 and GTK+ 3.10. Then, add a user-settable override in the main prefs panel, next to the icon scaling. This is independent of the icon scaling options. DPI handling is performed in a standalone class, so they can be shared between the prefs UI and the OpenGL backend easily. Also means Cairo could use the same interface in future. Also adjust the OpenGL grid drawing code to use the computed scale factor, which avoids over-thick grids in scaled environments (the user can manually thicken the grid if wanted). Fixes: lp:1797308 * https://bugs.launchpad.net/kicad/+bug/1797308 --- common/CMakeLists.txt | 1 + common/dialogs/panel_common_settings.cpp | 112 +++-- common/dialogs/panel_common_settings.h | 14 +- common/dialogs/panel_common_settings_base.cpp | 73 ++-- common/dialogs/panel_common_settings_base.fbp | 395 ++++++++++++------ common/dialogs/panel_common_settings_base.h | 14 +- common/dpi_scaling.cpp | 178 ++++++++ common/env_vars.cpp | 35 ++ common/gal/gal_display_options.cpp | 5 +- common/gal/hidpi_gl_canvas.cpp | 35 +- common/gal/opengl/opengl_gal.cpp | 9 +- common/legacy_gal/eda_draw_frame.cpp | 11 + common/legacy_wx/eda_draw_frame.cpp | 11 + include/dpi_scaling.h | 102 +++++ include/env_vars.h | 34 +- include/gal/gal_display_options.h | 3 + include/gal/hidpi_gl_canvas.h | 16 + include/pgm_base.h | 1 + 18 files changed, 830 insertions(+), 219 deletions(-) create mode 100644 common/dpi_scaling.cpp create mode 100644 include/dpi_scaling.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index c7a2645893..e557144c50 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -295,6 +295,7 @@ set( COMMON_SRCS convert_basic_shapes_to_polygon.cpp dialog_shim.cpp displlst.cpp + dpi_scaling.cpp draw_graphic_text.cpp dsnlexer.cpp eagle_parser.cpp diff --git a/common/dialogs/panel_common_settings.cpp b/common/dialogs/panel_common_settings.cpp index 42a988a2ef..db51bf4310 100644 --- a/common/dialogs/panel_common_settings.cpp +++ b/common/dialogs/panel_common_settings.cpp @@ -21,20 +21,50 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include <pgm_base.h> -#include <dialog_shim.h> -#include <kiface_i.h> -#include <bitmap_types.h> -#include <bitmaps.h> -#include <wx/graphics.h> #include "panel_common_settings.h" -PANEL_COMMON_SETTINGS::PANEL_COMMON_SETTINGS( DIALOG_SHIM* aDialog, wxWindow* aParent ) : - PANEL_COMMON_SETTINGS_BASE( aParent ), - m_dialog( aDialog ), - m_last_scale( -1 ) +#include <bitmap_types.h> +#include <bitmaps.h> +#include <dialog_shim.h> +#include <dpi_scaling.h> +#include <kiface_i.h> +#include <pgm_base.h> + +#include <wx/graphics.h> + + +static constexpr int dpi_scaling_precision = 1; +static constexpr double dpi_scaling_increment = 0.5; + + +PANEL_COMMON_SETTINGS::PANEL_COMMON_SETTINGS( DIALOG_SHIM* aDialog, wxWindow* aParent ) + : PANEL_COMMON_SETTINGS_BASE( aParent ), + m_dialog( aDialog ), + m_last_scale( -1 ) { - m_scaleSlider->SetStep( 25 ); + m_canvasScaleCtrl->SetRange( + DPI_SCALING::GetMinScaleFactor(), DPI_SCALING::GetMaxScaleFactor() ); + m_canvasScaleCtrl->SetDigits( dpi_scaling_precision ); + m_canvasScaleCtrl->SetIncrement( dpi_scaling_increment ); + m_canvasScaleCtrl->SetValue( DPI_SCALING::GetDefaultScaleFactor() ); + + m_canvasScaleCtrl->SetToolTip( + _( "Set the scale for the canvas." + "\n\n" + "On high-DPI displays on some platforms, KiCad cannot determine the " + "scaling factor. In this case you may need to set this to a value to " + "match your system's DPI scaling. 2.0 is a common value. " + "\n\n" + "If this does not match the system DPI scaling, the canvas will " + "not match the window size and cursor position." ) ); + + m_canvasScaleAuto->SetToolTip( + _( "Use an automatic value for the canvas scale." + "\n\n" + "On some platforms, the automatic value is incorrect and should be " + "set manually." ) ); + + m_iconScaleSlider->SetStep( 25 ); m_textEditorBtn->SetBitmap( KiBitmap( folder_xpm ) ); m_pdfViewerBtn->SetBitmap( KiBitmap( folder_xpm ) ); @@ -63,18 +93,24 @@ bool PANEL_COMMON_SETTINGS::TransferDataToWindow() commonSettings->Read( CAIRO_ANTIALIASING_MODE_KEY, &antialiasingMode, 0 ); m_antialiasingFallback->SetSelection( antialiasingMode ); - int scale_fourths; - commonSettings->Read( ICON_SCALE_KEY, &scale_fourths ); + int icon_scale_fourths; + commonSettings->Read( ICON_SCALE_KEY, &icon_scale_fourths ); - if( scale_fourths <= 0 ) + if( icon_scale_fourths <= 0 ) { - m_scaleAuto->SetValue( true ); - m_scaleSlider->SetValue( 25 * KiIconScale( GetParent() ) ); + m_iconScaleAuto->SetValue( true ); + m_iconScaleSlider->SetValue( 25 * KiIconScale( GetParent() ) ); } else { - m_scaleAuto->SetValue( false ); - m_scaleSlider->SetValue( scale_fourths * 25 ); + m_iconScaleAuto->SetValue( false ); + m_iconScaleSlider->SetValue( icon_scale_fourths * 25 ); + } + + { + const DPI_SCALING dpi( commonSettings, this ); + m_canvasScaleCtrl->SetValue( dpi.GetScaleFactor() ); + m_canvasScaleAuto->SetValue( dpi.GetCanvasIsAutoScaled() ); } bool option; @@ -111,9 +147,14 @@ bool PANEL_COMMON_SETTINGS::TransferDataFromWindow() commonSettings->Write( CAIRO_ANTIALIASING_MODE_KEY, m_antialiasingFallback->GetSelection() ); - const int scale_fourths = m_scaleAuto->GetValue() ? -1 : m_scaleSlider->GetValue() / 25; + const int scale_fourths = m_iconScaleAuto->GetValue() ? -1 : m_iconScaleSlider->GetValue() / 25; commonSettings->Write( ICON_SCALE_KEY, scale_fourths ); + { + DPI_SCALING dpi( commonSettings, this ); + dpi.SetDpiConfig( m_canvasScaleAuto->GetValue(), m_canvasScaleCtrl->GetValue() ); + } + commonSettings->Write( USE_ICONS_IN_MENUS_KEY, m_checkBoxIconsInMenus->GetValue() ); commonSettings->Write( ENBL_ZOOM_NO_CENTER_KEY, !m_ZoomCenterOpt->GetValue() ); commonSettings->Write( ENBL_MOUSEWHEEL_PAN_KEY, m_MousewheelPANOpt->GetValue() ); @@ -131,21 +172,42 @@ bool PANEL_COMMON_SETTINGS::TransferDataFromWindow() void PANEL_COMMON_SETTINGS::OnScaleSlider( wxScrollEvent& aEvent ) { - m_scaleAuto->SetValue( false ); + m_iconScaleAuto->SetValue( false ); } -void PANEL_COMMON_SETTINGS::OnScaleAuto( wxCommandEvent& aEvent ) +void PANEL_COMMON_SETTINGS::OnIconScaleAuto( wxCommandEvent& aEvent ) { - if( m_scaleAuto->GetValue() ) + if( m_iconScaleAuto->GetValue() ) { - m_last_scale = m_scaleSlider->GetValue(); - m_scaleSlider->SetValue( 25 * KiIconScale( GetParent() ) ); + m_last_scale = m_iconScaleAuto->GetValue(); + m_iconScaleSlider->SetValue( 25 * KiIconScale( GetParent() ) ); } else { if( m_last_scale >= 0 ) - m_scaleSlider->SetValue( m_last_scale ); + m_iconScaleSlider->SetValue( m_last_scale ); + } +} + + +void PANEL_COMMON_SETTINGS::OnCanvasScaleChange( wxCommandEvent& aEvent ) +{ + m_canvasScaleAuto->SetValue( false ); +} + + +void PANEL_COMMON_SETTINGS::OnCanvasScaleAuto( wxCommandEvent& aEvent ) +{ + const bool automatic = m_canvasScaleAuto->GetValue(); + + if( automatic ) + { + // set the scale to the auto value, without consulting the config + DPI_SCALING dpi( nullptr, this ); + + // update the field (no events sent) + m_canvasScaleCtrl->SetValue( dpi.GetScaleFactor() ); } } diff --git a/common/dialogs/panel_common_settings.h b/common/dialogs/panel_common_settings.h index 40dbd37f95..0a96f48ad0 100644 --- a/common/dialogs/panel_common_settings.h +++ b/common/dialogs/panel_common_settings.h @@ -40,10 +40,20 @@ protected: bool TransferDataToWindow() override; void OnScaleSlider( wxScrollEvent& aEvent ) override; - void OnScaleAuto( wxCommandEvent& aEvent ) override; + void OnIconScaleAuto( wxCommandEvent& aEvent ) override; void OnTextEditorClick( wxCommandEvent& event ) override; void OnPDFViewerClick( wxCommandEvent& event ) override; - void onUpdateUIPdfPath( wxUpdateUIEvent& event ) override; + void onUpdateUIPdfPath( wxUpdateUIEvent& event ) override; + + /** + * Event fired when the canvas scale field is modified + */ + void OnCanvasScaleChange( wxCommandEvent& aEvent ) override; + + /** + * Event fired when the canvas auto-scale option is changed + */ + void OnCanvasScaleAuto( wxCommandEvent& aEvent ) override; DIALOG_SHIM* m_dialog; diff --git a/common/dialogs/panel_common_settings_base.cpp b/common/dialogs/panel_common_settings_base.cpp index ee2053f68d..9731b83a41 100644 --- a/common/dialogs/panel_common_settings_base.cpp +++ b/common/dialogs/panel_common_settings_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jan 5 2019) +// C++ code generated with wxFormBuilder (version Nov 10 2018) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -136,25 +136,26 @@ PANEL_COMMON_SETTINGS_BASE::PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWind m_staticTexticonscale = new wxStaticText( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Icon scale:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTexticonscale->Wrap( -1 ); - fgSizer11->Add( m_staticTexticonscale, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 4 ); + fgSizer11->Add( m_staticTexticonscale, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 4 ); - wxBoxSizer* bSizer4; - bSizer4 = new wxBoxSizer( wxHORIZONTAL ); + m_iconScaleSlider = new STEPPED_SLIDER( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, 50, 50, 275, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL|wxSL_LABELS ); + m_iconScaleSlider->SetMinSize( wxSize( 240,-1 ) ); - m_scaleSlider = new STEPPED_SLIDER( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, 50, 50, 275, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL|wxSL_LABELS ); - m_scaleSlider->SetMinSize( wxSize( 240,-1 ) ); + fgSizer11->Add( m_iconScaleSlider, 1, wxBOTTOM|wxEXPAND, 4 ); - bSizer4->Add( m_scaleSlider, 1, wxBOTTOM|wxEXPAND, 4 ); + m_iconScaleAuto = new wxCheckBox( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Automatic"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer11->Add( m_iconScaleAuto, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 25 ); - m_staticTextPerCent = new wxStaticText( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("%"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextPerCent->Wrap( -1 ); - bSizer4->Add( m_staticTextPerCent, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); + m_staticTextCanvasScale = new wxStaticText( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Canvas scale:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCanvasScale->Wrap( -1 ); + fgSizer11->Add( m_staticTextCanvasScale, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_canvasScaleCtrl = new wxSpinCtrlDouble( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100, 0, 1 ); + m_canvasScaleCtrl->SetDigits( 0 ); + fgSizer11->Add( m_canvasScaleCtrl, 0, wxALL|wxEXPAND, 5 ); - fgSizer11->Add( bSizer4, 1, wxEXPAND, 5 ); - - m_scaleAuto = new wxCheckBox( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Automatic"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer11->Add( m_scaleAuto, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 25 ); + m_canvasScaleAuto = new wxCheckBox( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Automatic"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer11->Add( m_canvasScaleAuto, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 25 ); fgSizer11->Add( 0, 0, 0, wxEXPAND, 5 ); @@ -202,16 +203,18 @@ PANEL_COMMON_SETTINGS_BASE::PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWind m_PDFViewerPath->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_COMMON_SETTINGS_BASE::onUpdateUIPdfPath ), NULL, this ); m_pdfViewerBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnPDFViewerClick ), NULL, this ); m_pdfViewerBtn->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_COMMON_SETTINGS_BASE::onUpdateUIPdfPath ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_TOP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_BOTTOM, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_LINEUP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_LINEDOWN, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_PAGEUP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_THUMBRELEASE, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Connect( wxEVT_SCROLL_CHANGED, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleAuto->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleAuto ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_TOP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_BOTTOM, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_LINEUP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_LINEDOWN, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_PAGEUP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_THUMBRELEASE, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Connect( wxEVT_SCROLL_CHANGED, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleAuto->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnIconScaleAuto ), NULL, this ); + m_canvasScaleCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnCanvasScaleChange ), NULL, this ); + m_canvasScaleAuto->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnCanvasScaleAuto ), NULL, this ); } PANEL_COMMON_SETTINGS_BASE::~PANEL_COMMON_SETTINGS_BASE() @@ -221,15 +224,17 @@ PANEL_COMMON_SETTINGS_BASE::~PANEL_COMMON_SETTINGS_BASE() m_PDFViewerPath->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_COMMON_SETTINGS_BASE::onUpdateUIPdfPath ), NULL, this ); m_pdfViewerBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnPDFViewerClick ), NULL, this ); m_pdfViewerBtn->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_COMMON_SETTINGS_BASE::onUpdateUIPdfPath ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_TOP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_BOTTOM, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_LINEUP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_LINEDOWN, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_PAGEUP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_THUMBRELEASE, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleSlider->Disconnect( wxEVT_SCROLL_CHANGED, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); - m_scaleAuto->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleAuto ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_TOP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_BOTTOM, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_LINEUP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_LINEDOWN, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_PAGEUP, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_THUMBRELEASE, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleSlider->Disconnect( wxEVT_SCROLL_CHANGED, wxScrollEventHandler( PANEL_COMMON_SETTINGS_BASE::OnScaleSlider ), NULL, this ); + m_iconScaleAuto->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnIconScaleAuto ), NULL, this ); + m_canvasScaleCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnCanvasScaleChange ), NULL, this ); + m_canvasScaleAuto->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_COMMON_SETTINGS_BASE::OnCanvasScaleAuto ), NULL, this ); } diff --git a/common/dialogs/panel_common_settings_base.fbp b/common/dialogs/panel_common_settings_base.fbp index 5ffa9864bb..8e246ec5e5 100644 --- a/common/dialogs/panel_common_settings_base.fbp +++ b/common/dialogs/panel_common_settings_base.fbp @@ -1219,7 +1219,7 @@ <property name="vgap">0</property> <object class="sizeritem" expanded="0"> <property name="border">4</property> - <property name="flag">wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property> <property name="proportion">0</property> <object class="wxStaticText" expanded="0"> <property name="BottomDockable">1</property> @@ -1278,142 +1278,70 @@ <property name="wrap">-1</property> </object> </object> - <object class="sizeritem" expanded="1"> - <property name="border">5</property> - <property name="flag">wxEXPAND</property> + <object class="sizeritem" expanded="0"> + <property name="border">4</property> + <property name="flag">wxBOTTOM|wxEXPAND</property> <property name="proportion">1</property> - <object class="wxBoxSizer" expanded="1"> - <property name="minimum_size"></property> - <property name="name">bSizer4</property> - <property name="orient">wxHORIZONTAL</property> - <property name="permission">none</property> - <object class="sizeritem" expanded="0"> - <property name="border">4</property> - <property name="flag">wxBOTTOM|wxEXPAND</property> - <property name="proportion">1</property> - <object class="wxSlider" expanded="0"> - <property name="BottomDockable">1</property> - <property name="LeftDockable">1</property> - <property name="RightDockable">1</property> - <property name="TopDockable">1</property> - <property name="aui_layer"></property> - <property name="aui_name"></property> - <property name="aui_position"></property> - <property name="aui_row"></property> - <property name="best_size"></property> - <property name="bg"></property> - <property name="caption"></property> - <property name="caption_visible">1</property> - <property name="center_pane">0</property> - <property name="close_button">1</property> - <property name="context_help"></property> - <property name="context_menu">1</property> - <property name="default_pane">0</property> - <property name="dock">Dock</property> - <property name="dock_fixed">0</property> - <property name="docking">Left</property> - <property name="enabled">1</property> - <property name="fg"></property> - <property name="floatable">1</property> - <property name="font"></property> - <property name="gripper">0</property> - <property name="hidden">0</property> - <property name="id">wxID_ANY</property> - <property name="maxValue">275</property> - <property name="max_size"></property> - <property name="maximize_button">0</property> - <property name="maximum_size"></property> - <property name="minValue">50</property> - <property name="min_size"></property> - <property name="minimize_button">0</property> - <property name="minimum_size">240,-1</property> - <property name="moveable">1</property> - <property name="name">m_scaleSlider</property> - <property name="pane_border">1</property> - <property name="pane_position"></property> - <property name="pane_size"></property> - <property name="permission">protected</property> - <property name="pin_button">1</property> - <property name="pos"></property> - <property name="resize">Resizable</property> - <property name="show">1</property> - <property name="size"></property> - <property name="style">wxSL_HORIZONTAL|wxSL_LABELS</property> - <property name="subclass">STEPPED_SLIDER; widgets/stepped_slider.h; Not forward_declare</property> - <property name="toolbar_pane">0</property> - <property name="tooltip"></property> - <property name="validator_data_type"></property> - <property name="validator_style">wxFILTER_NONE</property> - <property name="validator_type">wxDefaultValidator</property> - <property name="validator_variable"></property> - <property name="value">50</property> - <property name="window_extra_style"></property> - <property name="window_name"></property> - <property name="window_style"></property> - <event name="OnScroll">OnScaleSlider</event> - </object> - </object> - <object class="sizeritem" expanded="0"> - <property name="border">2</property> - <property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property> - <property name="proportion">0</property> - <object class="wxStaticText" expanded="0"> - <property name="BottomDockable">1</property> - <property name="LeftDockable">1</property> - <property name="RightDockable">1</property> - <property name="TopDockable">1</property> - <property name="aui_layer"></property> - <property name="aui_name"></property> - <property name="aui_position"></property> - <property name="aui_row"></property> - <property name="best_size"></property> - <property name="bg"></property> - <property name="caption"></property> - <property name="caption_visible">1</property> - <property name="center_pane">0</property> - <property name="close_button">1</property> - <property name="context_help"></property> - <property name="context_menu">1</property> - <property name="default_pane">0</property> - <property name="dock">Dock</property> - <property name="dock_fixed">0</property> - <property name="docking">Left</property> - <property name="enabled">1</property> - <property name="fg"></property> - <property name="floatable">1</property> - <property name="font"></property> - <property name="gripper">0</property> - <property name="hidden">0</property> - <property name="id">wxID_ANY</property> - <property name="label">%</property> - <property name="markup">0</property> - <property name="max_size"></property> - <property name="maximize_button">0</property> - <property name="maximum_size"></property> - <property name="min_size"></property> - <property name="minimize_button">0</property> - <property name="minimum_size"></property> - <property name="moveable">1</property> - <property name="name">m_staticTextPerCent</property> - <property name="pane_border">1</property> - <property name="pane_position"></property> - <property name="pane_size"></property> - <property name="permission">protected</property> - <property name="pin_button">1</property> - <property name="pos"></property> - <property name="resize">Resizable</property> - <property name="show">1</property> - <property name="size"></property> - <property name="style"></property> - <property name="subclass">; forward_declare</property> - <property name="toolbar_pane">0</property> - <property name="tooltip"></property> - <property name="window_extra_style"></property> - <property name="window_name"></property> - <property name="window_style"></property> - <property name="wrap">-1</property> - </object> - </object> + <object class="wxSlider" expanded="0"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maxValue">275</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="minValue">50</property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size">240,-1</property> + <property name="moveable">1</property> + <property name="name">m_iconScaleSlider</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxSL_HORIZONTAL|wxSL_LABELS</property> + <property name="subclass">STEPPED_SLIDER; widgets/stepped_slider.h; Not forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value">50</property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnScroll">OnScaleSlider</event> </object> </object> <object class="sizeritem" expanded="0"> @@ -1457,7 +1385,7 @@ <property name="minimize_button">0</property> <property name="minimum_size"></property> <property name="moveable">1</property> - <property name="name">m_scaleAuto</property> + <property name="name">m_iconScaleAuto</property> <property name="pane_border">1</property> <property name="pane_position"></property> <property name="pane_size"></property> @@ -1478,7 +1406,198 @@ <property name="window_extra_style"></property> <property name="window_name"></property> <property name="window_style"></property> - <event name="OnCheckBox">OnScaleAuto</event> + <event name="OnCheckBox">OnIconScaleAuto</event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Canvas scale:</property> + <property name="markup">0</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticTextCanvasScale</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <property name="wrap">-1</property> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxSpinCtrlDouble" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="digits">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="inc">1</property> + <property name="initial">0</property> + <property name="max">100</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min">0</property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_canvasScaleCtrl</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxSP_ARROW_KEYS</property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="value"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnSpinCtrlText">OnCanvasScaleChange</event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">25</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Automatic</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_canvasScaleAuto</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnCheckBox">OnCanvasScaleAuto</event> </object> </object> <object class="sizeritem" expanded="0"> diff --git a/common/dialogs/panel_common_settings_base.h b/common/dialogs/panel_common_settings_base.h index a0fc37df5f..6bf69116fc 100644 --- a/common/dialogs/panel_common_settings_base.h +++ b/common/dialogs/panel_common_settings_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jan 5 2019) +// C++ code generated with wxFormBuilder (version Nov 10 2018) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -61,9 +61,11 @@ class PANEL_COMMON_SETTINGS_BASE : public wxPanel wxTextCtrl* m_PDFViewerPath; wxBitmapButton* m_pdfViewerBtn; wxStaticText* m_staticTexticonscale; - STEPPED_SLIDER* m_scaleSlider; - wxStaticText* m_staticTextPerCent; - wxCheckBox* m_scaleAuto; + STEPPED_SLIDER* m_iconScaleSlider; + wxCheckBox* m_iconScaleAuto; + wxStaticText* m_staticTextCanvasScale; + wxSpinCtrlDouble* m_canvasScaleCtrl; + wxCheckBox* m_canvasScaleAuto; wxCheckBox* m_checkBoxIconsInMenus; wxCheckBox* m_ZoomCenterOpt; wxCheckBox* m_MousewheelPANOpt; @@ -74,7 +76,9 @@ class PANEL_COMMON_SETTINGS_BASE : public wxPanel virtual void onUpdateUIPdfPath( wxUpdateUIEvent& event ) { event.Skip(); } virtual void OnPDFViewerClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnScaleSlider( wxScrollEvent& event ) { event.Skip(); } - virtual void OnScaleAuto( wxCommandEvent& event ) { event.Skip(); } + virtual void OnIconScaleAuto( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCanvasScaleChange( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCanvasScaleAuto( wxCommandEvent& event ) { event.Skip(); } public: diff --git a/common/dpi_scaling.cpp b/common/dpi_scaling.cpp new file mode 100644 index 0000000000..bdd27d540b --- /dev/null +++ b/common/dpi_scaling.cpp @@ -0,0 +1,178 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2019 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program 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 Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <dpi_scaling.h> + +#include <core/optional.h> + +#include <env_vars.h> +#include <pgm_base.h> + +#include <wx/config.h> +#include <wx/log.h> + + +/** + * Flag to enable trace for HiDPI scaling factors + * + * Use "KICAD_TRACE_HIGH_DPI" to enable. + * + * @ingroup trace_env_vars + */ +const wxChar* const traceHiDpi = wxT( "KICAD_TRACE_HIGH_DPI" ); + + +/** + * Get a user-configured scale factor from KiCad config file + * + * @return the scale factor, if set + */ +static OPT<double> getKiCadConfiguredScale( const wxConfigBase& aConfig ) +{ + OPT<double> scale; + double canvas_scale = 0.0; + aConfig.Read( CANVAS_SCALE_KEY, &canvas_scale, 0.0 ); + + if( canvas_scale > 0.0 ) + { + scale = canvas_scale; + } + + if( scale ) + { + wxLogTrace( traceHiDpi, "Scale factor (configured): %f", *scale ); + } + + return scale; +} + + +/** + * Get the toolkit scale factor from a user-set environment variable + * (for example GDK_SCALE on GTK). + * + * @return the scale factor, if set + */ +static OPT<double> getEnviromentScale() +{ + const wxPortId port_id = wxPlatformInfo::Get().GetPortId(); + OPT<double> scale; + + if( port_id == wxPORT_GTK ) + { + // Under GTK, the user can use GDK_SCALE to force the scaling + scale = GetEnvVar<double>( "GDK_SCALE" ); + } + + if( scale ) + { + wxLogTrace( traceHiDpi, "Scale factor (environment): %f", *scale ); + } + + return scale; +} + + +DPI_SCALING::DPI_SCALING( wxConfigBase* aConfig, const wxWindow* aWindow ) + : m_config( aConfig ), m_window( aWindow ) +{ +} + + +double DPI_SCALING::GetScaleFactor() const +{ + OPT<double> val; + + if( m_config ) + { + val = getKiCadConfiguredScale( *m_config ); + } + + if( !val ) + { + val = getEnviromentScale(); + } + + if( !val && m_window ) + { + // Use the native WX reporting. + // On Linux, this will not work until WX 3.2 and GTK >= 3.10 + // Otherwise it returns 1.0 + val = m_window->GetContentScaleFactor(); + wxLogTrace( traceHiDpi, "Scale factor (WX): %f", *val ); + } + + if( !val ) + { + // Nothing else we can do, give it a default value + val = GetDefaultScaleFactor(); + wxLogTrace( traceHiDpi, "Scale factor (default): %f", *val ); + } + + return *val; +} + + +bool DPI_SCALING::GetCanvasIsAutoScaled() const +{ + if( m_config == nullptr ) + { + // No configuration given, so has to be automatic scaling + return true; + } + + const bool automatic = getKiCadConfiguredScale( *m_config ) == boost::none; + wxLogTrace( traceHiDpi, "Scale is automatic: %d", automatic ); + return automatic; +} + + +void DPI_SCALING::SetDpiConfig( bool aAuto, double aValue ) +{ + wxCHECK_RET( m_config != nullptr, "Setting DPI config without a config store." ); + + const double value = aAuto ? 0.0 : aValue; + + m_config->Write( CANVAS_SCALE_KEY, value ); +} + + +double DPI_SCALING::GetMaxScaleFactor() +{ + // displays with higher than 4.0 DPI are not really going to be useful + // for KiCad (even an 8k display would be effectively only ~1080p at 4x) + return 6.0; +} + + +double DPI_SCALING::GetMinScaleFactor() +{ + // scales under 1.0 don't make sense from a HiDPI perspective + return 1.0; +} + +double DPI_SCALING::GetDefaultScaleFactor() +{ + // no scaling => 1.0 + return 1.0; +} \ No newline at end of file diff --git a/common/env_vars.cpp b/common/env_vars.cpp index ee51087eda..83baa5e909 100644 --- a/common/env_vars.cpp +++ b/common/env_vars.cpp @@ -23,6 +23,8 @@ #include <common.h> +#include <wx/utils.h> + using STRING_MAP = std::map<wxString, wxString>; /* @@ -102,4 +104,37 @@ wxString LookUpEnvVarHelp( const wxString& aEnvVar ) initialiseEnvVarHelp( env_var_help_text ); return env_var_help_text[aEnvVar]; +} + + +template<> +OPT<double> GetEnvVar( const wxString& aEnvVarName ) +{ + OPT<double> opt_value; + + wxString env; + if( wxGetEnv( aEnvVarName, &env ) ) + { + double value; + if( env.ToDouble( &value ) ) + { + opt_value = value; + } + } + + return opt_value; +} + +template<> +OPT<wxString> GetEnvVar( const wxString& aEnvVarName ) +{ + OPT<wxString> opt_value; + + wxString env; + if( wxGetEnv( aEnvVarName, &env ) ) + { + opt_value = env; + } + + return opt_value; } \ No newline at end of file diff --git a/common/gal/gal_display_options.cpp b/common/gal/gal_display_options.cpp index 0c9a43a51d..3b4be00757 100644 --- a/common/gal/gal_display_options.cpp +++ b/common/gal/gal_display_options.cpp @@ -22,9 +22,11 @@ */ #include <gal/gal_display_options.h> + #include <wx/config.h> #include <config_map.h> +#include <dpi_scaling.h> using namespace KIGFX; @@ -55,7 +57,8 @@ GAL_DISPLAY_OPTIONS::GAL_DISPLAY_OPTIONS() m_gridMinSpacing( 10.0 ), m_axesEnabled( false ), m_fullscreenCursor( false ), - m_forceDisplayCursor( false ) + m_forceDisplayCursor( false ), + m_scaleFactor( DPI_SCALING::GetDefaultScaleFactor() ) {} diff --git a/common/gal/hidpi_gl_canvas.cpp b/common/gal/hidpi_gl_canvas.cpp index f1404b99c5..fcc0807bf4 100644 --- a/common/gal/hidpi_gl_canvas.cpp +++ b/common/gal/hidpi_gl_canvas.cpp @@ -26,16 +26,14 @@ #include <gal/hidpi_gl_canvas.h> +#include <dpi_scaling.h> -HIDPI_GL_CANVAS::HIDPI_GL_CANVAS( wxWindow *parent, - wxWindowID id, - const int *attribList, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name, - const wxPalette& palette ) : - wxGLCanvas( parent, id, attribList, pos, size, style, name, palette ) + +HIDPI_GL_CANVAS::HIDPI_GL_CANVAS( wxWindow* parent, wxWindowID id, const int* attribList, + const wxPoint& pos, const wxSize& size, long style, const wxString& name, + const wxPalette& palette ) + : wxGLCanvas( parent, id, attribList, pos, size, style, name, palette ), + m_scale_factor( DPI_SCALING::GetDefaultScaleFactor() ) { #ifdef RETINA_OPENGL_PATCH SetViewWantsBestResolution( true ); @@ -47,15 +45,14 @@ wxSize HIDPI_GL_CANVAS::GetNativePixelSize() const { wxSize size = wxGLCanvas::GetClientSize(); -#ifdef RETINA_OPENGL_PATCH const float scaleFactor = GetBackingScaleFactor(); size.x *= scaleFactor; size.y *= scaleFactor; -#endif return size; } + float HIDPI_GL_CANVAS::GetBackingScaleFactor() const { #ifdef RETINA_OPENGL_PATCH @@ -63,6 +60,20 @@ float HIDPI_GL_CANVAS::GetBackingScaleFactor() const // => clean up when it officially has arrived in wxWidgets return static_cast< wxGLCanvas* >( const_cast< HIDPI_GL_CANVAS* >( this ))->GetBackingScaleFactor(); #else - return 1.0f; + + // Return the cached value (which originally was set from config or automatically) + return m_scale_factor; #endif } + + +void HIDPI_GL_CANVAS::SetScaleFactor( double aNewScaleFactor ) +{ + m_scale_factor = aNewScaleFactor; +} + + +double HIDPI_GL_CANVAS::GetScaleFactor() const +{ + return m_scale_factor; +} \ No newline at end of file diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 9c4215e9c4..fc34b4e495 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -336,6 +336,12 @@ bool OPENGL_GAL::updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions ) refresh = true; } + if( options.m_scaleFactor != GetScaleFactor() ) + { + SetScaleFactor( options.m_scaleFactor ); + refresh = true; + } + if( super::updatedGalDisplayOptions( aOptions ) || refresh ) { Refresh(); @@ -1224,7 +1230,8 @@ void OPENGL_GAL::DrawGrid() nonCachedManager->EnableDepthTest( false ); // sub-pixel lines all render the same - float minorLineWidth = std::fmax( 1.0f, gridLineWidth ) * getWorldPixelSize(); + float minorLineWidth = + std::fmax( 1.0f, gridLineWidth ) * getWorldPixelSize() / GetBackingScaleFactor(); float majorLineWidth = minorLineWidth * 2.0f; // Draw the axis and grid diff --git a/common/legacy_gal/eda_draw_frame.cpp b/common/legacy_gal/eda_draw_frame.cpp index fa1eec228b..9a32d22d6e 100644 --- a/common/legacy_gal/eda_draw_frame.cpp +++ b/common/legacy_gal/eda_draw_frame.cpp @@ -67,6 +67,7 @@ #include <page_info.h> #include <title_block.h> #include <advanced_config.h> +#include <dpi_scaling.h> /** * Definition for enabling and disabling scroll bar setting trace output. See the @@ -301,6 +302,11 @@ void EDA_DRAW_FRAME::CommonSettingsChanged() settings->Read( CAIRO_ANTIALIASING_MODE_KEY, &tmp, (int) KIGFX::CAIRO_ANTIALIASING_MODE::NONE ); m_galDisplayOptions.cairo_antialiasing_mode = (KIGFX::CAIRO_ANTIALIASING_MODE) tmp; + { + const DPI_SCALING dpi{ settings, this }; + m_galDisplayOptions.m_scaleFactor = dpi.GetScaleFactor(); + } + m_galDisplayOptions.NotifyChanged(); } @@ -852,6 +858,11 @@ void EDA_DRAW_FRAME::LoadSettings( wxConfigBase* aCfg ) cmnCfg->Read( CAIRO_ANTIALIASING_MODE_KEY, &temp, (int) KIGFX::CAIRO_ANTIALIASING_MODE::NONE ); m_galDisplayOptions.cairo_antialiasing_mode = (KIGFX::CAIRO_ANTIALIASING_MODE) temp; + { + const DPI_SCALING dpi{ cmnCfg, this }; + m_galDisplayOptions.m_scaleFactor = dpi.GetScaleFactor(); + } + m_galDisplayOptions.NotifyChanged(); } diff --git a/common/legacy_wx/eda_draw_frame.cpp b/common/legacy_wx/eda_draw_frame.cpp index 8702c30315..6e73422712 100644 --- a/common/legacy_wx/eda_draw_frame.cpp +++ b/common/legacy_wx/eda_draw_frame.cpp @@ -46,6 +46,7 @@ #include <math/box2.h> #include <lockfile.h> #include <trace_helpers.h> +#include <dpi_scaling.h> #include <wx/clipbrd.h> #include <fctsys.h> @@ -303,6 +304,11 @@ void EDA_DRAW_FRAME::CommonSettingsChanged() settings->Read( CAIRO_ANTIALIASING_MODE_KEY, &tmp, (int) KIGFX::CAIRO_ANTIALIASING_MODE::NONE ); m_galDisplayOptions.cairo_antialiasing_mode = (KIGFX::CAIRO_ANTIALIASING_MODE) tmp; + { + const DPI_SCALING dpi{ settings, this }; + m_galDisplayOptions.m_scaleFactor = dpi.GetScaleFactor(); + } + m_galDisplayOptions.NotifyChanged(); } @@ -871,6 +877,11 @@ void EDA_DRAW_FRAME::LoadSettings( wxConfigBase* aCfg ) cmnCfg->Read( CAIRO_ANTIALIASING_MODE_KEY, &temp, (int) KIGFX::CAIRO_ANTIALIASING_MODE::NONE ); m_galDisplayOptions.cairo_antialiasing_mode = (KIGFX::CAIRO_ANTIALIASING_MODE) temp; + { + const DPI_SCALING dpi{ cmnCfg, this }; + m_galDisplayOptions.m_scaleFactor = dpi.GetScaleFactor(); + } + m_galDisplayOptions.NotifyChanged(); } diff --git a/include/dpi_scaling.h b/include/dpi_scaling.h new file mode 100644 index 0000000000..b81e982817 --- /dev/null +++ b/include/dpi_scaling.h @@ -0,0 +1,102 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2019 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program 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 Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef DPI_SCALING__H +#define DPI_SCALING__H + +#include <wx/config.h> +#include <wx/window.h> + +/** + * Class to handle configuration and automatic determination of the DPI + * scale to use for canvases. This has several sources and the availability of + * some of them are platform dependent. + */ +class DPI_SCALING +{ +public: + /** + * Construct a DPI scale provider. + * + * @param aConfig the config store to check for a user value (can be nullptr, + * in which case on automatically determined values are considered) + * @param aWindow a WX window to use for automatic DPI determination + * @return the scaling factor (1.0 = no scaling) + */ + DPI_SCALING( wxConfigBase* aConfig, const wxWindow* aWindow ); + + /** + * Get the DPI scale from all known sources in order: + * + * * user config, if given + * * user's environment variables, if set and according to platform + * * WX's internal determination of the DPI scaling (WX > 3.1) + */ + double GetScaleFactor() const; + + /** + * Is the current value auto scaled, or is it user-set in the config + */ + bool GetCanvasIsAutoScaled() const; + + /** + * Set the common DPI config in a given config object + * + * The encoding of the automatic/manual nature of the config is handled internally. + * + * @param aAuto store a value meaning "no user-set scale" + * @param aValue the value to store (ignored if aAuto set) + */ + void SetDpiConfig( bool aAuto, double aValue ); + + /* + * Get the maximum scaling factor that should be presented to the user. + * This is only advisory, it has no real technical use other than for validation. + */ + static double GetMaxScaleFactor(); + + /* + * Get the minimum scaling factor that should be presented to the user. + * This is only advisory, it has no real technical use other than for validation. + */ + static double GetMinScaleFactor(); + + /** + * Get the "default" scaling factor to use if not other config is available + */ + static double GetDefaultScaleFactor(); + +private: + /** + * The configuration object to use to get/set user setting. nullptr + * if only automatic options are wanted + */ + wxConfigBase* m_config; + + /** + * The WX window to use for WX's automatic DPI checking + */ + const wxWindow* m_window; +}; + +#endif // DPI_SCALING__H \ No newline at end of file diff --git a/include/env_vars.h b/include/env_vars.h index cec25c2e04..d2200a4c2a 100644 --- a/include/env_vars.h +++ b/include/env_vars.h @@ -19,15 +19,18 @@ /** * @file env_vars.h - * Functions to provide helpful hints about what environment vars do + * Functions related to environment variables, including help functions */ #ifndef ENV_VARS_H #define ENV_VARS_H #include <wx/string.h> + #include <vector> +#include <core/optional.h> + using ENV_VAR_LIST = std::vector<wxString>; /** @@ -56,4 +59,33 @@ const ENV_VAR_LIST& GetPredefinedEnvVars(); */ wxString LookUpEnvVarHelp( const wxString& aEnvVar ); +/** + * Get an environment variable as a specific type, if set correctly + * + * @param aEnvVarName the name of the environment variable + * @return an OPT containing the value, if set and parseable, otherwise empty. + */ +template <typename VAL_TYPE> +OPT<VAL_TYPE> GetEnvVar( const wxString& aEnvVarName ); + +/** + * Get a string environment variable, if it is set. + * + * @param aEnvVarName the name of the environment variable + * @return an OPT containing the value, if set, otherwise empty. + */ +template<> +OPT<wxString> GetEnvVar( const wxString& aEnvVarName ); + +/** + * Get a double from an environment variable, if set + * + * @param aEnvVarName the name of the environment variable + * @return an OPT containing the value, if set and parseable as a double, + * otherwise empty. + */ +template <> +OPT<double> GetEnvVar( const wxString& aEnvVarName ); + + #endif /* ENV_VARS_H */ diff --git a/include/gal/gal_display_options.h b/include/gal/gal_display_options.h index 0b592d7a32..44bf3c0a7c 100644 --- a/include/gal/gal_display_options.h +++ b/include/gal/gal_display_options.h @@ -100,6 +100,9 @@ namespace KIGFX ///> Force cursor display bool m_forceDisplayCursor; + + ///> The pixel scale factor (>1 for hi-DPI scaled displays) + double m_scaleFactor; }; } diff --git a/include/gal/hidpi_gl_canvas.h b/include/gal/hidpi_gl_canvas.h index e8ed4c3f95..ebe3a789a9 100644 --- a/include/gal/hidpi_gl_canvas.h +++ b/include/gal/hidpi_gl_canvas.h @@ -53,6 +53,22 @@ public: virtual wxSize GetNativePixelSize() const; virtual float GetBackingScaleFactor() const; + + /** + * Set the canvas scale factor, probably for a hi-DPI display. + */ + void SetScaleFactor( double aFactor ); + + /** + * Get the current scale factor + */ + double GetScaleFactor() const; + +private: + /** + * The current scale factor (e.g. for hi-DPI displays) + */ + double m_scale_factor; }; #endif // HIDPI_GL_CANVAS_H diff --git a/include/pgm_base.h b/include/pgm_base.h index 05cecd00f5..b03c1e62ec 100644 --- a/include/pgm_base.h +++ b/include/pgm_base.h @@ -44,6 +44,7 @@ #define USE_ICONS_IN_MENUS_KEY wxT( "UseIconsInMenus" ) #define ICON_SCALE_KEY wxT( "IconScale" ) +#define CANVAS_SCALE_KEY wxT( "CanvasScale" ) #define AUTOSAVE_INTERVAL_KEY wxT( "AutoSaveInterval" ) #define ENBL_ZOOM_NO_CENTER_KEY wxT( "ZoomNoCenter" ) #define ENBL_MOUSEWHEEL_PAN_KEY wxT( "MousewheelPAN" )