From f08fb83b21f16d2e65821ea30e696d23feb99fa7 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 3 Mar 2012 22:49:43 +0100 Subject: [PATCH] API: Add the basics of the event recognizer implementation --- gtk/Makefile.am | 4 + gtk/gtk.h | 2 + gtk/gtkeventrecognizer.c | 262 ++++++++++++++++++++ gtk/gtkeventrecognizer.h | 104 ++++++++ gtk/gtkeventrecognizerprivate.h | 35 +++ gtk/gtkeventtracker.c | 420 ++++++++++++++++++++++++++++++++ gtk/gtkeventtracker.h | 81 ++++++ gtk/gtkeventtrackerprivate.h | 33 +++ gtk/gtktypes.h | 4 + 9 files changed, 945 insertions(+) create mode 100644 gtk/gtkeventrecognizer.c create mode 100644 gtk/gtkeventrecognizer.h create mode 100644 gtk/gtkeventrecognizerprivate.h create mode 100644 gtk/gtkeventtracker.c create mode 100644 gtk/gtkeventtracker.h create mode 100644 gtk/gtkeventtrackerprivate.h diff --git a/gtk/Makefile.am b/gtk/Makefile.am index e40232edb9..c387b644aa 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -237,6 +237,8 @@ gtk_public_h_sources = \ gtkentrycompletion.h \ gtkenums.h \ gtkeventbox.h \ + gtkeventrecognizer.h \ + gtkeventtracker.h \ gtkexpander.h \ gtkfilechooser.h \ gtkfilechooserbutton.h \ @@ -644,6 +646,8 @@ gtk_base_c_sources = \ gtkentrybuffer.c \ gtkentrycompletion.c \ gtkeventbox.c \ + gtkeventrecognizer.c \ + gtkeventtracker.c \ gtkexpander.c \ gtkfilechooser.c \ gtkfilechooserbutton.c \ diff --git a/gtk/gtk.h b/gtk/gtk.h index de0181b658..04be83b305 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -95,6 +95,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/gtk/gtkeventrecognizer.c b/gtk/gtkeventrecognizer.c new file mode 100644 index 0000000000..11e93d2d73 --- /dev/null +++ b/gtk/gtkeventrecognizer.c @@ -0,0 +1,262 @@ +/* + * Copyright © 2012 Red Hat Inc. + * + * 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.1 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "gtkeventrecognizer.h" +#include "gtkeventrecognizerprivate.h" + +#include "gtkeventtracker.h" +#include "gtkeventtrackerprivate.h" +#include "gtkintl.h" +#include "gtkmarshalers.h" +#include "gtkwidget.h" + +/** + * SECTION:gtkeventrecognizer + * @Short_description: Recognizes gestures from events + * @Title: GtkEventRecognizer + * @See_also: #GtkEventTracker + * + * #GtkEventRecoginzer and its subclasses are used for defining the event + * handling behavior of #GtkWidgets. + * + * #GtkEventRecognizer was added in GTK 3.6. + */ + +enum { + STARTED, + UPDATED, + FINISHED, + CANCELLED, + /* add more */ + LAST_SIGNAL +}; + +guint signals[LAST_SIGNAL]; + +G_DEFINE_ABSTRACT_TYPE (GtkEventRecognizer, gtk_event_recognizer, G_TYPE_OBJECT) + +static void +gtk_event_recognizer_default_recognize (GtkEventRecognizer *recognizer, + GtkWidget *widget, + GdkEvent *event) +{ +} + +static gboolean +gtk_event_recognizer_default_track (GtkEventRecognizer *recognizer, + GtkEventTracker *tracker, + GdkEvent *event) +{ + return FALSE; +} + +static void +gtk_event_recognizer_class_init (GtkEventRecognizerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + klass->tracker_type = GTK_TYPE_EVENT_TRACKER; + + klass->recognize = gtk_event_recognizer_default_recognize; + klass->track = gtk_event_recognizer_default_track; + + /** + * GtkEventRecognizer::started: + * @recognizer: the recognizer + * @tracker: the tracker that was started + * + * Signals that @tracker has started recognizing an event sequence. Widgets + * using @recognizer may now wish to update transient state based on + * @tracker. + * + * From now on, @recognizer will emit GtkEventRecognizer::updated signals + * for @tracker until either the sequence got cancelled via a + * GtkEventRecognizer::cancelled signal emission or successfully recognized + * with a GtkEventRecognizer::finished signal. + */ + signals[STARTED] = + g_signal_new (I_("started"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkEventRecognizerClass, started), + NULL, NULL, + _gtk_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, GTK_TYPE_EVENT_TRACKER); + /** + * GtkEventRecognizer::updated: + * @recognizer: the recognizer + * @tracker: the tracker that was updated + * + * Signals that @tracker has updated its internal state while recognizing + * an event sequence. Widgets using @recognizer may now wish to update + * transient state based on @tracker. + */ + signals[UPDATED] = + g_signal_new (I_("updated"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkEventRecognizerClass, updated), + NULL, NULL, + _gtk_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, GTK_TYPE_EVENT_TRACKER); + /** + * GtkEventRecognizer::finished: + * @recognizer: the recognizer + * @tracker: the tracker that was finished + * + * Signals that @tracker has successfully recognized an event sequence and + * will now stop processing events or change state. Widgets using @recognizer + * should now update their state based on this event based on the information + * provided by @tracker. + * + * This signal will only be emitted after GtkEventRecognizer::started has + * been emitted for @tracker. It might not ever be emitted if @tracker was + * cancelled and GtkEventRecognizer::cancelled has been emitted instead. After + * this signal has been emitted, no new signals will be emitted for @tracker. + */ + signals[FINISHED] = + g_signal_new (I_("finished"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkEventRecognizerClass, finished), + NULL, NULL, + _gtk_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, GTK_TYPE_EVENT_TRACKER); + /** + * GtkEventRecognizer::cancelled: + * @recognizer: the recognizer + * @tracker: the tracker that was cancelled + * + * Signals that @tracker has been cancelled. It will now stop tracking + * events. A widget should now undo all modifications it did due prior signal + * emissions. + * + * This signal will only be emitted after GtkEventRecognizer::started has + * been emitted for @tracker. If it gets emitted, no other events will be emitted + * for @tracker. + */ + signals[CANCELLED] = + g_signal_new (I_("cancelled"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkEventRecognizerClass, cancelled), + NULL, NULL, + _gtk_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, GTK_TYPE_EVENT_TRACKER); +} + +static void +gtk_event_recognizer_init (GtkEventRecognizer *recognizer) +{ +} + +gint +gtk_event_recognizer_class_get_event_mask (GtkEventRecognizerClass *klass) +{ + g_return_val_if_fail (GTK_IS_EVENT_RECOGNIZER_CLASS (klass), 0); + + return klass->event_mask; +} + +void +gtk_event_recognizer_class_set_event_mask (GtkEventRecognizerClass *klass, + gint event_mask) +{ + g_return_if_fail (GTK_IS_EVENT_RECOGNIZER_CLASS (klass)); + + klass->event_mask = event_mask; +} + +GType +gtk_event_recognizer_class_get_tracker_type (GtkEventRecognizerClass *klass) +{ + g_return_val_if_fail (GTK_IS_EVENT_RECOGNIZER_CLASS (klass), 0); + + return klass->tracker_type; +} + +void +gtk_event_recognizer_class_set_tracker_type (GtkEventRecognizerClass *klass, + GType tracker_type) +{ + g_return_if_fail (GTK_IS_EVENT_RECOGNIZER_CLASS (klass)); + g_return_if_fail (g_type_is_a (tracker_type, klass->tracker_type)); + + klass->tracker_type = tracker_type; +} + +void +gtk_event_recognizer_create_tracker (GtkEventRecognizer *recognizer, + GtkWidget *widget, + GdkEvent *event) +{ + GtkEventTracker *tracker; + + g_return_if_fail (GTK_IS_EVENT_RECOGNIZER (recognizer)); + g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget)); + g_return_if_fail (event != NULL); + + tracker = g_object_new (GTK_EVENT_RECOGNIZER_GET_CLASS (recognizer)->tracker_type, + "recognizer", recognizer, + "widget", widget, + NULL); + + _gtk_event_tracker_add (tracker); + _gtk_event_recognizer_track (recognizer, + tracker, + event); +} + +void +_gtk_event_recognizer_recognize (GtkEventRecognizer *recognizer, + GtkWidget *widget, + GdkEvent *event) +{ + GtkEventRecognizerClass *klass; + + g_return_if_fail (GTK_IS_EVENT_RECOGNIZER (recognizer)); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (event != NULL); + + klass = GTK_EVENT_RECOGNIZER_GET_CLASS (recognizer); + + klass->recognize (recognizer, widget, event); +} + +gboolean +_gtk_event_recognizer_track (GtkEventRecognizer *recognizer, + GtkEventTracker *tracker, + GdkEvent *event) +{ + GtkEventRecognizerClass *klass; + + g_return_val_if_fail (GTK_IS_EVENT_RECOGNIZER (recognizer), FALSE); + g_return_val_if_fail (GTK_IS_EVENT_TRACKER (tracker), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (gtk_event_tracker_is_finished (tracker)) + return FALSE; + + klass = GTK_EVENT_RECOGNIZER_GET_CLASS (recognizer); + return klass->track (recognizer, tracker, event); +} + diff --git a/gtk/gtkeventrecognizer.h b/gtk/gtkeventrecognizer.h new file mode 100644 index 0000000000..74c9b0cf2c --- /dev/null +++ b/gtk/gtkeventrecognizer.h @@ -0,0 +1,104 @@ +/* + * Copyright © 2012 Red Hat Inc. + * + * 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.1 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Benjamin Otte + */ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GTK_EVENT_RECOGNIZER_H__ +#define __GTK_EVENT_RECOGNIZER_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_EVENT_RECOGNIZER (gtk_event_recognizer_get_type ()) +#define GTK_EVENT_RECOGNIZER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_EVENT_RECOGNIZER, GtkEventRecognizer)) +#define GTK_EVENT_RECOGNIZER_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_EVENT_RECOGNIZER, GtkEventRecognizerClass)) +#define GTK_IS_EVENT_RECOGNIZER(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_EVENT_RECOGNIZER)) +#define GTK_IS_EVENT_RECOGNIZER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_EVENT_RECOGNIZER)) +#define GTK_EVENT_RECOGNIZER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_EVENT_RECOGNIZER, GtkEventRecognizerClass)) + +typedef struct _GtkEventRecognizerClass GtkEventRecognizerClass; +typedef struct _GtkEventRecognizerPrivate GtkEventRecognizerPrivate; +typedef struct _GtkEventRecognizerClassPrivate GtkEventRecognizerClassPrivate; + +struct _GtkEventRecognizer +{ + GObject parent; + + GtkEventRecognizerPrivate *priv; +}; + +struct _GtkEventRecognizerClass +{ + GObjectClass parent_class; + + /* XXX: Put into private struct */ + gint event_mask; + GType tracker_type; + + void (* recognize) (GtkEventRecognizer *recognizer, + GtkWidget *widget, + GdkEvent *event); + gboolean (* track) (GtkEventRecognizer *recognizer, + GtkEventTracker *tracker, + GdkEvent *event); + + /* signals */ + void (* started) (GtkEventRecognizer *recognizer, + GtkEventTracker *tracker); + void (* updated) (GtkEventRecognizer *recognizer, + GtkEventTracker *tracker); + void (* cancelled) (GtkEventRecognizer *recognizer, + GtkEventTracker *tracker); + void (* finished) (GtkEventRecognizer *recognizer, + GtkEventTracker *tracker); + + /* Padding for future expansion */ + void (*_gtk_reserved0) (void); + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); + void (*_gtk_reserved5) (void); + void (*_gtk_reserved6) (void); + void (*_gtk_reserved7) (void); +}; + +GType gtk_event_recognizer_get_type (void) G_GNUC_CONST; + +gint gtk_event_recognizer_class_get_event_mask (GtkEventRecognizerClass *klass); +void gtk_event_recognizer_class_set_event_mask (GtkEventRecognizerClass *klass, + gint event_mask); +GType gtk_event_recognizer_class_get_tracker_type (GtkEventRecognizerClass *klass); +void gtk_event_recognizer_class_set_tracker_type (GtkEventRecognizerClass *klass, + GType tracker_type); + +void gtk_event_recognizer_create_tracker (GtkEventRecognizer *recognizer, + GtkWidget *widget, + GdkEvent *event); + + +G_END_DECLS + +#endif /* __GTK_EVENT_RECOGNIZER_H__ */ diff --git a/gtk/gtkeventrecognizerprivate.h b/gtk/gtkeventrecognizerprivate.h new file mode 100644 index 0000000000..3724fad3dd --- /dev/null +++ b/gtk/gtkeventrecognizerprivate.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2012 Red Hat Inc. + * + * 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.1 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_EVENT_RECOGNIZER_PRIVATE_H__ +#define __GTK_EVENT_RECOGNIZER_PRIVATE_H__ + +#include + +#include + +void _gtk_event_recognizer_recognize (GtkEventRecognizer *recognizer, + GtkWidget *widget, + GdkEvent *event); +gboolean _gtk_event_recognizer_track (GtkEventRecognizer *recognizer, + GtkEventTracker *tracker, + GdkEvent *event); + +#endif /* __GTK_EVENT_RECOGNIZER_PRIVATE_H__ */ diff --git a/gtk/gtkeventtracker.c b/gtk/gtkeventtracker.c new file mode 100644 index 0000000000..6be59fbd15 --- /dev/null +++ b/gtk/gtkeventtracker.c @@ -0,0 +1,420 @@ +/* + * Copyright © 2012 Red Hat Inc. + * + * 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.1 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "gtkeventtracker.h" + +#include "gtkeventrecognizer.h" +#include "gtkeventrecognizerprivate.h" +#include "gtkintl.h" +#include "gtkwidget.h" + +/** + * SECTION:gtkeventtracker + * @Short_description: Tracks the events from a #GtkEventRecognizer + * @Title: GtkEventTracker + * @See_also: #GtkEventRecognizer + * + * The #GtkEventTracker object - or a subclass of it - is used to track + * sequences of events as recognized by a #GtkEventRecognizer. Once the + * recognizer finds it can potentially identify a sequence of events, it + * creates a #GtkEventTracker and uses it to store information about the + * event. See the event handling howto for a highlevel overview. + * + * #GtkEventTracker was added in GTK 3.6. + */ + + +enum { + PROP_0, + PROP_RECOGNIZER, + PROP_WIDGET +}; + +struct _GtkEventTrackerPrivate { + GtkEventRecognizer *recognizer; + GtkWidget *widget; + + guint started :1; + guint finished :1; + guint cancelled :1; +}; + +G_DEFINE_ABSTRACT_TYPE (GtkEventTracker, gtk_event_tracker, G_TYPE_OBJECT) + +static GQueue trackers = G_QUEUE_INIT; + +static void +gtk_event_tracker_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkEventTracker *tracker = GTK_EVENT_TRACKER (object); + GtkEventTrackerPrivate *priv = tracker->priv; + + switch (prop_id) + { + case PROP_RECOGNIZER: + priv->recognizer = g_value_dup_object (value); + if (priv->recognizer == NULL) + g_critical ("Attempting to construct a `%s' without a recognizer", G_OBJECT_TYPE_NAME (object)); + break; + case PROP_WIDGET: + priv->widget = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_event_tracker_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkEventTracker *tracker = GTK_EVENT_TRACKER (object); + GtkEventTrackerPrivate *priv = tracker->priv; + + switch (prop_id) + { + case PROP_RECOGNIZER: + g_value_set_object (value, priv->recognizer); + break; + case PROP_WIDGET: + g_value_set_object (value, priv->widget); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_event_tracker_dispose (GObject *object) +{ + GtkEventTracker *tracker = GTK_EVENT_TRACKER (object); + GtkEventTrackerPrivate *priv = tracker->priv; + + g_queue_remove (&trackers, tracker); + + g_clear_object (&priv->recognizer); + g_clear_object (&priv->widget); + + G_OBJECT_CLASS (gtk_event_tracker_parent_class)->dispose (object); +} + +static void +gtk_event_tracker_class_init (GtkEventTrackerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gtk_event_tracker_dispose; + object_class->set_property = gtk_event_tracker_set_property; + object_class->get_property = gtk_event_tracker_get_property; + + g_object_class_install_property (object_class, + PROP_RECOGNIZER, + g_param_spec_object ("recognizer", + P_("recognizer"), + P_("Recognizer running this tracker"), + GTK_TYPE_EVENT_RECOGNIZER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, + PROP_WIDGET, + g_param_spec_object ("widget", + P_("widget"), + P_("Widget that spawned this tracker"), + GTK_TYPE_WIDGET, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof (GtkEventTrackerPrivate)); +} + +static void +gtk_event_tracker_init (GtkEventTracker *tracker) +{ + tracker->priv = G_TYPE_INSTANCE_GET_PRIVATE (tracker, + GTK_TYPE_EVENT_TRACKER, + GtkEventTrackerPrivate); +} + +/** + * gtk_event_tracker_get_recognizer: + * @tracker: The event tracker + * + * Gets the recognizer that spawned this @tracker. + * + * Returns: The recognizer that spawned this tracker + * + * @Since: 3.6 + **/ +GtkEventRecognizer * +gtk_event_tracker_get_recognizer (GtkEventTracker *tracker) +{ + g_return_val_if_fail (GTK_IS_EVENT_TRACKER (tracker), NULL); + + return tracker->priv->recognizer; +} + +/** + * gtk_event_tracker_get_widget: + * @tracker: The event tracker + * + * Gets the widget that is affected by this tracker. + * + * Returns: The widget this tracker runs on or %NULL if none. + * + * @Since: 3.6 + **/ +GtkWidget * +gtk_event_tracker_get_widget (GtkEventTracker *tracker) +{ + g_return_val_if_fail (GTK_IS_EVENT_TRACKER (tracker), NULL); + + return tracker->priv->widget; +} + +/** + * gtk_event_tracker_is_cancelled: + * @tracker: The event tracker + * + * Queries if the tracker has been cancelled. A #GtkEventTracker + * can be cancelled for various reasons. See gtk_event_tracker_cancel() + * for details. + * + * Returns: %TRUE if the @tracker has been cancelled + **/ +gboolean +gtk_event_tracker_is_cancelled (GtkEventTracker *tracker) +{ + g_return_val_if_fail (GTK_IS_EVENT_TRACKER (tracker), TRUE); + + return tracker->priv->cancelled; +} + +/** + * gtk_event_tracker_is_started: + * @tracker: The event tracker + * + * Checks if the event tracker is started. An event tracker is + * considered started after the GtkEventRecognizer::started signal + * has been emitted for it. + * + * Returns: %TRUE if the event tracker is started + **/ +gboolean +gtk_event_tracker_is_started (GtkEventTracker *tracker) +{ + g_return_val_if_fail (GTK_IS_EVENT_TRACKER (tracker), TRUE); + + return tracker->priv->started; +} + +/** + * gtk_event_tracker_is_finished: + * @tracker: The event tracker + * + * Checks if the event tracker is finished. An event tracker is + * considered finished when it will not process events or emit + * signals anymore. At that point, the GtkEventRecognizer::finished + * or GtkEventRecognizer::cancelled signal will have been emitted + * for @recognizer. + * + * Returns: %TRUE if the event tracker is finished + **/ +gboolean +gtk_event_tracker_is_finished (GtkEventTracker *tracker) +{ + g_return_val_if_fail (GTK_IS_EVENT_TRACKER (tracker), TRUE); + + return tracker->priv->finished; +} + +/** + * gtk_event_tracker_cancel: + * @tracker: The event tracker + * + * Cancels the event tracker if the event tracker is not finished yet. + * If the event tracker was already finished, this function returns + * immediately. + * + * Cancelling an event tracker will cause the + * GtkEventRecognizer::cancelled signal to be emitted and the @tracker + * will not process any new events. + **/ +void +gtk_event_tracker_cancel (GtkEventTracker *tracker) +{ + GtkEventTrackerPrivate *priv; + + g_return_if_fail (GTK_IS_EVENT_TRACKER (tracker)); + + priv = tracker->priv; + + if (priv->finished) + return; + + priv->finished = TRUE; + priv->cancelled = TRUE; + + if (priv->started) + g_signal_emit_by_name (priv->recognizer, + "cancelled", + tracker); + else + priv->started = TRUE; + + /* release the reference from adding the tracker upon construction */ + g_object_unref (tracker); +} + +/** + * gtk_event_tracker_start: + * @tracker: The tracker to start + * + * Emits the GtkEventRecognizer::started signal for the @tracker. This + * signal should be emitted when @tracker should be made public and + * widgets using it might want to provide feedback for an impending event + * recognition. + * + * This function should only be called by #GtkEventRecognizer + * implementations. + **/ +void +gtk_event_tracker_start (GtkEventTracker *tracker) +{ + GtkEventTrackerPrivate *priv; + + g_return_if_fail (GTK_IS_EVENT_TRACKER (tracker)); + + priv = tracker->priv; + if (priv->started) + return; + + priv->started = TRUE; + + g_signal_emit_by_name (priv->recognizer, + "started", + tracker); +} + +/** + * gtk_event_tracker_update: + * @tracker: The tracker to update + * + * Emits the GtkEventRecognizer::updated signal for the @tracker. This + * signal should be emitted when @tracker has updated its state and + * widgets might want to update their state based on it. + * + * This function should only be called by #GtkEventRecognizer + * implementations. + **/ +void +gtk_event_tracker_update (GtkEventTracker *tracker) +{ + GtkEventTrackerPrivate *priv; + + g_return_if_fail (GTK_IS_EVENT_TRACKER (tracker)); + + priv = tracker->priv; + + g_object_ref (tracker); + + gtk_event_tracker_start (tracker); + + if (priv->finished) + return; + + g_signal_emit_by_name (priv->recognizer, + "updated", + tracker); + + g_object_unref (tracker); +} + +/** + * gtk_event_tracker_finish: + * @tracker: The event tracker + * + * Marks the event tracker as finished and emits the + * GtkEventRecognizer::finished signal. If the @tracker has + * already been finished, nothing happens. + * + * This function should only be called by #GtkEventRecognizer + * implementations. + **/ +void +gtk_event_tracker_finish (GtkEventTracker *tracker) +{ + GtkEventTrackerPrivate *priv; + + g_return_if_fail (GTK_IS_EVENT_TRACKER (tracker)); + + priv = tracker->priv; + + if (priv->finished) + return; + + priv->finished = TRUE; + + if (priv->started) + g_signal_emit_by_name (priv->recognizer, + "finished", + tracker); + + /* release the reference from adding the tracker upon construction */ + g_object_unref (tracker); +} + +void +_gtk_event_tracker_add (GtkEventTracker *tracker) +{ + g_queue_push_tail (&trackers, tracker); +} + +gboolean +_gtk_event_trackers_invoke (GdkEvent *event) +{ + GList *list; + gboolean eat_event = FALSE; + + g_return_val_if_fail (event != NULL, FALSE); + + list = g_queue_peek_head_link (&trackers); + while (list) + { + GtkEventTracker *tracker = list->data; + + g_object_ref (tracker); + + eat_event |= _gtk_event_recognizer_track (tracker->priv->recognizer, + tracker, + event); + + list = list->next; + g_object_unref (tracker); + } + + return eat_event; +} diff --git a/gtk/gtkeventtracker.h b/gtk/gtkeventtracker.h new file mode 100644 index 0000000000..f7fe59315f --- /dev/null +++ b/gtk/gtkeventtracker.h @@ -0,0 +1,81 @@ +/* + * Copyright © 2012 Red Hat Inc. + * + * 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.1 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Benjamin Otte + */ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GTK_EVENT_TRACKER_H__ +#define __GTK_EVENT_TRACKER_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_EVENT_TRACKER (gtk_event_tracker_get_type ()) +#define GTK_EVENT_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_EVENT_TRACKER, GtkEventTracker)) +#define GTK_EVENT_TRACKER_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_EVENT_TRACKER, GtkEventTrackerClass)) +#define GTK_IS_EVENT_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_EVENT_TRACKER)) +#define GTK_IS_EVENT_TRACKER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_EVENT_TRACKER)) +#define GTK_EVENT_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_EVENT_TRACKER, GtkEventTrackerClass)) + +typedef struct _GtkEventTrackerClass GtkEventTrackerClass; +typedef struct _GtkEventTrackerPrivate GtkEventTrackerPrivate; + +struct _GtkEventTracker +{ + GObject parent; + + GtkEventTrackerPrivate *priv; +}; + +struct _GtkEventTrackerClass +{ + GObjectClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved0) (void); + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); + void (*_gtk_reserved5) (void); + void (*_gtk_reserved6) (void); + void (*_gtk_reserved7) (void); +}; + +GType gtk_event_tracker_get_type (void) G_GNUC_CONST; + +GtkEventRecognizer * gtk_event_tracker_get_recognizer (GtkEventTracker *tracker); +GtkWidget * gtk_event_tracker_get_widget (GtkEventTracker *tracker); + +gboolean gtk_event_tracker_is_started (GtkEventTracker *tracker); +gboolean gtk_event_tracker_is_finished (GtkEventTracker *tracker); +gboolean gtk_event_tracker_is_cancelled (GtkEventTracker *tracker); + +void gtk_event_tracker_cancel (GtkEventTracker *tracker); + +void gtk_event_tracker_start (GtkEventTracker *tracker); +void gtk_event_tracker_update (GtkEventTracker *tracker); +void gtk_event_tracker_finish (GtkEventTracker *tracker); + +G_END_DECLS + +#endif /* __GTK_EVENT_TRACKER_H__ */ diff --git a/gtk/gtkeventtrackerprivate.h b/gtk/gtkeventtrackerprivate.h new file mode 100644 index 0000000000..dbc8999794 --- /dev/null +++ b/gtk/gtkeventtrackerprivate.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2012 Red Hat Inc. + * + * 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.1 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_EVENT_TRACKER_PRIVATE_H__ +#define __GTK_EVENT_TRACKER_PRIVATE_H__ + +#include + +#include + +void _gtk_event_tracker_add (GtkEventTracker *tracker); + +gboolean _gtk_event_trackers_invoke (GdkEvent *event); + + +#endif /* __GTK_EVENT_TRACKER_PRIVATE_H__ */ diff --git a/gtk/gtktypes.h b/gtk/gtktypes.h index b3eade30a5..7e2b0b13ed 100644 --- a/gtk/gtktypes.h +++ b/gtk/gtktypes.h @@ -29,10 +29,14 @@ #ifndef __GTK_TYPES_H__ #define __GTK_TYPES_H__ +#include + G_BEGIN_DECLS typedef struct _GtkAdjustment GtkAdjustment; typedef struct _GtkClipboard GtkClipboard; +typedef struct _GtkEventRecognizer GtkEventRecognizer; +typedef struct _GtkEventTracker GtkEventTracker; typedef struct _GtkIconSet GtkIconSet; typedef struct _GtkIconSource GtkIconSource; typedef struct _GtkRcStyle GtkRcStyle;