GNOME Bugzilla – Bug 453499
Widget specific special cases in the engine
Last modified: 2011-09-18 13:08:41 UTC
see http://abock.org/2007/07/02/suboptimal-theming-in-gtk/ Other information:
What is this bug exactly about? At least some overview should be here, and some discussion on who to fix this (short vs. long term stuff). A simple "we have a problem" bug seems useless to me.
Yeah, this seems pretty useless as a bug.
(In reply to comment #2) Sorry i just don't want get that suggestion lost. There is theming support for lowlevel widget stuff as draw_shadow and draw_box. ( http://blogs.gnome.org/thos/2007/07/04/re-suboptimal-theming-in-gtk/ ) The highlevel stuff like the special case GtkTreeView draw_treeview is missing. See http://svn.gnome.org/viewcvs/gtk-engines/trunk/engines/clearlooks/src/clearlooks_style.c?annotate=781#l497
This bit from the originally-linked post sums up the problem pretty well, and ought to have been in the original bug summary: "My widget does not derive from GtkTreeView, so I cannot use the styles defined for it by the engine. Because of this, custom widgets immediately become second class citizens. This is bad for complex applications that may do their own theming, and probably ISVs if they care, and most certainly for other toolkits (XUL, QT, Wx) which can use the GTK engine to provide a theme that integrates applications consuming another toolkit with the rest of GTK. "This limitation is pointless to me. All of this object-hierarchy-bound conditional theming can be replaced with a much better detail system that would allow any widget to draw any style. Details should also be published and made standard so it is easy to replicate the styles of a particular widget. The bottom line is that the theme engine should never need to know, or at least never require a widget to be of a particular type for the desired style to be drawn." Generally, these limitations are due to a large number of explicit GE_IS checks made throughout the theming engines, but it's not clear why these are needed or even beneficial. They do, however, essentially eliminate the utility of GtkStyle for writing custom widgets. In terms of short-term action, I think it's worth re-examining whether the GE_IS checks are really necessary, and if not, eliminating them.
(From the sound of things, at least some of the GE_IS checks would need to be replaced by checks for new detail names instead. I'm not sure what an appropriate transition plan would look like [e.g. stock Gtk widgets would need to start using the new detail names], but this is a serious problem and something really should be done.)
s/not clear why these are needed or even beneficial/& versus some other approach/
There are two issues: * We want to special case treeview headers * We don't want to break api or existing themes I'm afraid the current method is the only way to do both these things. Ideally we might fix this by adding a special detail hint for the treeview headers, but this would mean all existing themes would suddenly render incorrectly.
Why not begin by fixing the themes so that the they draw as treeview headers when the widget is a treeview OR when a new special detail hint is given. Then, maybe, much later, modify the treeview to use the new detail hint. The important part is enabling custom widgets to be drawn as treeview.
I see one way of improving the current situation. But it requires changes in engines, themes and applications. So, what we would do is to "move" the widget check into the gtkrc. This works by eg. doing a style like the following: style "treeview-header" { engine "clearlooks" { hint = "treeview-header" } } widget_class "*.<GtkTreeView>.<GtkButton>" style "treeview-header" Then in the engine check the hint parameter instead of using the passed in widget. (The passed in widget would still be used to try to special case the first and last column header. So the result will not be perfect, but pretty good.) Then the application needs to call gtk_rc_get_style_by_paths to get the style of the treeview header. This idea has the advantage that it works with pixmap themes. Other than that there are some disadvantages: * Every Clearlooks, etc. based theme needs to be modified to support it. Clearlooks could still fall back to using the passed in pointer for a while with the caveat of breaking applications. * Applications may not be able to access style properties because they may not have a fake widget. Same for the engine. See bug #412134. * External engines like UbuntuLooks might not pick this up, so the default Ubuntu theme may still be broken, even if Clearlooks is fixed.
Is it possible to implement Benjamin's solution, while leaving the existing widget class checks in for now as Quentin suggests?
Sure, my plan would be to leave the class checks in for at least one major release cycle.
Changed the summary and product.
Just in case someone is interested. I have implemented my suggestion for Clearlooks in a separate branch, which I will probably complete and merge some time next week. The code is currently in the less-widget-checks branch of gtk-engines. svn://svn.gnome.org/svn/gtk-engines/branches/less-widget-checks http://svn.gnome.org/viewcvs/gtk-engines/branches/less-widget-checks
Can we have a detail hint for items desired to be packed tightly against other widgets (like the entry and button in a combo box widget?) I wanted to recreate a combo box like widget with an entry, and instead of the combo drop down button, have a "..." button to bring up a completion interface. This is with a stock theme engine: http://www2.eng.cam.ac.uk/~pcjc2/geda/ui/footprint_picker2-crop.png And with it "correctly" rendered by hacking the theme engine: http://www2.eng.cam.ac.uk/~pcjc2/geda/ui/gschem_dotdot_box.png It seems this could also be applicable to spin buttons. ge_is_in_combo_box() is one of the relevant function. It is used to change drawing of the corners for the entry, and the corners of the button. (As well as spacing between the widgets). I'd guess the detail hints would have to be along the lines of: "something_tight_to_my_right_txt_dir" which could be interpreted as needing to cut off the corners on the RHS of this widget (or LHS for LTR text dir). a similar detail for the LHS would be needed, and for completeness, top and bottom too. Widgets (e.g. spin buttons) might have to be a combination of those flags, - so we essentially specify which corners not to round off. Can we set multiple detail flags at once, or do we have to enumerate all the combinations? We might want to specify the spin buttons pack tightly top and bottom, then have the spin button's container (a vbox?) with its "pack tightly left" detail over-ride the left-corners on the contained items. Assuming its possible, I think the latter seems preferable - although thinking about some hypothetical widgets tightly packed into a GtkTable, we might want their corners cut off on any combination of different sides. Other applicable widgets: Buttons on scrollbars? Scrollbars packed against / into views etc. (This might want a separation between "pack close" and "don't round corners which touch this close packing") Any thoughts on the feasibility / desirability of this suggestion? I might be able to try working up a patch in a month or so, but am not really familiar with theme engine coding - I might need to come back for advice!
Peter, have you looked in to the less-widget-checks branch? Ok, I have not even thought about some of your suggestions. I have never even considered that one would want to have eg. two adjacent spinbuttons packed together visually in some way. About the specific combobox faking you mentioned. You can do that with the code of my gtk-engines branch. What you want to do there is to fake a GtkComboBoxEntry. This works by using the style of the combobox, instead of the one you get by default. So what one needs to do is something along the line of (I have not played around with this, so there may be a better way, or some error here): 1. Hook into the style-set signals 2. As soon as a style change comes in, get a new style for the custom widget. You get the style with gtk_rc_get_style_by_paths, and instead of using your container, use a GtkComboBoxEntry in the class path. Note that this should be done for _all_ child widgets (including the labels). 3. Probably need to guard against recursion somehow, as you are setting a new style in style_set 4. Set and use this style instead. You might also subclass GtkComboBoxEntry and modify the button. This would have worked before already. (I'll think a little bit about this, I just had the idea of attaching a string with an "override-classname" to the container widget. Then it should be possible to write some generic code that handles the style stuff.)
I did look at the branch it seems interesting - and allows us to fake similar widgets to GTK's own. However... On one level of abstraction, we _could_ tell the theme engine we're drawing something which is "like" a combo box, but I believe the more meaningful description is to tell the theme engine what we're trying to achieve in both cases: "draw these widgets tightly together". I'm not sure exactly what hints would cover this requirement (can we have more than one hint per widget?). It seems to explode a bit if we need a unique hint for every combination of widget edges which could be rendered tight against something else. I'd imagine us using this new mechanism / hints when defining the GtkComboBoxEntry, spin button control, fake ComboBox, whatever. This ought to cover many other cases where compound widgets are used. I beleive the code in your branch to define hints is a good step towards how we might specify these. Essentially we're using the gtk-rc files to look at what widgets we have present, and to infer any spatial information possible (like the entry and button packed together in a GtkComboBoxEntry.) I'm imaginging we'd set some "tight_right" hint on the entry, and a "tight_left" hint on the button. (With details for LTR and RTL as necessary). Hopefully that removes the need for special casing like hint="comboboxentry". Other compound widgets like spin buttons, perhaps even treeview headers can benefit (although I'll admit the latter case isn't obvious without a special case in the theme engine) When I've looked at subclassing GTK widgets to change their behaviour / looks, I've often impossible due to hiden implementation details.
For your information. This never made it into the 2.12 release cycle as I decided to not push it in because of the 2.20 release. However I have now merged the code into trunk and it will be in the 2.13.0 gtk-engines release. Peter, anything like that would require some larger changes inside GTK+. The patch tries to improve on what is there. I agree that a more general solution would be great, but I think this is the best we can do without larger GTK+ changes. (Though it would be great if those come sooner then later. It does need some thought and discussion though.)
Ok, no point in keeping this bug opened; quite obsolete, just looking at the age, and now GTK+ 3.x has been out for quite some time too!