Codebase list dillo / debian/0.8.6-3 src / gtk_ext_menu.c
debian/0.8.6-3

Tree @debian/0.8.6-3 (Download .tar.gz)

gtk_ext_menu.c @debian/0.8.6-3raw · history · blame

/*
 * File: selection.c
 *
 * Copyright 2004 Sebastian Geerken <s.geerken@ping.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

/*
 * This widget, which is a variant of GtkMenu, works together with
 * GtkExtMenuItem. Together, they add the possibility to react on different
 * mouse buttons, for activating the menu items.
 *
 * If an item is activated by the mouse, the signals "activate1", "activate2",
 * and "activate3" are emitted. The signal "activate" should still be regarded,
 * since it is emitted (by the base classes), when an item was activated by
 * other input devices, e.g. the keyboard.
 *
 * Some notes about the implementation: Normally, mouse events are handled
 * by GtkMenu, not by GtkMenuItem. GtkMenu will call gtk_widget_activate(),
 * which emits the activate signal. For GtkMenuItem, this is "activate".
 *
 * GtkExtMenu changes dealing with release events a bit: if the affected
 * menu item is a GtkExtMenuItem, it is told to handle this event specially.
 * The GtkExtMenuItem will simply change its activate signal temporally.
 *
 * (This is a bit ugly, but still cleaner than listening to the low-level
 * events, like "button-release-event".)
 */

#include "gtk_ext_menu.h"
#include "gtk_ext_menu_item.h"
#include <gtk/gtkmenuitem.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>

static void Gtk_ext_menu_class_init       (GtkExtMenuClass *klass);
static void Gtk_ext_menu_init             (GtkExtMenu *menu);

static gint Gtk_ext_menu_button_release   (GtkWidget *widget,
                                           GdkEventButton *event);

static GtkMenuClass *parent_class = NULL;


/*
 * Standard Gtk+ function.
 */
GtkType a_Gtk_ext_menu_get_type (void)
{
   static GtkType type = 0;

   if (!type) {
      GtkTypeInfo info = {
         "GtkExtMenu",
         sizeof (GtkExtMenu),
         sizeof (GtkExtMenuClass),
         (GtkClassInitFunc) Gtk_ext_menu_class_init,
         (GtkObjectInitFunc) Gtk_ext_menu_init,
         (GtkArgSetFunc) NULL,
         (GtkArgGetFunc) NULL,
         (GtkClassInitFunc)NULL
      };

      type = gtk_type_unique (gtk_menu_get_type (), &info);
   }

   return type;
}


/*
 * Standard Gtk+ function.
 */
static void Gtk_ext_menu_class_init (GtkExtMenuClass *klass)
{
   GtkWidgetClass *gtk_widget_class;

   parent_class = gtk_type_class (gtk_menu_get_type ());

   gtk_widget_class = (GtkWidgetClass*) klass;
   gtk_widget_class->button_release_event = Gtk_ext_menu_button_release;
}


/*
 * Standard Gtk+ function.
 */
static void Gtk_ext_menu_init (GtkExtMenu *menu)
{
}


/*
 * Create a new GtkExtMenu.
 */
GtkWidget* a_Gtk_ext_menu_new (void)
{
   return gtk_type_new (a_Gtk_ext_menu_get_type ());
}


/*
 * Copied from Gtk+ 1.2.10, file "menu_shell.c", function
 * gtk_menu_shell_is_item.
 */
static gint Gtk_ext_menu_is_item (GtkMenuShell *menu_shell,
                                  GtkWidget *child)
{
   GtkWidget *parent;

   g_return_val_if_fail (menu_shell != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_MENU_SHELL (menu_shell), FALSE);
   g_return_val_if_fail (child != NULL, FALSE);

   parent = child->parent;
   while (parent && GTK_IS_MENU_SHELL (parent)) {
      if (parent == (GtkWidget*) menu_shell)
         return TRUE;
      parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
   }

   return FALSE;
}

/*
 * Copied from Gtk+ 1.2.10, file "menu_shell.c", function
 * gtk_menu_shell_get_item.
 */
static GtkWidget* Gtk_ext_menu_get_item (GtkMenuShell *menu_shell,
                                         GdkEvent *event)
{
   GtkWidget *menu_item;

  menu_item = gtk_get_event_widget ((GdkEvent*) event);

  while (menu_item && !GTK_IS_MENU_ITEM (menu_item))
     menu_item = menu_item->parent;

  if (menu_item && Gtk_ext_menu_is_item (menu_shell, menu_item))
     return menu_item;
  else
     return NULL;
}


/*
 * Standard Gtk+ function.
 */
static gint Gtk_ext_menu_button_release (GtkWidget *widget,
                                         GdkEventButton *event)
{
   GtkWidget *menu_item;
   gint return_value;

   menu_item = Gtk_ext_menu_get_item (GTK_MENU_SHELL (widget),
                                      (GdkEvent*) event);
   if (menu_item != NULL && GTK_IS_EXT_MENU_ITEM (menu_item))
      p_Gtk_ext_menu_item_prepare_button_release (GTK_EXT_MENU_ITEM(menu_item),
                                                  event);
   return_value =
      GTK_WIDGET_CLASS(parent_class)->button_release_event (widget, event);
   if (menu_item != NULL && GTK_IS_EXT_MENU_ITEM (menu_item))
      p_Gtk_ext_menu_item_finish_button_release (GTK_EXT_MENU_ITEM (menu_item),
                                                 event);
   return return_value;
}