Re: uline accels, aka. mnemonic activators



Tim Janik <timj gtk org> writes:

> On 16 Mar 2001, Owen Taylor wrote:
> 
> > 
> > Hi Tim,
> > 
> > I would agree with you that mnemonic's and menu accelerators are
> > somewhat different:
> > 
> >  - Mnemonics have different conflict resolution behavior
> >  - The dynamic-accelerator-changing code in GtkMenu isn't necessary for mnemonic.
> 
> and most important probably is the different visibility related behaviour.
> 
> > But in essence, GtkAccelGroup is just a fancy hash from keyval/modifiers
> > to action, and that's what we need for mnemonics. I don't think
> > introducing a separate, unrelated mechanism for mnemonics is
> > less confusing or simpler.
> > 
> > >From the point of view of the average programmer, GtkAccelGroup actually
> > looks very simple:
> > 
> >  - Create an accelgroup
> >  - Connect keyval/modifiers to actions within that accelgroup
> >  - Attach the accelgroup to a toplevel, to add those keyvals/modifiers
> >    to set of keys that are handled globally on the window.
> > 
> > This same high level view makes perfect sense for mnemonics as well.
> 
> it doesn't quite. mnemonics are fine to set on leaf widgets and expect
> them to get automatically carried over e.g. if reparenting.

In both your proposal and mine, this is handled by the mnemonic
widget - that is, the label.
 
> > So, all we need is a global toggle indicating whether this accel
> > group holds mnemonics or menu accelerators. Sure, this internally
> > complicates the accelerator group a bit, but you certainly
> > arent' scared of a little implementation complexity ;-)
> 
> not just internally, internally it means that the accel group
> code has to become quite clever about widgets, knowing visibility.
> externally though that means means that an accel group entry
> suddenly turns into a list and API such as unlock_entry is suddenly
> utterly useless.

Internally doesn't really matter; I mean, Alex already wrote
the code. And, to tell the truth, I don't think anybody but
you think GtkAccelGroup is simple or intuitive now if they
start looking at the details.
 
> > The other possibility would be to have gtk_accel_group_add_mnemonic() 
> > and make the distinction a per-entry thing. Perhaps that would
> > seem a bit simpler than having separate accel groups with a
> > global behavior toggle.
> 
> no, that has still the same problems.
> 
> > The point here is keeping the number of independent unrelated concepts
> > that the programmer needs to know to use GTK+ to a minimum.
> 
> eh? lemme give an anonymous quote that i think you'd also agree with: ;)
> 
>  > So, I think a clean design that involves a small new concept
>  > is better than what appear to be essentially a hack.

Sure, that's a design principle that I'm not going to disagree with ;-)
But the exact applicability depends on the degree of smallness,
newness, and hackness. 
 
> > Other reasons for using accelerator groups instead of making up
> > a new concept:
> > 
> >  - To properly handle keyboards with multiple groups (say, a Russina
> >    keyboard) need to be doing somewhat sophisticated resolution
> >    of key presses. 
> 
> there's nothing you'd gain from using an accel group here.
> 
> >    It would be better not to duplicate this code more than possible,
> 
> there's really not much duplication here, as mnemonics need to be handled
> way differently than accelerators, you have to figure visibility and
> ancestry propagation and conflict resolution at activation time, which
> is way different than accelerator overrides due to conflicts at
> installation time.

I think I wasn't clear about the problem I was talking about:taking a
set of modifier keys and a keycode and figuring out what
modifier/accelerator combo to activate. Conflicts between identical
modifier/accelerator combos aren't the problem.

In particular, if I have only an accelerator:

 <alt>a

Then I want to activate it when the user types <alt>Cyrillic_ef,
since that is the same key when the keyboard is in Russian
mode. But, if there is also an accelerator <alt>Cyrillic_ef, then
these need to be distinguished.

> >    and furthermore the resolution can be done better the more you
> >    know about what accelerators are available. For instance,
> >    on a US keyboard, you might want to treat <Ctrl>= as the same as   
> >    <Ctrl>+ if only one was bound to an accelerator, but separate
> >    them if both are bound.
> 
> that can go into our general gtk_accelerator_*() namespace, these
> kind of key alias issues have to be handled differently for
> mnemonics anyways as they indicate duplicate entries that still
> do not conflict. btw, that's an implementation detail that's not API
> visible, so i wouldn't worry too much about this.

This type of conflict resolution requires a global view of
what is installed - that is, it requires a data structure
that is a big table of installed accelerators - GtkAccelGroup
is that 
 
> >  - Enhancements like per-entry data are also needed for GtkAccelGroup
> >    and we shouldn't have to keep changing both APIs in parallel.
> 
> i'm sorry, but data extensions for accel groups would break serialization.

Serialization? I don't think you mean gtk_item_factory_dump_items(),
since that only dumps path and accelerator.... and I'm not sure
what else you woudl be referring to.

> accelerators are in place to "activate" a widget argumentless, we sat down
> at some point to cover more sophisticated keybinding setupd, and GtkBinding
> steemed out of that. if we're missing globally parameterized key bindings,
> that's (which we do) to be fixed on the GtkBindings side.
> accel groups are for user-changable and serializable widget activations
> that are unique within a dialog, once you start adding parameters or
> riddle with uniqueness of the accelerators, the concept breaks and that
> shows itself in inconsistent API and also has bad effects on thngs like
> serialization or negotiation.

Yes, I remember the discussion we had about whether we could use
a single mechanism for GtkBinding and GtkAccelGroup.

The main distinctions that caused us not to do that were:

 - Per class vs. per instance
 - Actions on one widget vs. actions on many widgets

The question of how many signal arguments wasn't really the point.
But just because we have two types of tables of key bindings, doesn't
mean we need a third.
 
> >  - For GtkPlug, I need to keep track of _all_ globally trapped 
> >    keystrokes and forward them to the parent GtkWindow.
> 
> right, and you better handle mnemonics differently from accelerators
> there, since acclerators are always globally trapped, while mnemonics
> depend on visibility.

>From the perspective of plug/socket, where the plug doesn't know anything
about the accelerators inside the socket, accelerators are no difference
between always-viewable mnemonis.
 
> > So, yes, mnemonics are somewhat different from menu accelerators, 
> > but in the end, they are globally trapped keystrokes, GtkAccelGroup
> > is how we handle globally trapped keystrokes, and I don't think
> > it makes sense to introduce a new parallel mechanism.
> 
> 
> well first, the API to install either of them is proposed different already,
> i.e. you'd do gtk_label_new_with_mnemonic ("My _Label"); and want that
> to work (e.g. as child of a menu item), while for accelerators, you
> have to specify it in the item factory "Ctrl+X" or directly via
> gtk_widget_add_accelerator() which wants accel flags that don't apply to
> mnemonics and wants a signal_id that's also odd for mnemonics which need
> their (widget, mnemonic_group, activate_data) signal.

I think the assumption is that the average programmer will never use the
GtkAccelGroup API for either purpose, so we are debating internal
mechanism.

But the internal mechanism will appear in the API docs, so I'd
like it to be as consistent, compact and sensible as possible.

> for mnemonics the user shouldn't specify modifiers, instead we pick either
> none or Alt depending on whether the mnemonic is used inside a menubar, etc.
> the two things are quite different, even in existing API.

This could be handled multiple ways within the framework I presented;
as simply as having the label check the type of toplevel, or in
a more sophisticated manner. Either way, you need an API to say
what the mnemonic modifiers should be.
 
> so yeah, additional API will be introduced to install mnemonics but that's
> hardly too complex for the user. either people use the convenient "_Action"
> way in item factory entries and labels, or they'll have to do some
> gtk_mnemonic_activator_add (window, keyval, modifier, activate_data);
> in ::heirarchy_changed.
> while that function could even be internally and the only public API
> we provide would be:
> 
> gtk_widget_add_mnemonic (widget, keyval, data);
> 
> which does automatic (re-)installation on ::heirarchy_changed and
> picks a modifier on its own.

This is, (IMO) just kludging up GtkWidget more.

I guess my basic feeling here is that we need a consistent framework
for handling global keystrokes, not 3 or 5 or whatever.

Regards,
                                        Owen




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]