Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#16862 closed defect (fixed)

wxListCtrl emits Invalid rectangle error under GTK3

Reported by: swt2c Owned by: Vadim Zeitlin <vadim@…>
Priority: normal Milestone:
Component: wxGTK Version: 3.0.2
Keywords: Cc:
Blocked By: Blocking:
Patch: yes


Under GTK+3 wxListCtrl emits this error when inserting an item:
* BUG *
In pixman_region32_init_rect: Invalid rectangle passed
Set a breakpoint on '_pixman_log_error' to debug

Reproducer: run listctrl sample and select List -> Append an item

Attachments (1)

0001-Don-t-attempt-to-draw-lines-that-aren-t-visible.patch download (907 bytes) - added by swt2c 5 years ago.

Download all attachments as: .zip

Change History (12)

comment:1 Changed 5 years ago by vadz

  • Status changed from new to infoneeded_new

Don't see it here with GTK+ 3.4.2 (Debian Wheezy).

Could you please set a breakpoint on _pixman_log_error in gdb and show the backtrace?

comment:2 Changed 5 years ago by swt2c

  • Status changed from infoneeded_new to new
#0  0x00007fffe6bf2a20 in _pixman_log_error () at /lib64/
#1  0x00007fffe6befa26 in pixman_region32_init_rect ()
    at /lib64/
#2  0x00007ffff12f9e0e in cairo_region_create_rectangle ()
    at /lib64/
#3  0x00007ffff17f5dce in gdk_window_invalidate_rect_full (window=0x9ddea0, rect=<optimized out>, invalidate_children=1) at gdkwindow.c:3663
#4  0x00007ffff6883d0c in wxWindow::Refresh(bool, wxRect const*) ()
    at /lib64/
#5  0x00007ffff68a9cbe in wxListMainWindow::RefreshLines(unsigned long, unsigned long) () at /lib64/
#6  0x00007ffff68b11b6 in wxListMainWindow::InsertItem(wxListItem&) ()
    at /lib64/
#7  0x00007ffff68b1310 in wxGenericListCtrl::InsertItem(wxListItem&) ()
    at /lib64/
#8  0x00007ffff68b13fb in wxGenericListCtrl::InsertItem(long, wxString const&) () at /lib64/
#9  0x0000000000415008 in MyFrame::OnAdd(wxCommandEvent&) ()
#10 0x00007ffff5d15d3e in wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const () at /lib64/
#11 0x00007ffff5eb2348 in wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () at /lib64/
#12 0x00007ffff5eb244b in wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*)
 () at /lib64/
#13 0x00007ffff5eb27f8 in wxEvtHandler::TryHereOnly(wxEvent&) ()
    at /lib64/
#14 0x00007ffff5eb2883 in wxEvtHandler::ProcessEventLocally(wxEvent&) ()
    at /lib64/
#15 0x00007ffff5eb28e5 in wxEvtHandler::ProcessEvent(wxEvent&) ()
    at /lib64/
#16 0x00007ffff6a8e278 in wxWindowBase::TryAfter(wxEvent&) ()
    at /lib64/
#17 0x00007ffff5eb2657 in wxEvtHandler::SafelyProcessEvent(wxEvent&) ()
    at /lib64/
#18 0x00007ffff6a28f71 in wxMenuBase::SendEvent(int, int) ()
    at /lib64/
#19 0x00007ffff68fd589 in menuitem_activate ()
    at /lib64/
#20 0x00007ffff439dd35 in g_closure_invoke () at /lib64/
#21 0x00007ffff43afa42 in signal_emit_unlocked_R ()
    at /lib64/
#22 0x00007ffff43b8181 in g_signal_emit_valist () at /lib64/
#23 0x00007ffff43b83af in g_signal_emit () at /lib64/
#24 0x00007ffff48fc6f6 in gtk_widget_activate (widget=widget@entry=0x907790)
    at gtkwidget.c:7806
#25 0x00007ffff47eb396 in gtk_menu_shell_activate_item (menu_shell=0x8a27b0, menu_item=0x907790, force_deactivate=<optimized out>) at gtkmenushell.c:1380
#26 0x00007ffff47eb6f8 in gtk_menu_shell_button_release (widget=0x8a27b0, event=<optimized out>) at gtkmenushell.c:792
#27 0x00007ffff47cca7e in _gtk_marshal_BOOLEAN__BOXEDv (closure=0x69f970, return_value=0x7fffffffda30, instance=<optimized out>, args=<optimized out>, marshal_data=<optimized out>, n_params=<optimized out>, param_types=0x69f9a0)
    at gtkmarshalers.c:130
#28 0x00007ffff439df64 in _g_closure_invoke_va () at /lib64/
#29 0x00007ffff43b762b in g_signal_emit_valist () at /lib64/
#30 0x00007ffff43b83af in g_signal_emit () at /lib64/
#31 0x00007ffff48fd714 in gtk_widget_event_internal (widget=0x8a27b0, event=0xa41530) at gtkwidget.c:7773
#32 0x00007ffff47ca3de in propagate_event (topmost=<optimized out>, event=<optimized out>, widget=0x8a27b0) at gtkmain.c:2414
#33 0x00007ffff47ca3de in propagate_event (widget=<optimized out>, event=0xa41530, captured=<optimized out>, topmost=0x0) at gtkmain.c:2516
#34 0x00007ffff47cbf9e in gtk_main_do_event (event=0xa41530) at gtkmain.c:1748
#35 0x00007ffff1809bb2 in gdk_event_source_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at gdkeventsource.c:364
#36 0x00007ffff409eaeb in g_main_context_dispatch () at /lib64/
#37 0x00007ffff409ee88 in g_main_context_iterate.isra ()
    at /lib64/
#38 0x00007ffff409f1b2 in g_main_loop_run () at /lib64/
#39 0x00007ffff47cb2a5 in gtk_main () at gtkmain.c:1207
#40 0x00007ffff6866515 in wxGUIEventLoop::DoRun() ()
    at /lib64/
#41 0x00007ffff5d5c0a0 in wxEventLoopBase::Run() ()
    at /lib64/
#42 0x00007ffff5d18066 in wxAppConsoleBase::MainLoop() ()
    at /lib64/
#43 0x00007ffff5db2ff0 in wxEntry(int&, wchar_t**) ()
    at /lib64/
#44 0x000000000040fea1 in main ()

comment:3 Changed 5 years ago by vadz

Thanks, but I still don't see what's going on here. It would, of course, be great to know the value of the wxRect being refreshed, but you don't have debug information required to see it. It would be great if you could rebuild with it or, if you're comfortable with this kind of things, just look it up from the data on the stack: it's a pretty simple struct so you can find it easily in memory.

Also, what version of GTK+ do you use?


comment:4 Changed 5 years ago by swt2c

I think this is what you're asking for? Let me know if I misunderstood.

(gdb) frame 4
#4  0x00007ffff6883d0c in wxWindow::Refresh (this=0x9926b0, 
    rect=0x7fffffffd030) at src/gtk/window.cpp:3913
3913	                gdk_window_invalidate_rect(window, &r, true);
(gdb) print rect
$1 = (const wxRect *) 0x7fffffffd030
(gdb) print rect.x
$2 = 0
(gdb) print rect.y
$3 = 270
(gdb) print rect.height
$4 = -27
(gdb) print rect.width
$5 = 585

This is under GTK+ 3.14.8 (Fedora 21).

comment:5 Changed 5 years ago by vadz

Yes, this was what I wanted, thanks.

Now, of course, the puzzle is how exactly does rect.height become negative. In principle, it's supposed to come directly from wxListMainWindow::GetLineHeight() where it is set from the result of a wxDC::GetTextExtent() call and it's really not supposed to be negative.

Please try to track this further if possible (anybody else having this GTK+ version at hand is very welcome to help too, of course, but I don't have it right now).

comment:6 Changed 5 years ago by swt2c

Sure, I will see what I can figure out.

comment:7 Changed 5 years ago by swt2c

  • Patch set

The issue was that in wxListMainWindow::RefreshLines() we were attempting to draw lines that weren't visible. This caused the lineFrom to be > lineTo, which caused the negative heights. Patch attached to avoid trying to draw invisible lines, which seems to resolve the issue.

comment:8 Changed 5 years ago by vadz

Thanks a lot for debugging and fixing this!

comment:9 Changed 5 years ago by Vadim Zeitlin <vadim@…>

  • Owner set to Vadim Zeitlin <vadim@…>
  • Resolution set to fixed
  • Status changed from new to closed

In 1b61975fba2a9df81e8eb9178bc289a3ba12adb6/git-wxWidgets:

Avoid refreshing not currently visible items in generic wxListCtrl.

This is useless at best and resulted in GTK+ warnings because we ended up
(somehow -- is there another bug lurking here?) with negative items height in
this case.

Closes #16862.

comment:10 Changed 5 years ago by Vadim Zeitlin <vadim@…>

In c4f569ed60f08ecb318c7268c92471cc5d9071a8/git-wxWidgets:

Avoid refreshing not currently visible items in generic wxListCtrl.

This is useless at best and resulted in GTK+ warnings because we ended up
(somehow -- is there another bug lurking here?) with negative items height in
this case.

Closes #16862.

comment:11 Changed 5 years ago by swt2c

Nope, there isn't another bug lurking here. The negative heights came from the if ( lineFrom < visibleFrom ) ... lines below when a non-visible item was being added. All should be resolved, I think.

Note: See TracTickets for help on using tickets.