From 00d4cf5c5a13eaa256ccf239904f74df47400ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=89=AC=E6=96=8C?= Date: Mon, 30 Dec 2024 14:00:56 +0800 Subject: [PATCH] GTK: Add conditional debug logging infrastructure to src/gtk/debughlp.cpp and log all gdk_window_invalidate_rect(), gtk_widget_queue_draw() and gtk_widget_queue_draw_area(). The logging will be available when GDK_DEBUG env is defined. --- build/cmake/files.cmake | 1 + include/wx/gtk/private/debughlp.h | 11 +++++++++++ src/gtk/dataview.cpp | 3 +++ src/gtk/debughlp.cpp | 20 ++++++++++++++++++++ src/gtk/mdi.cpp | 5 ++++- src/gtk/minifram.cpp | 5 ++++- src/gtk/overlay.cpp | 2 ++ src/gtk/slider.cpp | 2 ++ src/gtk/toplevel.cpp | 8 ++++++-- src/gtk/win_gtk.cpp | 7 +++++++ src/gtk/window.cpp | 31 +++++++++++++++++++++++++------ src/gtk1/win_gtk.c | 1 + src/unix/glegl.cpp | 1 + 13 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 include/wx/gtk/private/debughlp.h create mode 100644 src/gtk/debughlp.cpp diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake index b71799f9bc0c..e312704880b7 100644 --- a/build/cmake/files.cmake +++ b/build/cmake/files.cmake @@ -1317,6 +1317,7 @@ set(GTK_LOWLEVEL_SRC src/gtk/utilsgtk.cpp src/gtk/win_gtk.cpp src/gtk/window.cpp + src/gtk/debughlp.cpp ) set(GTK2_LOWLEVEL_SRC diff --git a/include/wx/gtk/private/debughlp.h b/include/wx/gtk/private/debughlp.h new file mode 100644 index 000000000000..17fdd3ce9a45 --- /dev/null +++ b/include/wx/gtk/private/debughlp.h @@ -0,0 +1,11 @@ +#ifndef _WX_GTK_PRIVATE_DEBUGHLP_H_ +#define _WX_GTK_PRIVATE_DEBUGHLP_H_ + +#include "wx/defs.h" + +bool wxGtkDebugLog(const char* format, const char* function_name, int line_num, const char* src_file ...); + +#define DO_GTK_DEBUG_LOG(format, ...) \ + wxGtkDebugLog("%s:%d:%s--->" format, __func__, __LINE__, __FILE__, __VA_ARGS__) + +#endif \ No newline at end of file diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index e080f1ffcb15..1b19078f7bd9 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -1920,6 +1920,8 @@ bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsig gtk_widget_get_allocation(GTK_WIDGET(gtk_tree_view_column_get_button(gcolumn)), &a); int ydiff = a.height; // Redraw + DO_GTK_DEBUG_LOG("wxGtkDataViewModelNotifier::ValueChanged:Call gtk_widget_queue_draw_area(%p, rect(%d, %d, %d, %d)).\n", + GTK_WIDGET(widget), cell_area.x - xdiff, ydiff + cell_area.y, cell_area.width, cell_area.height); gtk_widget_queue_draw_area( GTK_WIDGET(widget), cell_area.x - xdiff, ydiff + cell_area.y, cell_area.width, cell_area.height ); } @@ -3748,6 +3750,7 @@ void wxDataViewCtrlInternal::OnInternalIdle() if (m_dirty) { GtkWidget *widget = m_owner->GtkGetTreeView(); + DO_GTK_DEBUG_LOG("wxDataViewCtrlInternal::OnInternalIdle() Call gtk_widget_queue_draw(%p).\n", widget); gtk_widget_queue_draw( widget ); m_dirty = false; } diff --git a/src/gtk/debughlp.cpp b/src/gtk/debughlp.cpp new file mode 100644 index 000000000000..713b653da0e1 --- /dev/null +++ b/src/gtk/debughlp.cpp @@ -0,0 +1,20 @@ +#include "wx/gtk/private/debughlp.h" + +bool wxGtkDebugLog(const char* format, const char* function_name, int line_num, const char* src_file, ...){ + const static auto GDK_DEBUG_defined = wxGetEnv("GDK_DEBUG", nullptr); + if (!GDK_DEBUG_defined) + return false; + ::FILE* logfile_ = std::fopen("/tmp/cmclient_gtk.log", "a"); + timespec nano_now; + clock_gettime(CLOCK_REALTIME, &nano_now); + if (logfile_ != nullptr){ + va_list argptr; + va_start(argptr,line_num); + fprintf(logfile_, "PreciseTime:%ld,%ld. ", nano_now.tv_sec, nano_now.tv_nsec); + fprintf(logfile_, format, src_file, line_num, function_name, argptr); + va_end(argptr); + std::fclose(logfile_); + return true; + } + return false; +} \ No newline at end of file diff --git a/src/gtk/mdi.cpp b/src/gtk/mdi.cpp index a8ff73ef096b..b8a715de2d63 100644 --- a/src/gtk/mdi.cpp +++ b/src/gtk/mdi.cpp @@ -19,6 +19,7 @@ #endif #include "wx/gtk/private.h" +#include "wx/gtk/private/debughlp.h" //----------------------------------------------------------------------------- // "switch_page" @@ -289,8 +290,10 @@ wxMDIChildFrame::~wxMDIChildFrame() delete m_menuBar; // wxMDIClientWindow does not get redrawn properly after last child is removed - if (m_parent && m_parent->GetChildren().size() <= 1) + if (m_parent && m_parent->GetChildren().size() <= 1){ + DO_GTK_DEBUG_LOG("wxMDIChildFrame::~wxMDIChildFrame() Call gtk_widget_queue_draw(%p).\n", m_parent->m_widget); gtk_widget_queue_draw(m_parent->m_widget); + } } void wxMDIChildFrame::GTKHandleRealized() diff --git a/src/gtk/minifram.cpp b/src/gtk/minifram.cpp index c31a3ad16c6c..e6b6b8d7bb9d 100644 --- a/src/gtk/minifram.cpp +++ b/src/gtk/minifram.cpp @@ -27,6 +27,7 @@ #include "wx/gtk/private/wrapgtk.h" #include "wx/gtk/private/gtk3-compat.h" #include "wx/gtk/private/backend.h" +#include "wx/gtk/private/debughlp.h" //----------------------------------------------------------------------------- // data @@ -456,8 +457,10 @@ void wxMiniFrame::SetTitle( const wxString &title ) wxFrame::SetTitle( title ); GdkWindow* window = gtk_widget_get_window(gtk_bin_get_child(GTK_BIN(m_widget))); - if (window) + if (window){ + DO_GTK_DEBUG_LOG("wxMiniFrame::SetTitle() Call gdk_window_invalidate_rect(%p, NULL_RECT, false).\n", window); gdk_window_invalidate_rect(window, NULL, false); + } } #endif // wxUSE_MINIFRAME diff --git a/src/gtk/overlay.cpp b/src/gtk/overlay.cpp index e4446077b22e..c0f716dd364f 100644 --- a/src/gtk/overlay.cpp +++ b/src/gtk/overlay.cpp @@ -15,6 +15,7 @@ #include "wx/window.h" #include "wx/gtk/private/wrapgtk.h" #include "wx/gtk/private/backend.h" +#include "wx/gtk/private/debughlp.h" class wxOverlayImpl: public wxOverlay::Impl { @@ -185,6 +186,7 @@ void wxOverlayImpl::EndDrawing(wxDC* dc) cairo_surface_destroy(m_surface); m_surface = surface; } + DO_GTK_DEBUG_LOG("wxOverlayImpl::EndDrawing() Call gtk_widget_queue_draw(%p).\n", m_overlay); gtk_widget_queue_draw(m_overlay); } diff --git a/src/gtk/slider.cpp b/src/gtk/slider.cpp index 9d63d7a0e49c..5ec80b9ed3c5 100644 --- a/src/gtk/slider.cpp +++ b/src/gtk/slider.cpp @@ -20,6 +20,7 @@ #include "wx/gtk/private/wrapgtk.h" #include "wx/gtk/private/eventsdisabler.h" +#include "wx/gtk/private/debughlp.h" //----------------------------------------------------------------------------- // data @@ -432,6 +433,7 @@ void wxSlider::GTKSetValue(int value) gtk_range_set_value(GTK_RANGE (m_scale), value); // GTK only updates value label if handle moves at least 1 pixel + DO_GTK_DEBUG_LOG("wxSlider::GTKSetValue() Call gtk_widget_queue_draw(%p).\n", m_scale); gtk_widget_queue_draw(m_scale); } diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index c5f374a9c35e..dd75d29bd379 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -39,6 +39,7 @@ #include "wx/gtk/private/stylecontext.h" #include "wx/gtk/private/win_gtk.h" #include "wx/gtk/private/backend.h" +#include "wx/gtk/private/debughlp.h" #ifdef GDK_WINDOWING_X11 #include @@ -1040,14 +1041,17 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long) void wxTopLevelWindowGTK::Refresh( bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect) ) { wxCHECK_RET( m_widget, wxT("invalid frame") ); - + + DO_GTK_DEBUG_LOG("wxTopLevelWindowGTK::Refresh() Call gtk_widget_queue_draw(%p).\n", m_widget); gtk_widget_queue_draw( m_widget ); GdkWindow* window = NULL; if (m_wxwindow) window = gtk_widget_get_window(m_wxwindow); - if (window) + if (window){ + DO_GTK_DEBUG_LOG("wxTopLevelWindowGTK::Refresh() Call gdk_window_invalidate_rect(%p, NULL_RECT, true).\n", window); gdk_window_invalidate_rect(window, NULL, true); + } } #if defined(__WXGTK3__) && defined(GDK_WINDOWING_X11) diff --git a/src/gtk/win_gtk.cpp b/src/gtk/win_gtk.cpp index 406be37765f3..5c390c100938 100644 --- a/src/gtk/win_gtk.cpp +++ b/src/gtk/win_gtk.cpp @@ -10,6 +10,7 @@ #include "wx/gtk/private.h" #include "wx/gtk/private/win_gtk.h" +#include "wx/gtk/private/debughlp.h" /* wxPizza is a custom GTK+ widget derived from GtkFixed. A custom widget @@ -86,6 +87,10 @@ static void pizza_size_allocate(GtkWidget* widget, GtkAllocation* alloc) GtkAllocation old_alloc; gtk_widget_get_allocation(widget, &old_alloc); GdkWindow* parent = gtk_widget_get_parent_window(widget); + DO_GTK_DEBUG_LOG("pizza_size_allocate() Call gdk_window_invalidate_rect(%p, rect(%d, %d, %d, %d), false)(old_alloc).\n", + parent, old_alloc.x, old_alloc.y, old_alloc.width, old_alloc.height); + DO_GTK_DEBUG_LOG("pizza_size_allocate() Call gdk_window_invalidate_rect(%p, rect(%d, %d, %d, %d), false)(alloc).\n", + parent, alloc->x, alloc->y, alloc->width, alloc->height); gdk_window_invalidate_rect(parent, &old_alloc, false); gdk_window_invalidate_rect(parent, alloc, false); } @@ -135,6 +140,7 @@ static void pizza_show(GtkWidget* widget) // invalidate whole allocation so borders will be drawn properly GtkAllocation a; gtk_widget_get_allocation(widget, &a); + DO_GTK_DEBUG_LOG("pizza_show() Call gtk_widget_queue_draw_area(%p, rect(%d, %d, %d, %d)).\n", parent, a.x, a.y, a.width, a.height); gtk_widget_queue_draw_area(parent, a.x, a.y, a.width, a.height); } @@ -149,6 +155,7 @@ static void pizza_hide(GtkWidget* widget) // invalidate whole allocation so borders will be erased properly GtkAllocation a; gtk_widget_get_allocation(widget, &a); + DO_GTK_DEBUG_LOG("pizza_hide() Call gtk_widget_queue_draw_area(%p, rect(%d, %d, %d, %d)).\n", parent, a.x, a.y, a.width, a.height); gtk_widget_queue_draw_area(parent, a.x, a.y, a.width, a.height); } diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index dfa3d1b2800e..2329cbfc2aad 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -46,6 +46,7 @@ #include "wx/gtk/private/win_gtk.h" #include "wx/gtk/private/backend.h" #include "wx/private/textmeasure.h" +#include "wx/gtk/private/debughlp.h" using namespace wxGTKImpl; #ifdef GDK_WINDOWING_X11 @@ -522,11 +523,15 @@ bool wxGTKImpl::IsX11(void* instance) extern "C" { #ifdef __WXGTK3__ -static gboolean draw(GtkWidget*, cairo_t* cr, wxWindow* win) +static gboolean draw(GtkWidget* gtk_widget, cairo_t* cr, wxWindow* win) { - if (gtk_cairo_should_draw_window(cr, win->GTKGetDrawingWindow())) + DO_GTK_DEBUG_LOG("Gtk \"draw\" signal called for %p. wxWin %p\n", gtk_widget, win); + if (gtk_cairo_should_draw_window(cr, win->GTKGetDrawingWindow())){ + DO_GTK_DEBUG_LOG("gtk_cairo_should_draw_window is ok called for %p. wxWin %p.\n", gtk_widget, win); win->GTKSendPaintEvents(cr); - + } + else + DO_GTK_DEBUG_LOG("gtk_cairo_should_draw_window is NOT ok called for %p. wxWin %p.\n", gtk_widget, win); return false; } #else // !__WXGTK3__ @@ -5321,20 +5326,33 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground), GdkRectangle r = { rect->x, rect->y, rect->width, rect->height }; if (GetLayoutDirection() == wxLayout_RightToLeft) r.x = gdk_window_get_width(window) - r.x - rect->width; + DO_GTK_DEBUG_LOG("wxWindowGTK::Refresh() Call gdk_window_invalidate_rect(%p, rect(%d, %d, %d, %d), true). m_wxwindow:%p, m_widget:%p\n", window, r.x, r.y, r.width, r.height, m_wxwindow, m_widget); gdk_window_invalidate_rect(window, &r, true); } - else + else{ + DO_GTK_DEBUG_LOG("wxWindowGTK::Refresh() Call gdk_window_invalidate_rect(%p, NULL_RECT, true). m_wxwindow:%p, m_widget:%p\n", window, m_wxwindow, m_widget); gdk_window_invalidate_rect(window, NULL, true); + } + } + else { + DO_GTK_DEBUG_LOG("wxWindowGTK::Refresh() The m_wxwindow %p is NOT yet mapped, Skip. m_wxwindow:%p, m_widget:%p\n", m_wxwindow, m_wxwindow, m_widget); } } else if (m_widget) { if (gtk_widget_get_mapped(m_widget)) { - if (rect) + if (rect){ + DO_GTK_DEBUG_LOG("wxWindowGTK::Refresh() Call gtk_widget_queue_draw_area(%p, rect(%d, %d, %d, %d)). m_wxwindow:%p, m_widget:%p\n", m_widget, rect->x, rect->y, rect->width, rect->height, m_wxwindow, m_widget); gtk_widget_queue_draw_area(m_widget, rect->x, rect->y, rect->width, rect->height); - else + } + else { + DO_GTK_DEBUG_LOG("wxWindowGTK::Refresh() Call gtk_widget_queue_draw(%p). m_wxwindow:%p, m_widget:%p\n", m_widget, m_wxwindow, m_widget); gtk_widget_queue_draw(m_widget); + } + } + else { + DO_GTK_DEBUG_LOG("wxWindowGTK::Refresh() The m_widget %p is NOT yet mapped, Skip. m_wxwindow:%p, m_widget:%p\n", m_widget, m_wxwindow, m_widget); } } } @@ -6689,6 +6707,7 @@ void wxWindowGTK::GTKFreezeWidget(GtkWidget* widget) void wxWindowGTK::GTKThawWidget(GtkWidget* widget) { g_signal_handlers_block_by_func(widget, (void*)draw_freeze, this); + DO_GTK_DEBUG_LOG("wxWindowGTK::GTKThawWidget() Call gtk_widget_queue_draw(%p).\n", widget); gtk_widget_queue_draw(widget); } diff --git a/src/gtk1/win_gtk.c b/src/gtk1/win_gtk.c index 7ac199dedc1d..c423dd340077 100644 --- a/src/gtk1/win_gtk.c +++ b/src/gtk1/win_gtk.c @@ -219,6 +219,7 @@ gtk_pizza_set_shadow_type (GtkPizza *pizza, if (GTK_WIDGET_VISIBLE (pizza)) { gtk_widget_size_allocate (GTK_WIDGET (pizza), &(GTK_WIDGET (pizza)->allocation)); + DO_GTK_DEBUG_LOG("gtk_pizza_set_shadow_type() Call gtk_widget_queue_draw(%p).\n", GTK_WIDGET (pizza)); gtk_widget_queue_draw (GTK_WIDGET (pizza)); } } diff --git a/src/unix/glegl.cpp b/src/unix/glegl.cpp index 7c91c8c905fb..1e613cc2e266 100644 --- a/src/unix/glegl.cpp +++ b/src/unix/glegl.cpp @@ -455,6 +455,7 @@ void wxGLCanvasEGL::OnWLFrameCallback() m_readyToDraw = true; g_clear_pointer(&m_wlFrameCallbackHandler, wl_callback_destroy); SendSizeEvent(); + DO_GTK_DEBUG_LOG("wxGLCanvasEGL::OnWLFrameCallback() Call gtk_widget_queue_draw(%p).\n", m_wxwindow); gtk_widget_queue_draw(m_wxwindow); #endif // GDK_WINDOWING_WAYLAND }