Introduce GdkTouchCluster

This is a per-window/device object to gather a group of touch IDs
as a single entity.
This commit is contained in:
Carlos Garnacho
2011-03-01 09:09:59 +01:00
parent 93162f080d
commit 4be23cb80c
8 changed files with 448 additions and 1 deletions

View File

@@ -33,6 +33,7 @@
<xi:include href="xml/windows.xml" />
<xi:include href="xml/events.xml" />
<xi:include href="xml/event_structs.xml" />
<xi:include href="xml/touchcluster.xml" />
<xi:include href="xml/keys.xml" />
<xi:include href="xml/selections.xml" />
<xi:include href="xml/dnd.xml" />

View File

@@ -766,7 +766,6 @@ gdk_event_get_state
gdk_event_get_axis
gdk_event_get_coords
gdk_event_get_root_coords
gdk_event_get_touch_id
gdk_event_request_motions
gdk_events_get_angle
gdk_events_get_center
@@ -846,6 +845,25 @@ gdk_event_get_type
gdk_owner_change_get_type
</SECTION>
<SECTION>
<TITLE>Multitouch</TITLE>
<FILE>touchcluster</FILE>
GdkTouchCluster
gdk_touch_cluster_add_touch
gdk_touch_cluster_remove_touch
gdk_touch_cluster_remove_all
gdk_touch_cluster_set_device
gdk_touch_cluster_get_device
gdk_touch_cluster_get_touches
<SUBSECTION Standard>
GDK_TYPE_TOUCH_CLUSTER
<SUBSECTION Private>
gdk_touch_cluster_get_type
</SECTION>
<SECTION>
<TITLE>Cursors</TITLE>
<FILE>cursors</FILE>

View File

@@ -9,5 +9,6 @@ gdk_display_manager_get_type
gdk_drag_context_get_type
gdk_keymap_get_type
gdk_screen_get_type
gdk_touch_cluster_get_type
gdk_visual_get_type
gdk_window_get_type

View File

@@ -88,6 +88,7 @@ gdk_public_h_sources = \
gdkselection.h \
gdktestutils.h \
gdkthreads.h \
gdktouchcluster.h \
gdktypes.h \
gdkvisual.h \
gdkwindow.h
@@ -129,6 +130,7 @@ gdk_c_sources = \
gdkrgba.c \
gdkscreen.c \
gdkselection.c \
gdktouchcluster.c \
gdkvisual.c \
gdkwindow.c \
gdkwindowimpl.c

View File

@@ -53,6 +53,7 @@
#include <gdk/gdkselection.h>
#include <gdk/gdktestutils.h>
#include <gdk/gdkthreads.h>
#include <gdk/gdktouchcluster.h>
#include <gdk/gdktypes.h>
#include <gdk/gdkvisual.h>
#include <gdk/gdkwindow.h>

View File

@@ -319,6 +319,11 @@ gdk_threads_enter
gdk_threads_init
gdk_threads_leave
gdk_threads_set_lock_functions
gdk_touch_cluster_add_touch
gdk_touch_cluster_get_device
gdk_touch_cluster_get_type G_GNUC_CONST
gdk_touch_cluster_list_touches
gdk_touch_cluster_remove_touch
gdk_unicode_to_keyval G_GNUC_CONST
gdk_utf8_to_string_target
gdk_visibility_state_get_type G_GNUC_CONST

350
gdk/gdktouchcluster.c Normal file
View File

@@ -0,0 +1,350 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2011 Carlos Garnacho <carlosg@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gdktouchcluster.h"
#include "gdkintl.h"
/**
* SECTION:touchcluster
* @Short_description: Multitouch handling
* @Title: Multitouch
* @See_also: #GdkEventMultiTouch
*
* #GdkTouchCluster is an object that gathers touch IDs from a
* touch-enabled slave #GdkDevice, in order to send
* #GdkEventMultiTouch<!-- --> events whenever a contained touch ID
* is updated.
*
* #GdkTouchCluster<!-- -->s are always associated to a window,
* you need to create them through gdk_window_create_touch_cluster(),
* and free them through gdk_window_remove_touch_cluster().
*
* Touch IDs from devices can be obtained from %GDK_TOUCH_PRESS,
* %GDK_TOUCH_MOTION or %GDK_TOUCH_RELEASE events through
* gdk_event_get_touch_id(), and then be added via
* gdk_touch_cluster_add_touch(). Note that touch IDs are
* highly transitive, even be an incrementable number only
* identifying the current touch event stream, so touch IDs
* should always be gotten from these events.
*
* Anytime a touch ID is within a cluster, no %GDK_TOUCH_PRESS,
* %GDK_TOUCH_MOTION or %GDK_TOUCH_RELEASE events will happen
* for the individual touch. The event will be available instead
* as part of the #GdkMultitouchEvent that will be emitted. This
* will hold true until gdk_touch_cluster_remove_touch() is
* called for it. Note that GTK+ will automatically take a
* touch ID out of any cluster if %GDK_TOUCH_RELEASE is gotten
* internally.
*/
typedef struct GdkTouchClusterPrivate GdkTouchClusterPrivate;
struct GdkTouchClusterPrivate
{
GdkDevice *device;
GList *touches;
};
enum {
PROP_0,
PROP_DEVICE
};
enum {
TOUCH_ADDED,
TOUCH_REMOVED,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0 };
static void gdk_touch_cluster_finalize (GObject *object);
static void gdk_touch_cluster_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gdk_touch_cluster_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GdkTouchCluster, gdk_touch_cluster, G_TYPE_OBJECT)
static void
gdk_touch_cluster_class_init (GdkTouchClusterClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gdk_touch_cluster_finalize;
object_class->get_property = gdk_touch_cluster_get_property;
object_class->set_property = gdk_touch_cluster_set_property;
g_object_class_install_property (object_class,
PROP_DEVICE,
g_param_spec_object ("device",
P_("Device"),
P_("Device attached to the cluster"),
GDK_TYPE_DEVICE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
signals[TOUCH_ADDED] =
g_signal_new (g_intern_static_string ("touch-added"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GdkTouchClusterClass, touch_added),
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1, G_TYPE_UINT);
signals[TOUCH_REMOVED] =
g_signal_new (g_intern_static_string ("touch-removed"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GdkTouchClusterClass, touch_removed),
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1, G_TYPE_UINT);
g_type_class_add_private (object_class, sizeof (GdkTouchClusterPrivate));
}
static void
gdk_touch_cluster_init (GdkTouchCluster *cluster)
{
cluster->priv = G_TYPE_INSTANCE_GET_PRIVATE (cluster,
GDK_TYPE_TOUCH_CLUSTER,
GdkTouchClusterPrivate);
}
static void
gdk_touch_cluster_finalize (GObject *object)
{
GdkTouchClusterPrivate *priv;
priv = GDK_TOUCH_CLUSTER (object)->priv;
g_list_free (priv->touches);
G_OBJECT_CLASS (gdk_touch_cluster_parent_class)->finalize (object);
}
static void
gdk_touch_cluster_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkTouchClusterPrivate *priv;
priv = GDK_TOUCH_CLUSTER (object)->priv;
switch (prop_id)
{
case PROP_DEVICE:
gdk_touch_cluster_set_device (GDK_TOUCH_CLUSTER (object),
g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_touch_cluster_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkTouchClusterPrivate *priv;
priv = GDK_TOUCH_CLUSTER (object)->priv;
switch (prop_id)
{
case PROP_DEVICE:
g_value_set_object (value, priv->device);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/**
* gdk_touch_cluster_add_touch:
* @cluster: a #GdkTouchCluster
* @touch_id: a touch ID from a touch event
*
* Adds a touch ID to @cluster, so it will generate a
* %GDK_MULTITOUCH_ADDED event, followed by %GDK_MULTITOUCH_UPDATED
* events whenever this touch ID is updated.
*
* If @touch_id already pertained to another #GdkTouchCluster, it
* will be removed from it, generating a %GDK_MULTITOUCH_REMOVED
* for that another cluster.
**/
void
gdk_touch_cluster_add_touch (GdkTouchCluster *cluster,
guint touch_id)
{
GdkTouchClusterPrivate *priv;
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
priv = cluster->priv;
if (!g_list_find (priv->touches, GUINT_TO_POINTER (touch_id)))
{
priv->touches = g_list_prepend (priv->touches, GUINT_TO_POINTER (touch_id));
g_signal_emit (cluster, signals [TOUCH_ADDED], 0, touch_id);
}
}
/**
* gdk_touch_cluster_remove_touch:
* @cluster: a #GdkTouchCluster
* @touch_id: a touch ID from a touch event
*
* Removes a touch ID from @cluster, generating a %GDK_MULTITOUCH_REMOVED
* event for @cluster, and causing any further input from @touch_id
* to be reported trough %GDK_TOUCH_MOTION events.
*
* <note><para>
* Note that GTK+ automatically removes a touch ID from any cluster
* if a %GDK_TOUCH_RELEASE event is gotten internally.
* </para></note>
**/
void
gdk_touch_cluster_remove_touch (GdkTouchCluster *cluster,
guint touch_id)
{
GdkTouchClusterPrivate *priv;
GList *link;
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
priv = cluster->priv;
link = g_list_find (priv->touches, GUINT_TO_POINTER (touch_id));
if (link)
{
priv->touches = g_list_remove_link (priv->touches, link);
g_signal_emit (cluster, signals [TOUCH_REMOVED], 0, touch_id);
g_list_free1 (link);
}
}
/**
* gdk_touch_cluster_remove_all:
* @cluster: a #GdkTouchCluster
*
* Removes all touch IDs from @cluster.
**/
void
gdk_touch_cluster_remove_all (GdkTouchCluster *cluster)
{
GdkTouchClusterPrivate *priv;
GList *link;
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
priv = cluster->priv;
link = priv->touches;
while (link)
{
priv->touches = g_list_remove_link (priv->touches, link);
g_signal_emit (cluster, signals [TOUCH_REMOVED], 0, link->data);
}
g_list_free (priv->touches);
priv->touches = NULL;
}
/**
* gdk_touch_cluster_get_touches:
* @cluster: a #GdkTouchCluster
*
* Returns a const list of touch IDs as #guint.
*
* Returns: (transfer none): A list of touch IDs.
**/
GList *
gdk_touch_cluster_get_touches (GdkTouchCluster *cluster)
{
GdkTouchClusterPrivate *priv;
g_return_val_if_fail (GDK_IS_TOUCH_CLUSTER (cluster), NULL);
priv = cluster->priv;
return priv->touches;
}
/**
* gdk_touch_cluster_set_device:
* @cluster: a #GdkTouchCluster
* @device: a #GdkDevice
*
* Sets the current device associated to @cluster, all contained
* touch IDs must pertain to this device. As a consequence,
* gdk_touch_cluster_remove_all() will be called on @cluster
* if the current device changes.
**/
void
gdk_touch_cluster_set_device (GdkTouchCluster *cluster,
GdkDevice *device)
{
GdkTouchClusterPrivate *priv;
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
g_return_if_fail (!device || GDK_IS_DEVICE (device));
priv = cluster->priv;
if (priv->device != device)
gdk_touch_cluster_remove_all (cluster);
priv->device = device;
}
/**
* gdk_touch_cluster_get_device:
* @cluster: a #GdkTouchCluster
*
* Returns the slave/floating device this touch cluster pertains to,
* only touch IDs from this device can be included in @cluster.
* the #GdkDevice will typically have the %GDK_SOURCE_TOUCH input source.
*
* Returns: (transfer none): The #GdkDevice generating the contained touch IDs
**/
GdkDevice *
gdk_touch_cluster_get_device (GdkTouchCluster *cluster)
{
GdkTouchClusterPrivate *priv;
g_return_val_if_fail (GDK_IS_TOUCH_CLUSTER (cluster), NULL);
priv = cluster->priv;
return priv->device;
}

69
gdk/gdktouchcluster.h Normal file
View File

@@ -0,0 +1,69 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2011 Carlos Garnacho <carlosg@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GDK_TOUCH_CLUSTER_H__
#define __GDK_TOUCH_CLUSTER_H__
#include <glib-object.h>
#include <gdk/gdkdevice.h>
G_BEGIN_DECLS
#define GDK_TYPE_TOUCH_CLUSTER (gdk_touch_cluster_get_type ())
#define GDK_TOUCH_CLUSTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_TOUCH_CLUSTER, GdkTouchCluster))
#define GDK_IS_TOUCH_CLUSTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_TOUCH_CLUSTER))
typedef struct _GdkTouchCluster GdkTouchCluster;
typedef struct _GdkTouchClusterClass GdkTouchClusterClass;
struct _GdkTouchCluster
{
GObject parent_instance;
gpointer priv;
};
struct _GdkTouchClusterClass
{
GObjectClass parent_class;
void (* touch_added) (GdkTouchCluster *cluster,
guint touch_id);
void (* touch_removed) (GdkTouchCluster *cluster,
guint touch_id);
gpointer padding[16];
};
GType gdk_touch_cluster_get_type (void) G_GNUC_CONST;
void gdk_touch_cluster_add_touch (GdkTouchCluster *cluster,
guint touch_id);
void gdk_touch_cluster_remove_touch (GdkTouchCluster *cluster,
guint touch_id);
void gdk_touch_cluster_remove_all (GdkTouchCluster *cluster);
GList * gdk_touch_cluster_get_touches (GdkTouchCluster *cluster);
void gdk_touch_cluster_set_device (GdkTouchCluster *cluster,
GdkDevice *device);
GdkDevice * gdk_touch_cluster_get_device (GdkTouchCluster *cluster);
G_END_DECLS
#endif /* __GDK_TOUCH_CLUSTER_H__ */