2
* Copyright 2010 Canonical, Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of either or both of the following licenses:
7
* 1) the GNU Lesser General Public License version 3, as published by the
8
* Free Software Foundation; and/or
9
* 2) the GNU Lesser General Public License version 2.1, as published by
10
* the Free Software Foundation.
12
* This program is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranties of
14
* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
15
* PURPOSE. See the applicable version of the GNU Lesser General Public
16
* License for more details.
18
* You should have received a copy of both the GNU Lesser General Public
19
* License version 3 and version 2.1 along with this program. If not, see
20
* <http://www.gnu.org/licenses/>
23
* Cody Russell <crussell@canonical.com>
26
#include "idogesturemanager.h"
29
#include <geis/geis.h>
31
typedef struct _IdoGestureRegistration IdoGestureRegistration;
32
typedef struct _IdoGestureBinding IdoGestureBinding;
34
struct _IdoGestureManagerPrivate
39
struct _IdoGestureBinding
43
IdoGestureCallback start;
44
IdoGestureCallback update;
45
IdoGestureCallback end;
48
struct _IdoGestureRegistration
52
GeisInstance instance;
53
GIOChannel *iochannel;
56
static void gesture_added (void *cookie,
57
GeisGestureType gesture_type,
58
GeisGestureId gesture_id,
60
GeisGestureAttr *attrs);
62
static void gesture_removed (void *cookie,
63
GeisGestureType gesture_type,
64
GeisGestureId gesture_id,
66
GeisGestureAttr *attrs);
68
static void gesture_start (void *cookie,
69
GeisGestureType gesture_type,
70
GeisGestureId gesture_id,
72
GeisGestureAttr *attrs);
74
static void gesture_update (void *cookie,
75
GeisGestureType gesture_type,
76
GeisGestureId gesture_id,
78
GeisGestureAttr *attrs);
80
static void gesture_finish (void *cookie,
81
GeisGestureType gesture_type,
82
GeisGestureId gesture_id,
84
GeisGestureAttr *attrs);
86
static IdoGestureManager *manager_singleton = NULL;
87
static GeisGestureFuncs gesture_funcs = {
95
G_DEFINE_TYPE (IdoGestureManager, ido_gesture_manager, G_TYPE_OBJECT)
97
#define IDO_GESTURE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IDO_TYPE_GESTURE_MANAGER, IdoGestureManagerPrivate))
100
ido_gesture_manager_dispose (GObject *object)
102
IdoGestureManagerPrivate *priv = IDO_GESTURE_MANAGER (object)->priv;
104
if (priv->hash != NULL)
106
g_hash_table_unref (priv->hash);
112
ido_gesture_manager_finalize (GObject *object)
117
ido_gesture_manager_constructor (GType type,
119
GObjectConstructParam *params)
123
if (manager_singleton != NULL)
125
object = g_object_ref (manager_singleton);
129
object = G_OBJECT_CLASS (ido_gesture_manager_parent_class)->constructor (type,
133
manager_singleton = IDO_GESTURE_MANAGER (object);
134
g_object_add_weak_pointer (object, (gpointer) &manager_singleton);
141
ido_gesture_manager_class_init (IdoGestureManagerClass *class)
143
GObjectClass *gobject_class;
145
gobject_class = G_OBJECT_CLASS (class);
147
ido_gesture_manager_parent_class = g_type_class_peek_parent (class);
149
g_type_class_add_private (gobject_class, sizeof (IdoGestureManagerPrivate));
151
gobject_class->constructor = ido_gesture_manager_constructor;
152
gobject_class->dispose = ido_gesture_manager_dispose;
153
gobject_class->finalize = ido_gesture_manager_finalize;
158
print_attr (GeisGestureAttr *attr)
162
g_print ("\tattr '%s'=", attr->name);
165
case GEIS_ATTR_TYPE_BOOLEAN:
166
g_print ("%s\n", attr->boolean_val ? "true" : "false");
168
case GEIS_ATTR_TYPE_FLOAT:
169
g_print ("%f\n", attr->float_val);
171
case GEIS_ATTR_TYPE_INTEGER:
172
g_print ("%d\n", (gint)attr->integer_val);
174
case GEIS_ATTR_TYPE_STRING:
175
g_print ("\"%s\"\n", attr->string_val);
178
g_print ("<unknown>\n");
185
pinch_gesture_handle_properties (IdoEventGesturePinch *event,
187
GeisGestureAttr *attrs)
192
for (i = 0; i < attr_count; ++i)
194
if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
195
attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
197
touches = attrs[i].integer_val;
199
if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
200
attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
202
event->timestamp = attrs[i].integer_val;
204
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
205
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
207
event->focus_x = attrs[i].float_val;
209
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
210
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
212
event->focus_y = attrs[i].float_val;
214
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA) == 0 &&
215
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
217
event->radius_delta = attrs[i].float_val;
219
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY) == 0 &&
220
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
222
event->radial_velocity = attrs[i].float_val;
224
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIUS) == 0 &&
225
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
227
event->radius = attrs[i].float_val;
235
drag_gesture_handle_properties (IdoEventGestureDrag *event,
237
GeisGestureAttr *attrs)
242
for (i = 0; i < attr_count; ++i)
244
if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
245
attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
247
touches = attrs[i].integer_val;
249
if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
250
attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
252
event->timestamp = attrs[i].integer_val;
254
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
255
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
257
event->focus_x = attrs[i].float_val;
259
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
260
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
262
event->focus_y = attrs[i].float_val;
264
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DELTA_X) == 0 &&
265
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
267
event->delta_x = attrs[i].float_val;
269
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y) == 0 &&
270
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
272
event->delta_y = attrs[i].float_val;
274
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X) == 0 &&
275
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
277
event->velocity_x = attrs[i].float_val;
279
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y) == 0 &&
280
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
282
event->velocity_y = attrs[i].float_val;
284
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
285
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
287
event->position_x = attrs[i].float_val;
289
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
290
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
292
event->position_y = attrs[i].float_val;
300
rotate_gesture_handle_properties (IdoEventGestureRotate *event,
302
GeisGestureAttr *attrs)
307
for (i = 0; i < attr_count; ++i)
309
if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
310
attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
312
touches = attrs[i].integer_val;
314
if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
315
attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
317
event->timestamp = attrs[i].integer_val;
319
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
320
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
322
event->focus_x = attrs[i].float_val;
324
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
325
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
327
event->focus_y = attrs[i].float_val;
329
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA) == 0 &&
330
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
332
event->angle_delta = attrs[i].float_val;
334
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY) == 0 &&
335
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
337
event->angular_velocity = attrs[i].float_val;
339
else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGLE) == 0 &&
340
attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
342
event->angle = attrs[i].float_val;
351
gesture_added (void *cookie,
352
GeisGestureType gesture_type,
353
GeisGestureId gesture_id,
355
GeisGestureAttr *attrs)
360
gesture_removed (void *cookie,
361
GeisGestureType gesture_type,
362
GeisGestureId gesture_id,
364
GeisGestureAttr *attrs)
369
gesture_start (void *cookie,
370
GeisGestureType type,
373
GeisGestureAttr *attrs)
375
IdoGestureRegistration *reg = (IdoGestureRegistration *)cookie;
378
for (l = reg->bindings; l != NULL; l = l->next)
380
IdoGestureBinding *binding = (IdoGestureBinding *)l->data;
382
if (binding->type == type)
384
if (type == IDO_GESTURE_DRAG)
386
IdoEventGestureDrag drag;
390
drag.fingers = drag_gesture_handle_properties (&drag,
394
if (drag.fingers == binding->touches)
396
binding->start (reg->window,
397
((IdoGestureEvent*)&drag));
400
else if (type == IDO_GESTURE_PINCH)
402
IdoEventGesturePinch pinch;
406
pinch.fingers = pinch_gesture_handle_properties (&pinch,
410
if (pinch.fingers == binding->touches)
412
binding->start (reg->window,
413
((IdoGestureEvent*)&pinch));
416
else if (type == IDO_GESTURE_ROTATE)
418
IdoEventGestureRotate rotate;
422
rotate.fingers = rotate_gesture_handle_properties (&rotate,
426
if (rotate.fingers == binding->touches)
428
binding->start (reg->window,
429
((IdoGestureEvent*)&rotate));
439
gesture_update (void *cookie,
440
GeisGestureType type,
443
GeisGestureAttr *attrs)
445
IdoGestureRegistration *reg = (IdoGestureRegistration *)cookie;
448
for (l = reg->bindings; l != NULL; l = l->next)
450
IdoGestureBinding *binding = (IdoGestureBinding *)l->data;
452
if (binding->type == type)
454
if (type == IDO_GESTURE_DRAG)
456
IdoEventGestureDrag drag;
460
drag.fingers = drag_gesture_handle_properties (&drag,
464
if (drag.fingers == binding->touches)
466
binding->update (reg->window,
467
((IdoGestureEvent*)&drag));
470
else if (type == IDO_GESTURE_PINCH)
472
IdoEventGesturePinch pinch;
476
pinch.fingers = pinch_gesture_handle_properties (&pinch,
480
if (pinch.fingers == binding->touches)
482
binding->update (reg->window,
483
((IdoGestureEvent*)&pinch));
486
else if (type == IDO_GESTURE_ROTATE)
488
IdoEventGestureRotate rotate;
492
rotate.fingers = rotate_gesture_handle_properties (&rotate,
496
if (rotate.fingers == binding->touches)
498
binding->update (reg->window,
499
((IdoGestureEvent*)&rotate));
507
gesture_finish (void *cookie,
508
GeisGestureType type,
511
GeisGestureAttr *attrs)
513
IdoGestureRegistration *reg = (IdoGestureRegistration *)cookie;
516
for (l = reg->bindings; l != NULL; l = l->next)
518
IdoGestureBinding *binding = (IdoGestureBinding *)l->data;
520
if (binding->type == type)
522
if (type == IDO_GESTURE_DRAG)
524
IdoEventGestureDrag drag;
528
drag.fingers = drag_gesture_handle_properties (&drag,
532
if (drag.fingers == binding->touches)
534
binding->end (reg->window,
535
((IdoGestureEvent*)&drag));
538
else if (type == IDO_GESTURE_PINCH)
540
IdoEventGesturePinch pinch;
544
pinch.fingers = pinch_gesture_handle_properties (&pinch,
548
if (pinch.fingers == binding->touches)
550
binding->end (reg->window,
551
((IdoGestureEvent*)&pinch));
554
else if (type == IDO_GESTURE_ROTATE)
556
IdoEventGestureRotate rotate;
560
rotate.fingers = rotate_gesture_handle_properties (&rotate,
564
if (rotate.fingers == binding->touches)
566
binding->end (reg->window,
567
((IdoGestureEvent*)&rotate));
575
ido_gesture_manager_init (IdoGestureManager *item)
577
IdoGestureManagerPrivate *priv;
579
priv = item->priv = IDO_GESTURE_MANAGER_GET_PRIVATE (item);
581
priv->hash = g_hash_table_new (g_direct_hash, g_direct_equal);
585
io_callback (GIOChannel *source,
586
GIOCondition condition,
589
IdoGestureRegistration *reg = (IdoGestureRegistration *)data;
591
geis_event_dispatch (reg->instance);
597
window_destroyed_cb (GtkObject *object,
600
IdoGestureManager *manager = (IdoGestureManager *)user_data;
601
IdoGestureManagerPrivate *priv = manager->priv;
602
IdoGestureRegistration *reg = g_hash_table_lookup (priv->hash, object);
605
for (list = reg->bindings; list != NULL; list = list->next)
607
IdoGestureBinding *binding = (IdoGestureBinding *)list->data;
612
g_list_free (reg->bindings);
614
g_io_channel_shutdown (reg->iochannel, TRUE, NULL);
616
geis_finish (reg->instance);
618
g_hash_table_remove (priv->hash, object);
625
ido_gesture_manager_get (void)
627
return g_object_new (IDO_TYPE_GESTURE_MANAGER, NULL);
631
* ido_gesture_manager_register_window:
632
* @window: A #GtkWindow to register the gesture event for.
633
* @gesture_type: The type of gesture event to register.
634
* @touch_points: Number of touch points for this gesture.
635
* @start: Called when a user initiates a gesture.
636
* @update: Called each time the user updates the gesture.
637
* @end: Called when the user ends the gesture.
639
* Registers a toplevel window to receive gesture events.
640
* The callback parameters provided will be called by the
641
* #IdoGestureManager whenever the user initiates a gesture
642
* on the specified window.
645
ido_gesture_manager_register_window (IdoGestureManager *manager,
647
IdoGestureType gesture_type,
649
IdoGestureCallback start,
650
IdoGestureCallback update,
651
IdoGestureCallback end)
653
IdoGestureManagerPrivate *priv;
654
IdoGestureRegistration *reg;
655
IdoGestureBinding *binding;
657
g_return_if_fail (IDO_IS_GESTURE_MANAGER (manager));
658
g_return_if_fail (GTK_IS_WINDOW (window));
659
g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (window)));
661
priv = manager->priv;
663
if (!(reg = g_hash_table_lookup (priv->hash, window)))
665
GeisInstance instance;
666
GIOChannel *iochannel;
668
GeisXcbWinInfo xcb_win_info = {
669
.display_name = NULL,
671
.window_id = GDK_DRAWABLE_XID (GTK_WIDGET (window)->window)
673
GeisWinInfo win_info = {
674
GEIS_XCB_FULL_WINDOW,
678
if (geis_init (&win_info, &instance) != GEIS_STATUS_SUCCESS)
680
g_warning ("Failed to initialize gesture manager.");
684
if (geis_configuration_supported (instance,
685
GEIS_CONFIG_UNIX_FD) != GEIS_STATUS_SUCCESS)
687
g_warning ("Gesture manager does not support UNIX fd.");
691
if (geis_configuration_get_value (instance,
693
&fd) != GEIS_STATUS_SUCCESS)
695
g_error ("Gesture manager failed to obtain UNIX fd.");
699
reg = g_new0 (IdoGestureRegistration, 1);
701
reg->window = window;
702
reg->instance = instance;
704
g_signal_connect (window,
706
G_CALLBACK (window_destroyed_cb),
709
geis_subscribe (reg->instance,
710
GEIS_ALL_INPUT_DEVICES,
715
iochannel = g_io_channel_unix_new (fd);
716
g_io_add_watch (iochannel,
721
reg->iochannel = iochannel;
724
/* XXX - check for duplicates in reg->bindings first */
725
binding = g_new0 (IdoGestureBinding, 1);
727
binding->type = gesture_type;
728
binding->touches = touch_points;
729
binding->start = start;
730
binding->update = update;
733
reg->bindings = g_list_append (reg->bindings, binding);
735
g_hash_table_insert (priv->hash,