Re: Accelerators and gtk_grab_add



hi matt,

sorry for replying to your email in public, but this is the
second private email on this topic and both raise the same
point which actually results out of a misconception in
gtk (which is also why i put gtk-devel on the Cc: list).
i'll first quote my reply to that other email, since
it pretty much covers the issue already:

On Thu, 27 Jul 2000, Tim Janik wrote:

> On Thu, 27 Jul 2000, <someone> wrote:
> 
> > On Thu, 27 Jul 2000, Tim Janik wrote:
> 
> > > > Hmmm...  I may be misunderstanding your proposed solution.  The reason I used
> > > > gtk_accel_group_default() is because that is where the user defined
> > > > accelerators for the menus wind up.  Here is the substitution if you would like
> > > > to see it.
> > > 
> > 
> > > what do you mean "that is where the user defined accelerators for the menus
> > > wind up"? who would put them there except you?
> > 
> > Exactemundo! But then, can you explain why menu's created with
> > GtkItemFactory allow users to change the accelerators?
> 
> that's a generic feature not limited to teh item factory.
> the item factory just does a few extra things:
> 
> 1) provides a simple interface to setup a mass of menu items
>    in a hirachy
> 2) maintains a global hash table for
>    menupath (string) <-> accelerator (string)
>    association
> 3) provides functions to read in and write out that global
>    hash table to from rc files
> 4) override accelerator specifications in 1) according to
>    loaded data stored in 2)
> 5) keep 2) uptodate according to runtime changes made by the
>    user, so the updated data is kept persistent across
>    programm invokations using the functions from 3)
> 
> the ability to change accelerators at runtime is implemented in GtkMenu
> actually, it either eplaces the existing accelerator of a menu item
> in the accel group that the accelerator is stored in, or if there's
> no accelerator >> uses the global default accelerator group <<.
> 
> now writing that out, i actually see your problem ;)
> for 2.0, i'll probably change that use the corresonding
> menu's accelerator group instead of the global
> accelerator group, since that behaviour is hardly desired ;)
> but that carries the problem of that accelerator group not
> neccessarily being installed on the corresponding window,
> which would make the accelerator appear on the GUI but
> not work ;(
> 
> hm, gotta ponder this a bit more, i'm kinda getting
> a feeling that the explicit add_accel_group() call
> on windows/menus we currently require might not be
> the all and end of it... ;)
>
> ---
> ciaoTJ


On Wed, 26 Jul 2000, Matt Carlson wrote:

> > what do you mean "that is where the user defined accelerators for the
> > menus wind up"? who would put them there except you?
> 
> Sorry.  I guess I wasn't too clear here.  If you remove the
> gtk_widget_add_accelerator() line you highlighted in your 1st response and
> then run the program, the menu item "Do Something" will accept user
> keystrokes which dynamically seta the key accelerator for that menu item.  I
> like this behavior and would like to keep it.
> 
> Here's where I get confused.  How do I tell gtk that I would like a group of
> widgets to be a part of an accelerator group, but not assign their
> accelerator keys (i.e. leave it to the user)?  To phrase the question from
> another perspective, how to I tell gtk not to assign whatever accelerator
> the user sets to the default accelerator, but to an accelerator that I can
> turn off when displaying a modal dialog?  The answers to these questions are
> what I'm trying to get from the discussion.
> 
> I apoligize for being a thorn.

you haven't, instead, i should have figured the issue earlier ;)

as written above gtkmenu.c handles the accelerator installation.
if the item factory is used, it automatically assures every menu gets
the factory's accel group and that is added to the main window.
that's also where newly added accelerators end up, so they are kept
per-window.
if a gtkmenu is created manually, it doesn't have that accelerator group
though, and it can't create it on demand, since it wouldn't know what
menu to add it to (it could be a popup menu that doesn't have the window(s)
it is used in it's runtime widget tree as an anchestor).

so instead it uses the global default accelerator group, returned from
gtk_accel_group_get_default(). every window resorts to that group if it
couldn't find an accelerator binding for a key being pressed. that's why
you have window A where the user installed a new accelerator on menu
item A.m, and then popup a modal dialog B that resorts to activating
A.m if the accelerator is pressed.

as a workaround for 1.2.x, follow my advice as far as i gave it, and
do one extra thing ;)
the accel group that you create per menu bar has to be added to all
menus you create, so they don't store the new accelerators in the
global default group. you do that by ading to your code, such as:

w = window_new ();
mb = menu_bar_new ();
mb_ag = gtk_accel_group_new ();
add (w, mb);
gtk_window_add_accel_group (w, mb_ag);
mi = menu_item_new ();
ad (mb, mi);
m = menu_new ();
gtk_menu_item_set_submenu (mi, m);
gtk_accel_group_unref (mb_ag);

an extra call, right after menu creation:

 w = window_new ();
 mb = menu_bar_new ();
 mb_ag = gtk_accel_group_new ();
 add (w, mb);
 gtk_window_add_accel_group (w, mb_ag);
 mi = menu_item_new ();
 ad (mb, mi);
 m = menu_new ();
+gtk_menu_set_accel_group (m, mb_ag);
 gtk_menu_item_set_submenu (mi, m);
 gtk_accel_group_unref (mb_ag);


---
ciaoTJ





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