From 4ef6cbf4fb6f414cca79e3082995ad4d6504362c Mon Sep 17 00:00:00 2001 From: Ian McInerney Date: Wed, 12 Apr 2023 15:22:04 +0100 Subject: [PATCH] Add hack to speed up font choice box widget creation There are problems internal to GTK that mean creating choice boxes with a lot of items is a very slow process. This hack works around one of those issues to make it faster to create and display the menu in the choice box. Fixes https://gitlab.com/kicad/code/kicad/-/issues/14277 (Cherry-picked from a77e94d16fc6de0b3bbbc30bba7b46bd1bf0ad83) --- common/widgets/font_choice.cpp | 5 ++++ libs/kiplatform/gtk/ui.cpp | 39 +++++++++++++++++++++++++ libs/kiplatform/include/kiplatform/ui.h | 8 +++++ libs/kiplatform/msw/ui.cpp | 6 ++++ libs/kiplatform/osx/ui.mm | 6 ++++ 5 files changed, 64 insertions(+) diff --git a/common/widgets/font_choice.cpp b/common/widgets/font_choice.cpp index 42db88c345..c295cb2446 100644 --- a/common/widgets/font_choice.cpp +++ b/common/widgets/font_choice.cpp @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -54,7 +55,11 @@ FONT_CHOICE::FONT_CHOICE( wxWindow* aParent, int aId, wxPoint aPosition, wxSize menuList.Add( wxString( name ) ); menuList.Sort(); + + Freeze(); Append( menuList ); + KIPLATFORM::UI::LargeChoiceBoxHack( this ); + Thaw(); m_notFound = wxS( " " ) + _( "" ); } diff --git a/libs/kiplatform/gtk/ui.cpp b/libs/kiplatform/gtk/ui.cpp index 8bfc554844..b47e2acd4c 100644 --- a/libs/kiplatform/gtk/ui.cpp +++ b/libs/kiplatform/gtk/ui.cpp @@ -89,6 +89,45 @@ bool KIPLATFORM::UI::IsStockCursorOk( wxStockCursor aCursor ) } +/** + * The following two functions are based on the "hack" contained in the attached patch at + * https://gitlab.gnome.org/GNOME/gtk/-/issues/1910 which is supposed to speed up creation of + * GTK choice boxes. + * + * The basic idea is to disable some of the event handlers on the menus for the choice box to + * prevent them from running, which will speed up the creation of the choice box and its popup menu. + */ +static void disable_area_apply_attributes_cb( GtkWidget* pItem, gpointer userdata ) +{ + // GTK needs this enormous chain to get the actual type of item that we want + GtkMenuItem* pMenuItem = GTK_MENU_ITEM( pItem ); + GtkWidget* child = gtk_bin_get_child( GTK_BIN( pMenuItem ) ); + GtkCellView* pCellView = GTK_CELL_VIEW( child ); + GtkCellLayout* pCellLayout = GTK_CELL_LAYOUT( pCellView ); + GtkCellArea* pCellArea = gtk_cell_layout_get_area( pCellLayout ); + + g_signal_handlers_block_matched( pCellArea, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, userdata ); +} + + +void KIPLATFORM::UI::LargeChoiceBoxHack( wxChoice* aChoice ) +{ + AtkObject* atkObj = gtk_combo_box_get_popup_accessible( GTK_COMBO_BOX( aChoice->m_widget ) ); + + if( !atkObj || !GTK_IS_ACCESSIBLE( atkObj ) ) + return; + + GtkWidget* widget = gtk_accessible_get_widget( GTK_ACCESSIBLE( atkObj ) ); + + if( !widget || !GTK_IS_MENU( widget ) ) + return; + + GtkMenu* menu = GTK_MENU( widget ); + + gtk_container_foreach( GTK_CONTAINER( menu ), disable_area_apply_attributes_cb, menu ); +} + + void KIPLATFORM::UI::EllipsizeChoiceBox( wxChoice* aChoice ) { // This function is based on the code inside the function post_process_ui in diff --git a/libs/kiplatform/include/kiplatform/ui.h b/libs/kiplatform/include/kiplatform/ui.h index 23b5571c02..490e513787 100644 --- a/libs/kiplatform/include/kiplatform/ui.h +++ b/libs/kiplatform/include/kiplatform/ui.h @@ -86,6 +86,14 @@ namespace KIPLATFORM */ bool IsStockCursorOk( wxStockCursor aCursor ); + /** + * Configure a wxChoice control to support a lot of entries by disabling functionality that makes + * adding new items become very expensive. + * + * @param aChoice is the choice box to modify + */ + void LargeChoiceBoxHack( wxChoice* aChoice ); + /** * Configure a wxChoice control to ellipsize the shown text in the button with the ellipses * placed at the end of the string. diff --git a/libs/kiplatform/msw/ui.cpp b/libs/kiplatform/msw/ui.cpp index 02bd03f6ee..733c9fd7d4 100644 --- a/libs/kiplatform/msw/ui.cpp +++ b/libs/kiplatform/msw/ui.cpp @@ -110,6 +110,12 @@ bool KIPLATFORM::UI::IsStockCursorOk( wxStockCursor aCursor ) } +void KIPLATFORM::UI::LargeChoiceBoxHack( wxChoice* aChoice ) +{ + // Not implemented +} + + void KIPLATFORM::UI::EllipsizeChoiceBox( wxChoice* aChoice ) { // Not implemented diff --git a/libs/kiplatform/osx/ui.mm b/libs/kiplatform/osx/ui.mm index 2e7e461fc5..807a0bb1be 100644 --- a/libs/kiplatform/osx/ui.mm +++ b/libs/kiplatform/osx/ui.mm @@ -109,6 +109,12 @@ bool KIPLATFORM::UI::IsStockCursorOk( wxStockCursor aCursor ) } +void KIPLATFORM::UI::LargeChoiceBoxHack( wxChoice* aChoice ) +{ + // Not implemented +} + + void KIPLATFORM::UI::EllipsizeChoiceBox( wxChoice* aChoice ) { // Not implemented