mutter/clutter/clutter/clutter-action.c
Carlos Garnacho fe9fff2729 clutter: Make detached actions let events through
Actions might get detached sometime during event processing,
at a time that the stage did already prepare an emission chain
holding references to the actions and actors that need to handle
events. This means actions might become detached, but still handle
the incoming event, or possible crossing events generated in-place
when the actor becomes unparented.

Avoid this situation, by skipping event handling on actions that
went detached, we will just instruct to continue event processing.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3988>
2024-08-30 17:24:24 +00:00

148 lines
4.2 KiB
C

/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
/**
* ClutterAction:
*
* Abstract class for event-related logic
*
* #ClutterAction is an abstract base class for event-related actions that
* modify the user interaction of a [class@Actor], just like
* [class@Constraint] is an abstract class for modifiers of an actor's
* position or size.
*
* Implementations of #ClutterAction are associated to an actor and can
* provide behavioral changes when dealing with user input - for instance
* drag and drop capabilities, or scrolling, or panning - by using the
* various event-related signals provided by [class@Actor] itself.
*/
#include "config.h"
#include "clutter/clutter-action.h"
#include "clutter/clutter-action-private.h"
#include "clutter/clutter-debug.h"
#include "clutter/clutter-private.h"
typedef struct _ClutterActionPrivate ClutterActionPrivate;
struct _ClutterActionPrivate
{
ClutterEventPhase phase;
};
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterAction, clutter_action,
CLUTTER_TYPE_ACTOR_META)
static gboolean
clutter_action_handle_event_default (ClutterAction *action,
const ClutterEvent *event)
{
return FALSE;
}
static void
clutter_action_class_init (ClutterActionClass *klass)
{
klass->handle_event = clutter_action_handle_event_default;
}
static void
clutter_action_init (ClutterAction *self)
{
}
void
clutter_action_set_phase (ClutterAction *action,
ClutterEventPhase phase)
{
ClutterActionPrivate *priv;
priv = clutter_action_get_instance_private (action);
priv->phase = phase;
}
ClutterEventPhase
clutter_action_get_phase (ClutterAction *action)
{
ClutterActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTION (action), CLUTTER_PHASE_CAPTURE);
priv = clutter_action_get_instance_private (action);
return priv->phase;
}
gboolean
clutter_action_handle_event (ClutterAction *action,
const ClutterEvent *event)
{
gboolean retval = CLUTTER_EVENT_PROPAGATE;
g_object_ref (action);
if (clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)))
retval = CLUTTER_ACTION_GET_CLASS (action)->handle_event (action, event);
g_object_unref (action);
return retval;
}
void
clutter_action_sequence_cancelled (ClutterAction *action,
ClutterInputDevice *device,
ClutterEventSequence *sequence)
{
ClutterActionClass *action_class = CLUTTER_ACTION_GET_CLASS (action);
if (action_class->sequence_cancelled)
action_class->sequence_cancelled (action, device, sequence);
}
gboolean
clutter_action_register_sequence (ClutterAction *self,
const ClutterEvent *event)
{
ClutterActionClass *action_class = CLUTTER_ACTION_GET_CLASS (self);
if (action_class->register_sequence)
return action_class->register_sequence (self, event);
return TRUE;
}
int
clutter_action_setup_sequence_relationship (ClutterAction *action_1,
ClutterAction *action_2,
ClutterInputDevice *device,
ClutterEventSequence *sequence)
{
ClutterActionClass *action_class = CLUTTER_ACTION_GET_CLASS (action_1);
if (action_class->setup_sequence_relationship)
return action_class->setup_sequence_relationship (action_1, action_2, device, sequence);
return 0;
}