GNOME Bugzilla – Bug 407215
the PRELIGHT state is misdesigned and unusable with colored widgets
Last modified: 2013-10-06 06:48:46 UTC
PRELIGHT works when widgets do not use color to indicate state. But consider a button that is red when active, and some other color when not. What color should it be in PRELIGHT? if it is red, then when the button is not active and the mouse crosses it, the buttons flickers red - very misleading. But if it is not red in PRELIGHT, then the button "turns off" when the mouse enters it, for which I can provide numerous IRC logs showing deep confusion among users. There should be a way to turn off prelighting for any and/or all widgets. Either that, or it should be removed as a widget state, and replaced by a model that doesn't use color modification to indicate the prelight state. Other information:
This is especially bad for radio buttons. If you hover over the currently-active button, it makes it look like it will do something (such as deactivate) if clicked.
Sounds to me like there should be 2 prelight states (on-prelight and off-prelight) or prelight as a sub-state.
See also bug #51747. There is the point "The states sometimes should be combined".
Even if the current state of affairs is not ideal, I dont believe this is a bug. The requested behaviour can easily be implemented in an application. Colours are generally determined by the theme, not by the application. GtkButton is not an MVC object. GTK_STATE_PRELIGHT, as a representation of the widgets instaneous visual style, is distinct from the state of the corresponding model object. If the application author chooses - possibly with good reason, eg in the case of audio Record or Solo buttons - to override the theme colours, then the application *must* also be responsible for the prelight colours. For example by making the prelight colour a minor variation of the main state. The application has access to the widget style and to all the events: there is nothing to prevent it setting whichever colours it likes. A different prelight colour may be needed for each of the states of the model object. For GtkToggleButton, these states would correspond to GTK_STATE_NORMAL and GTK_STATE_ACTIVE. void button__on_model_state_change(GtkWidget* widget, AppModel* model) { GtkStyle* style = gtk_style_copy(gtk_widget_get_style(widget)); calculate_new_prelight_colour(style, model->state); gtk_widget_set_style(widget, style); g_object_unref(style); }
Tim, I like your suggestion. However, a couple of comments. You said "Colours are generally determined by the theme, not by the application". This is precisely the issue. Ardour is not overriding the theme colours at all. It has its own theme with colors set for each state. My point is that the *logic* of PRELIGHT just isn't right - a button that is currently ACTIVE should be able to treated differently by a theme than a button that is currently NORMAL. The current style/state model doesn't allow for this ... unless the application intervenes to explicitly compute new colors as you suggest. PRELIGHT is a nice idea, but I think that its a mistake to view it as a member of the same set of visual states as ACTIVE, INSENSITIVE or NORMAL. Its an augmentation of the visual information conveyed by those states, not a replacement of it.
(In reply to comment #5) > [...] I think that its a mistake to view [PRELIGHT] as a member of the same > set of visual states as ACTIVE, INSENSITIVE or NORMAL. Its an augmentation of > the visual information conveyed by those states, not a replacement of it. 0) This echoes my feelings. 1) My _first_ impression is that PRELIGHT now basically is implemented as "effect of mouseover on widget in NORMAL state". Would it make sense to add a "PRELIGHT_FOR_ACTIVE" state? ("PRELIGHT_FOR_INSENSITIVE" seems not so useful.) Of course it could be that this new state implies a rewrite of all themes (since such a new state can't be implemented without "breaking" existing themes - i.e. without making them look horrible) and/or a rewrite of all (widgets in) applications that could use that new state?
another update. I finally implemented tim's suggestion. its a bit more work than he describes - you also have to handle style changes, and it requires keeping some state around so that as a style changes, you know what the last state was before entering prelight. but i have to say that it works, even though i still considered the prelight state as it is currently designed to be a fundamental conceptual error. prelight is an *additional* piece of state information, not an alternative to active/normal/insensitive etc.
(In reply to comment #7) > another update. I finally implemented tim's suggestion. its a bit more work > than he describes - you also have to handle style changes, and it requires > keeping some state around so that as a style changes, you know what the last > state was before entering prelight. but i have to say that it works, Could you add one or more pointers to the commits (for ardour?) of your implementation?
paul, certainly: http://subversion.ardour.org/svn/ardour2/branches/3.0/libs/gtkmm2ext/stateful_button.cc see the 2 methods that start with "avoid_prelight_ ..." probably still a little refinement to do here, but that shows the basic idea.
I think this problem has been solved with state flags