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
This commit is contained in:
Ian McInerney 2023-04-12 15:22:04 +01:00
parent e1c9e0e6fc
commit a77e94d16f
5 changed files with 64 additions and 0 deletions

View File

@ -18,6 +18,7 @@
*/
#include <widgets/font_choice.h>
#include <kiplatform/ui.h>
#include <wx/fontenum.h>
#include <font/fontconfig.h>
#include <pgm_base.h>
@ -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( " " ) + _( "<not found>" );
}

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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