GNOME Bugzilla – Bug 694086
GtkEntry elements need clipping
Last modified: 2013-07-26 12:17:48 UTC
I see this bug in GTK3 Firefox port on Fedora 18 and Fedora 15. When GtkEntry elements are drawn by gtk_render_background()/gtk_render_frame(), the background and frame fill whole window area with bg color or draw some artefacts around so I have to set cairo clipping to achieve proper look. Both (gtk_render_background() and gtk_render_frame()) needs the clipping. I affects gtk_draw_insertion_cursor() too, it fills whole GtkEntry element area without the clipping. // Extra clipping code for GtkEntry GdkRectangle clipped_rect = {x, y, width, height}; gdk_cairo_rectangle(cr, &clipped_rect); cairo_clip(cr); style = gtk_widget_get_style_context(gEntryWidget); gtk_render_background(style, cr, x, y, width, height); gtk_render_frame(style, cr, x, y, width, height); // Extra clipping code for cursor gdk_cairo_rectangle(cr, &location); cairo_clip(cr); gtk_draw_insertion_cursor(gEntryWidget, cr, &location, TRUE, direction, FALSE);
Created attachment 236608 [details] GtkEntry - gtk_render_background() GtkEntry & gtk_render_background() only - see that the whole window area is filled, tabs which are under the menu are missing.
Created attachment 236610 [details] GtkEntry - gtk_render_frame() GtkEntry & gtk_render_frame() only - see the grey artifacts produced by the second entry box (google search).
Created attachment 236612 [details] gtk_draw_insertion_cursor() withnout clipping - fills whole entry
So, after debugging this with Martin it doesn't seem to be a problem in GTK but rather involve buggy code in Firefox's GTK3 drawing routines. So I'm gonna close this for now.
Created attachment 237028 [details] before gtkentry paint
Created attachment 237029 [details] after gtkentry paint
After some debugging it still looks like a bug in the gtk/cairo for me :) See those the two screenshots, before and after gtkentry paint.
The GtkEntry widget is drawn on 0,0 -> 298,24, there may be some transformations involved. It may be also caused by some bad cairo configuration/setup, but I wonder where to look at.
Well, the cairo matrix looks okay, it's: $1 = {xx = 1, yx = 0, xy = 0, yy = 1, x0 = 402, y0 = 60}
Ehm, sorry, that's for the first widget. This one is: $2 = {xx = 1, yx = 0, xy = 0, yy = 1, x0 = 44, y0 = 60}
I found more widgets which shows similar problems - GtkNotebook, GtkButton in disabled state, GtkEntry and a cursor drawn by gtk_draw_insertion_cursor().
Does this happen even with the default theme? gtk_draw_insertion_cursor() doesn't actually depend on the theme engine. That and, in the default theme, render_frame_fill() and _gtk_theming_background_paint_color() limit their drawing, and so don't rely on any clip being already set on the provided cairo_t. That seems to hint at a cairo bug.
Created attachment 249879 [details] testcase There's a testcase which shows this bug. gtk_render_background()/gtk_render_frame() does not clear existing cairo path which is used as a clipping area instead of the one, smaller, inside gtk3 element. When cairo_rectangle() is removed from surface_test() the widgets are rendered correctly.
I'm tempted to close this as NOTABUG because I think it's the responsibility of the caller to make sure the cairo_t is in a proper state when passed to GTK render functions. So there should be no preexisting path, the operator should be OVER, things like that. Do Mozilla APIs handle that differently?
(In reply to comment #14) > I'm tempted to close this as NOTABUG because I think it's the responsibility of > the caller to make sure the cairo_t is in a proper state when passed to GTK > render functions. So there should be no preexisting path, the operator should > be OVER, things like that. Is that written somewhere in Gtk3 documentation? I've got an impression that gtk rendering routines save the current cairo state, draw the widget (set color/shapes and so) and restore the cairo state. When the gtk3 code uses paths I expect the code make sure the path is properly set. The operators are a different story - if the code does not fiddle with them one can expect they're in correct state and gtk code does not change them either. > Do Mozilla APIs handle that differently? How do you mean it?
Paths are not part of the save/restore cycle so one would have to do extra work to get them saved/restored properly. In practice I've only ever seen cairo paths used the way GTK does by adding paths only for an immediate operation (clip/fill/stroke) and then clearing the path again before doing anything else with the cairo_t. Which is why I was wondering about Mozilla's use of Cairo and if they treat paths differently.
Ahh, I see. Well, the "clearing the path again before doing anything else" part is apparently missing in gtk code :) Mozilla just clears cairo path before any rendering, but not after it.
...so I think the expected workflow is to clear path, create my own and use it. We can apply a workaround in Mozilla for that but my feeling is when I use something I should set it/initialize it properly.
I suppose it doesn't hurt from a performance pov to call cairo_new_path() after cairo_save() in all the gtk_render_*() functions. And it makes people that are new to cairo or that have learned different conventions (like you) not run into weird bugs. Care to do a patch for that?
Thanks, will do such patch. Is it enough to do it against gtk+-3.9.8 - the one in Fedora 21?
Yeah, that code probably hasn't changed since 3.8.0.
Created attachment 250007 [details] [review] cairo new path
Comment on attachment 250007 [details] [review] cairo new path Perfect. I assume you tested it fixes your issue, so feel free to push it.
Yes, I tested it and it fixes the issue. What do you mean by "feel free to push it"? I don't have any rights here and/or in gtk project.
we'll pick it up, no worries
I always think everyone has git access, makes my life way easier because most of the times I'm right. Pushed your patch, closing this. I don't think we want to backport to 3.8, do we?
(In reply to comment #26) > Pushed your patch, closing this. I don't think we want to backport to 3.8, do > we? No, I don't think so.