GtkMenuShell::selection-done



hi owen,

as you may remeber, i introduced the ::selction-done signal to provide
a callback mechanism to be emitted after popup menus got poped down
*and* the menu item got activated. the intend here is to set certain
popup related data on the menu, pop it up and later catch selection-done
to destroy the popup data again.
however, that doesn't correctly work with the current
gtk_menu_shell_activate_item() if the popup menu contains submenus, as the
selection-done signal will then only be emitted for the submenu and the
selection-done signal on the popup menu is never triggered.
i'm not sure whether this used to work in my initial implementation,
but be have to do something about that, one way or the other.
i (locally) currently do:

Mon May 10 04:20:41 1999  Tim Janik  <timj@gtk.org>

        * gtk/gtkmenushell.c (gtk_menu_shell_activate_item): propagate
        ::selection-done emissions up to the topmost menu shell.

i.e.:
void
gtk_menu_shell_activate_item (GtkMenuShell      *menu_shell,
                              GtkWidget         *menu_item,
                              gboolean           force_deactivate)
{
  GSList *slist, *shells = NULL;
  gboolean deactivate = force_deactivate;

  g_return_if_fail (menu_shell != NULL);
  g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
  g_return_if_fail (menu_item != NULL);
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));

  if (!deactivate)
    deactivate = GTK_MENU_ITEM_CLASS (GTK_OBJECT (menu_item)->klass)->hide_on_activate;

  gtk_widget_ref (GTK_WIDGET (menu_shell));

  if (deactivate)
    {
      GtkMenuShell *parent_menu_shell = menu_shell;

      do
        {
          gtk_widget_ref (GTK_WIDGET (parent_menu_shell));
          shells = g_slist_prepend (shells, parent_menu_shell);
          parent_menu_shell = (GtkMenuShell*) parent_menu_shell->parent_menu_shell;
        }
      while (parent_menu_shell);
      shells = g_slist_reverse (shells);

      gtk_menu_shell_deactivate (menu_shell);

      /* flush the x-queue, so any grabs are removed and
       * the menu is actually taken down
       */
      gdk_flush ();
    }

  gtk_widget_activate (menu_item);

  for (slist = shells; slist; slist = slist->next)
    {
      gtk_signal_emit (slist->data, menu_shell_signals[SELECTION_DONE]);
      gtk_widget_unref (slist->data);
    }
  g_slist_free (shells);

  gtk_widget_unref (GTK_WIDGET (menu_shell));
}

but i'm not too sure whether we'd want it this way, it might be better
to change ::selection_done to GTK_RUN_LAST and then propagate the signal
emission up to ->parent_menu_shell in a gtk_menu_shell_selection_done()
class handler, so users can intercept the process if they know what
they are doing (in order to get that to work, we'd have to move
  menu_shell->parent_menu_shell = NULL;
out of gtk_menu_shell_deactivate() into the gtk_menu_shell_selection_done()
handler).

what's your stance on this subject (i'd *really* like to see this fixed
in 1.2.3, as the current gtk_item_factory_popup_with_data() simply
leaks memory with the current approach, and menu item activation
through accelerators may refer to stale invalid popup data).

---
ciaoTJ



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