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" )