Allow popup menu to be persistent, and support direct window selection

When the user click+hold+release over the icon, the effect we want
is for the menu to stick around.

Also, allow the user to mouse over the actual windows and select
them directly.  If the user mouses over a window, reflect that in
the menu.

https://bugzilla.gnome.org/show_bug.cgi?id=594699
This commit is contained in:
Colin Walters
2009-09-09 21:14:31 -04:00
parent 7ac9fb2dd0
commit 2812c21322
4 changed files with 142 additions and 18 deletions

View File

@ -16,6 +16,9 @@ struct _ShellMenuPrivate {
gboolean popped_up;
gboolean have_grab;
gboolean released_on_source;
ClutterActor *source_actor;
ClutterActor *selected;
};
@ -32,10 +35,10 @@ enum
static guint shell_menu_signals [LAST_SIGNAL] = { 0 };
static gboolean
shell_menu_contains (ShellMenu *box,
ClutterActor *actor)
container_contains (ClutterContainer *container,
ClutterActor *actor)
{
while (actor != NULL && actor != (ClutterActor*)box)
while (actor != NULL && actor != (ClutterActor*)container)
{
actor = clutter_actor_get_parent (actor);
}
@ -83,7 +86,7 @@ shell_menu_enter_event (ClutterActor *actor,
{
ShellMenu *box = SHELL_MENU (actor);
if (!shell_menu_contains (box, event->source))
if (!container_contains (CLUTTER_CONTAINER (box), event->source))
return TRUE;
if (event->source == (ClutterActor*)box)
@ -117,9 +120,21 @@ shell_menu_button_release_event (ClutterActor *actor,
if (event->button != 1)
return FALSE;
if (box->priv->source_actor && !box->priv->released_on_source)
{
if (box->priv->source_actor == event->source ||
(CLUTTER_IS_CONTAINER (box->priv->source_actor) &&
container_contains (CLUTTER_CONTAINER (box->priv->source_actor), event->source)))
{
/* On the next release, we want to pop down the menu regardless */
box->priv->released_on_source = TRUE;
return TRUE;
}
}
shell_menu_popdown_nosignal (box);
if (!shell_menu_contains (CLUTTER_CONTAINER (box), event->source))
if (!container_contains (CLUTTER_CONTAINER (box), event->source))
{
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
return FALSE;
@ -145,6 +160,7 @@ shell_menu_popup (ShellMenu *box,
return;
box->priv->popped_up = TRUE;
box->priv->have_grab = TRUE;
box->priv->released_on_source = FALSE;
clutter_grab_pointer (CLUTTER_ACTOR (box));
}
@ -163,6 +179,45 @@ shell_menu_popdown (ShellMenu *box)
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
}
static void
on_source_destroyed (ClutterActor *actor,
ShellMenu *box)
{
box->priv->source_actor = NULL;
}
/**
* shell_menu_set_persistent_source:
* @box:
* @source: Actor to use as menu origin
*
* This function changes the menu behavior on button release. Normally
* when the mouse is released anywhere, the menu "pops down"; when this
* function is called, if the mouse is released over the source actor,
* the menu stays.
*
* The given @source actor must be reactive for this function to work.
*/
void
shell_menu_set_persistent_source (ShellMenu *box,
ClutterActor *source)
{
if (box->priv->source_actor)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (box->priv->source_actor),
G_CALLBACK (on_source_destroyed),
box);
}
box->priv->source_actor = source;
if (box->priv->source_actor)
{
g_signal_connect (G_OBJECT (box->priv->source_actor),
"destroy",
G_CALLBACK (on_source_destroyed),
box);
}
}
/**
* shell_menu_append_separator:
* @box:
@ -183,12 +238,24 @@ shell_menu_append_separator (ShellMenu *box,
big_box_append (BIG_BOX (box), separator, flags);
}
static void
shell_menu_dispose (GObject *gobject)
{
ShellMenu *self = SHELL_MENU (gobject);
shell_menu_set_persistent_source (self, NULL);
G_OBJECT_CLASS (shell_menu_parent_class)->dispose (gobject);
}
static void
shell_menu_class_init (ShellMenuClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
gobject_class->dispose = shell_menu_dispose;
actor_class->enter_event = shell_menu_enter_event;
actor_class->leave_event = shell_menu_leave_event;
actor_class->button_release_event = shell_menu_button_release_event;

View File

@ -32,6 +32,8 @@ GType shell_menu_get_type (void) G_GNUC_CONST;
void shell_menu_popup (ShellMenu *behavior, guint button, guint32 activate_time);
void shell_menu_set_persistent_source (ShellMenu *behavior, ClutterActor *source);
void shell_menu_append_separator (ShellMenu *behavior, ClutterActor *separator, BigBoxPackFlags flags);
void shell_menu_popdown (ShellMenu *behavior);