From aa1baec06230ba066c3a548dd6dcdb6c25ac6c5c Mon Sep 17 00:00:00 2001 From: Seth Hillbrand <seth@kipro-pcb.com> Date: Tue, 25 Feb 2025 19:37:58 -0800 Subject: [PATCH] Fix git flicker on Windows --- kicad/project_tree_pane.cpp | 88 +++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/kicad/project_tree_pane.cpp b/kicad/project_tree_pane.cpp index 0e6c5536fb..8d4aa14ed3 100644 --- a/kicad/project_tree_pane.cpp +++ b/kicad/project_tree_pane.cpp @@ -181,6 +181,8 @@ BEGIN_EVENT_TABLE( PROJECT_TREE_PANE, wxSashLayoutWindow ) END_EVENT_TABLE() +wxDECLARE_EVENT( UPDATE_ICONS, wxCommandEvent ); + PROJECT_TREE_PANE::PROJECT_TREE_PANE( KICAD_MANAGER_FRAME* parent ) : wxSashLayoutWindow( parent, ID_LEFT_FRAME, wxDefaultPosition, wxDefaultSize, wxNO_BORDER | wxTAB_TRAVERSAL ) @@ -1157,8 +1159,6 @@ void PROJECT_TREE_PANE::onIdle( wxIdleEvent& aEvent ) item->Activate( this ); } - - updateGitStatusIcons(); } @@ -1967,6 +1967,13 @@ void PROJECT_TREE_PANE::updateGitStatusIcons() std::unique_lock<std::mutex> lock( m_gitStatusMutex, std::try_to_lock ); + CallAfter( + [this]() + { + m_gitStatusTimer.Start( ADVANCED_CFG::GetCfg().m_GitIconRefreshInterval, + wxTIMER_ONE_SHOT ); + } ); + if( !lock.owns_lock() ) return; @@ -2118,6 +2125,7 @@ void PROJECT_TREE_PANE::updateGitStatusIconMap() auto [ localChanges, remoteChanges ] = m_TreeProject->GitCommon()->GetDifferentFiles(); size_t count = git_status_list_entrycount( status_list ); + bool updated = false; for( size_t ii = 0; ii < count; ++ii ) { @@ -2138,36 +2146,98 @@ void PROJECT_TREE_PANE::updateGitStatusIconMap() // that is the main status we want to show. if( entry->status & GIT_STATUS_IGNORED ) { - m_gitStatusIcons[iter->second] = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_IGNORED; + auto [it, inserted] = m_gitStatusIcons.try_emplace( iter->second, + KIGIT_COMMON::GIT_STATUS::GIT_STATUS_IGNORED ); + + if( inserted || it->second != KIGIT_COMMON::GIT_STATUS::GIT_STATUS_IGNORED ) + updated = true; + + it->second = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_IGNORED; } else if( entry->status & ( GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED ) ) { - m_gitStatusIcons[iter->second] = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED; + auto [it, inserted] = m_gitStatusIcons.try_emplace( iter->second, + KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED ); + + if( inserted || it->second != KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED ) + updated = true; + + it->second = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED; } else if( entry->status & ( GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_NEW ) ) { - m_gitStatusIcons[iter->second] = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_ADDED; + auto [it, inserted] = m_gitStatusIcons.try_emplace( iter->second, + KIGIT_COMMON::GIT_STATUS::GIT_STATUS_ADDED ); + + if( inserted || it->second != KIGIT_COMMON::GIT_STATUS::GIT_STATUS_ADDED ) + updated = true; + + it->second = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_ADDED; } else if( entry->status & ( GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_DELETED ) ) { - m_gitStatusIcons[iter->second] = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_DELETED; + auto [it, inserted] = m_gitStatusIcons.try_emplace( iter->second, + KIGIT_COMMON::GIT_STATUS::GIT_STATUS_DELETED ); + + if( inserted || it->second != KIGIT_COMMON::GIT_STATUS::GIT_STATUS_DELETED ) + updated = true; + + it->second = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_DELETED; } else if( localChanges.count( path ) ) { - m_gitStatusIcons[iter->second] = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_AHEAD; + auto [it, inserted] = m_gitStatusIcons.try_emplace( iter->second, + KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED ); + + if( inserted || it->second != KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED ) + updated = true; + + it->second = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED; } else if( remoteChanges.count( path ) ) { - m_gitStatusIcons[iter->second] = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_BEHIND; + auto [it, inserted] = m_gitStatusIcons.try_emplace( iter->second, + KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED ); + + if( inserted || it->second != KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED ) + updated = true; + + it->second = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED; } else { - m_gitStatusIcons[iter->second] = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_CURRENT; + auto [it, inserted] = m_gitStatusIcons.try_emplace( iter->second, + KIGIT_COMMON::GIT_STATUS::GIT_STATUS_CURRENT ); + + if( inserted || it->second != KIGIT_COMMON::GIT_STATUS::GIT_STATUS_CURRENT ) + updated = true; + + it->second = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_CURRENT; } } git_status_list_free( status_list ); git_index_free( index ); + + // If the icons are current, don't bother refreshing the tree because it flickers on Windows + if( updated ) + { + CallAfter( + [this]() + { + updateGitStatusIcons(); + } ); + } + else + { + // Need to callAfter so that it is started in the main thread + CallAfter( + [this]() + { + m_gitStatusTimer.Start( ADVANCED_CFG::GetCfg().m_GitIconRefreshInterval, + wxTIMER_ONE_SHOT ); + } ); + } }