deviceeventcontroller.c 60.9 KB
Newer Older
1
2
/* AT-SPI - Assistive Technology Service Provider Interface
 *
3
4
 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
 *
5
 * Copyright 2001, 2003 Sun Microsystems Inc.,
6
 * Copyright 2001, 2002 Ximian, Inc.
7
8
 *
 * This library is free software; you can redistribute it and/or
Mike Gorse's avatar
Mike Gorse committed
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
Mike Gorse's avatar
Mike Gorse committed
11
 * version 2.1 of the License, or (at your option) any later version.
12
13
14
15
 *
 * 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
Mike Gorse's avatar
Mike Gorse committed
16
 * Lesser General Public License for more details.
17
 *
Mike Gorse's avatar
Mike Gorse committed
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the
Mike Gorse's avatar
Mike Gorse committed
20
21
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
22
23
 */

24
/* deviceeventcontroller.c: implement the DeviceEventController interface */
25

26
#include "config.h"
27

billh's avatar
billh committed
28
#undef  SPI_XKB_DEBUG
29
#undef  SPI_DEBUG
30
#undef  SPI_KEYEVENT_DEBUG
31

32
33
34
#include <string.h>
#include <ctype.h>
#include <stdio.h>
padraigo's avatar
padraigo committed
35
#include <sys/time.h>
36

37
#include <glib.h>
38

39
#include <dbus/dbus.h>
40

41
42
43
#include "paths.h"
#include "de-types.h"
#include "de-marshaller.h"
44
45
#include "keymasks.h"

46
47
48
49
#include "deviceeventcontroller.h"
#include "reentrant-list.h"
#include "introspection.h"

50
#ifdef HAVE_X11
51
#include "deviceeventcontroller-x11.h"
52
#include "display.h"
Mike Gorse's avatar
Mike Gorse committed
53
#include "event-source.h"
54
#endif
55

56
57
#define CHECK_RELEASE_DELAY 20
#define BIT(c, x)       (c[x/8]&(1<<(x%8)))
Mike Gorse's avatar
Mike Gorse committed
58
static SpiDEController *saved_controller;
59

60
/* Our parent Gtk object type */
61
#define PARENT_TYPE G_TYPE_OBJECT
62

63
64
65
66
67
68
69
70
71
72
#ifndef HAVE_X11
/* If we are using X11, SpiDEControllerPrivate is defined in deviceeventcontroller-x11.h.
 * Otherwise, there is no private data and so we use a dummy struct.
 * This is so that G_ADD_PRIVATE() will have a type to work with.
 */
typedef struct {
  int _dummy;
} SpiDEControllerPrivate;
#endif

73
/* A pointer to our parent object class */
74
static int spi_error_code = 0;
75
76
77
78
79
struct _SpiPoint {
    gint x;
    gint y;
};
typedef struct _SpiPoint SpiPoint;
80

billh's avatar
billh committed
81
82
static unsigned int mouse_mask_state = 0;
static unsigned int key_modifier_mask =
83
84
85
  SPI_KEYMASK_MOD1 | SPI_KEYMASK_MOD2 | SPI_KEYMASK_MOD3 | SPI_KEYMASK_MOD4 |
  SPI_KEYMASK_MOD5 | SPI_KEYMASK_SHIFT | SPI_KEYMASK_SHIFTLOCK |
  SPI_KEYMASK_CONTROL | SPI_KEYMASK_NUMLOCK;
86
unsigned int _numlock_physical_mask = SPI_KEYMASK_MOD2; /* a guess, will be reset */
87

88
89
90
static gboolean have_mouse_listener = FALSE;
static gboolean have_mouse_event_listener = FALSE;

91

92
93
94
95
typedef struct {
  guint                             ref_count : 30;
  guint                             pending_add : 1;
  guint                             pending_remove : 1;
96

97
  Accessibility_ControllerEventMask mod_mask;
98
  dbus_uint32_t               key_val;  /* KeyCode */
99
} DEControllerGrabMask;
100

billh's avatar
billh committed
101

Mike Gorse's avatar
Mike Gorse committed
102
gboolean spi_controller_update_key_grabs               (SpiDEController           *controller,
103
							       Accessibility_DeviceEvent *recv);
Mike Gorse's avatar
Mike Gorse committed
104
105
106

static gboolean eventtype_seq_contains_event (dbus_uint32_t types,
					      const Accessibility_DeviceEvent *event);
107
108
static gboolean spi_dec_poll_mouse_moving (gpointer data);
static gboolean spi_dec_poll_mouse_idle (gpointer data);
billh's avatar
billh committed
109

110
111
G_DEFINE_TYPE_WITH_CODE(SpiDEController, spi_device_event_controller, G_TYPE_OBJECT,
                        G_ADD_PRIVATE (SpiDEController))
112

Mike Gorse's avatar
Mike Gorse committed
113
114
115
116
117
118
119
120
121
122
123
124
static gint
spi_dec_plat_get_keycode (SpiDEController *controller,
                          gint keysym,
                          gchar *key_str,
                          gboolean fix,
                          guint *modmask)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.get_keycode)
    return klass->plat.get_keycode (controller, keysym, key_str, fix, modmask);
  else
125
126
127
128
129
130
131
    {
      if (modmask)
        {
          *modmask = 0;
        }
      return keysym;
    }
Mike Gorse's avatar
Mike Gorse committed
132
133
134
135
136
137
138
139
140
141
142
}

static guint
spi_dec_plat_mouse_check (SpiDEController *controller, 
		     int *x, int *y, gboolean *moved)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.mouse_check)
    return klass->plat.mouse_check (controller, x, y, moved);
  else
143
144
145
146
147
148
149
    {
      if (moved)
        {
          *moved = FALSE;
        }
      return 0;
    }
Mike Gorse's avatar
Mike Gorse committed
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
}

static gboolean
spi_dec_plat_grab_key (SpiDEController *controller, guint key_val, Accessibility_ControllerEventMask mod_mask)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.grab_key)
    return klass->plat.grab_key (controller, key_val, mod_mask);
  else
    return FALSE;
}

static void
spi_dec_plat_ungrab_key (SpiDEController *controller, guint key_val, Accessibility_ControllerEventMask mod_mask)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.ungrab_key)
    klass->plat.ungrab_key (controller, key_val, mod_mask);
}

static gboolean
spi_dec_plat_synth_keycode_press (SpiDEController *controller,
			 unsigned int keycode)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.synth_keycode_press)
    return klass->plat.synth_keycode_press (controller, keycode);
  else
    return FALSE;
}

static gboolean
spi_dec_plat_synth_keycode_release (SpiDEController *controller,
			   unsigned int keycode)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.synth_keycode_release)
    return klass->plat.synth_keycode_release (controller, keycode);
  else
    return FALSE;
}

static gboolean
spi_dec_plat_lock_modifiers (SpiDEController *controller, unsigned modifiers)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.lock_modifiers)
    return klass->plat.lock_modifiers (controller, modifiers);
  else
    return FALSE;
}

static gboolean
spi_dec_plat_unlock_modifiers (SpiDEController *controller, unsigned modifiers)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.unlock_modifiers)
    return klass->plat.unlock_modifiers (controller, modifiers);
  else
    return FALSE;
}

static gboolean
spi_dec_plat_synth_keystring (SpiDEController *controller, guint synth_type, gint keycode, const char *keystring)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.synth_keystring)
    return klass->plat.synth_keystring (controller, synth_type, keycode, keystring);
  else
    return FALSE;
}

static void
spi_dec_plat_emit_modifier_event (SpiDEController *controller, guint prev_mask, 
			     guint current_mask)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.emit_modifier_event)
236
    klass->plat.emit_modifier_event (controller, prev_mask, current_mask);
Mike Gorse's avatar
Mike Gorse committed
237
238
239
240
241
242
243
244
245
246
247
}

static void
spi_dec_plat_generate_mouse_event (SpiDEController *controller,
                                   gint x,
                                   gint y,
                                   const char *eventName)
{
  SpiDEControllerClass *klass;
  klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
  if (klass->plat.generate_mouse_event)
248
    klass->plat.generate_mouse_event (controller, x, y, eventName);
Mike Gorse's avatar
Mike Gorse committed
249
250
}

251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
DBusMessage *
invalid_arguments_error (DBusMessage *message)
{
    DBusMessage *reply;
    gchar       *errmsg;

    errmsg= g_strdup_printf (
            "Method \"%s\" with signature \"%s\" on interface \"%s\" was supplied with invalid arguments\n",
            dbus_message_get_member (message),
            dbus_message_get_signature (message),
            dbus_message_get_interface (message));
    reply = dbus_message_new_error (message,
                                    DBUS_ERROR_INVALID_ARGS,
                                    errmsg);
    g_free (errmsg);
    return reply;
}

269
/* Private methods */
270
271
272
273
274
275
276
277
278
279
static dbus_bool_t
spi_dbus_add_disconnect_match (DBusConnection *bus, const char *name)
{
  char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name);
  if (match)
  {
    DBusError error;
    dbus_error_init (&error);
    dbus_bus_add_match (bus, match, &error);
    g_free (match);
William Jon McCann's avatar
William Jon McCann committed
280
281
282
283
284
285
286
287
288
    if (dbus_error_is_set (&error))
      {
        dbus_error_free (&error);
        return FALSE;
      }
    else
      {
        return TRUE;
      }
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  }
  else return FALSE;
}

static dbus_bool_t
spi_dbus_remove_disconnect_match (DBusConnection *bus, const char *name)
{
  char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name);
  if (match)
  {
    DBusError error;
    dbus_error_init (&error);
    dbus_bus_remove_match (bus, match, &error);
    g_free (match);
William Jon McCann's avatar
William Jon McCann committed
303
304
305
306
307
308
309
310
311
    if (dbus_error_is_set (&error))
      {
        dbus_error_free (&error);
        return FALSE;
      }
    else
      {
        return TRUE;
      }
312
313
314
  }
  else return FALSE;
}
billh's avatar
billh committed
315

316
static DEControllerGrabMask *
317
spi_grab_mask_clone (DEControllerGrabMask *grab_mask)
318
{
319
  DEControllerGrabMask *clone = g_new (DEControllerGrabMask, 1);
320

321
  memcpy (clone, grab_mask, sizeof (DEControllerGrabMask));
billh's avatar
billh committed
322

323
324
325
326
327
  clone->ref_count = 1;
  clone->pending_add = TRUE;
  clone->pending_remove = FALSE;

  return clone;
billh's avatar
billh committed
328
329
}

330
331
static void
spi_grab_mask_free (DEControllerGrabMask *grab_mask)
332
{
333
  g_free (grab_mask);
334
335
}

billh's avatar
billh committed
336
static gint
337
spi_grab_mask_compare_values (gconstpointer p1, gconstpointer p2)
billh's avatar
billh committed
338
{
339
340
341
  DEControllerGrabMask *l1 = (DEControllerGrabMask *) p1;
  DEControllerGrabMask *l2 = (DEControllerGrabMask *) p2;

342
343
344
345
346
347
  if (p1 == p2)
    {
      return 0;
    }
  else
    { 
348
      return ((l1->mod_mask != l2->mod_mask) || (l1->key_val != l2->key_val));
349
    }
billh's avatar
billh committed
350
351
}

Mike Gorse's avatar
Mike Gorse committed
352
353
354
void
spi_dec_dbus_emit (SpiDEController *controller, const char *interface,
                   const char *name, const char *minor, int a1, int a2)
355
{
356
  DBusMessage *signal = NULL;
357
  DBusMessageIter iter, iter_struct, iter_variant;
358
  int nil = 0;
359
  const char *path = SPI_DBUS_PATH_ROOT;
360
  const char *bus_name = dbus_bus_get_unique_name (controller->bus);
361

362
363
364
365
366
  signal = dbus_message_new_signal (path, interface, name);

  dbus_message_iter_init_append (signal, &iter);

  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor);
Mike Gorse's avatar
Mike Gorse committed
367
368
  dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a1);
  dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a2);
369
370
371
372
  dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &iter_variant);
      dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &nil);
  dbus_message_iter_close_container (&iter, &iter_variant);

373
374
375
376
377
378
  dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
                                    &iter_struct);
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &bus_name);
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
  dbus_message_iter_close_container (&iter, &iter_struct);

379
  dbus_connection_send (controller->bus, signal, NULL);
380
  dbus_message_unref (signal);
381
382
}

383
384
385
static gboolean
spi_dec_poll_mouse_moved (gpointer data)
{
386
387
  SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(data);
  int x, y;
388
389
390
  gboolean moved;
  guint mask_return;

Mike Gorse's avatar
Mike Gorse committed
391
  mask_return = spi_dec_plat_mouse_check (controller, &x, &y, &moved);
392

393
394
395
  if ((mask_return & key_modifier_mask) !=
      (mouse_mask_state & key_modifier_mask)) 
    {
Mike Gorse's avatar
Mike Gorse committed
396
      spi_dec_plat_emit_modifier_event (controller, mouse_mask_state, mask_return);
397
398
399
400
      mouse_mask_state = mask_return;
    }

  return moved;
401
402
403
404
405
}

static gboolean
spi_dec_poll_mouse_idle (gpointer data)
{
406
407
408
  if (!have_mouse_event_listener && !have_mouse_listener)
    return FALSE;
  else if (!spi_dec_poll_mouse_moved (data))
409
410
411
    return TRUE;
  else
    {
Bastien Nocera's avatar
Bastien Nocera committed
412
413
414
      guint id;
      id = g_timeout_add (20, spi_dec_poll_mouse_moving, data);
      g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_moving");
415
416
417
418
419
420
421
      return FALSE;	    
    }
}

static gboolean
spi_dec_poll_mouse_moving (gpointer data)
{
422
423
424
  if (!have_mouse_event_listener && !have_mouse_listener)
    return FALSE;
  else if (spi_dec_poll_mouse_moved (data))
425
426
427
    return TRUE;
  else
    {
Bastien Nocera's avatar
Bastien Nocera committed
428
429
430
      guint id;
      id = g_timeout_add (100, spi_dec_poll_mouse_idle, data);
      g_source_set_name_by_id (id, "[at-spi2-core] check_release");
431
432
433
434
      return FALSE;
    }
}

435
436
437
/**
 * Eventually we can use this to make the marshalling of mask types
 * more sane, but for now we just use this to detect 
438
 * the use of 'virtual' masks such as numlock and convert them to
439
440
441
442
443
444
 * system-specific mask values (i.e. ModMask).
 * 
 **/
static Accessibility_ControllerEventMask
spi_dec_translate_mask (Accessibility_ControllerEventMask mask)
{
445
446
447
448
449
450
451
452
453
454
  Accessibility_ControllerEventMask tmp_mask;
  gboolean has_numlock;

  has_numlock = (mask & SPI_KEYMASK_NUMLOCK);
  tmp_mask = mask;
  if (has_numlock)
    {
      tmp_mask = mask ^ SPI_KEYMASK_NUMLOCK;
      tmp_mask |= _numlock_physical_mask;
    }
455
 
456
  return tmp_mask;
457
458
}

459
static DEControllerKeyListener *
460
spi_dec_key_listener_new (const char *bus_name,
461
462
			  const char *path,
			  GSList *keys,
463
			  const Accessibility_ControllerEventMask mask,
464
465
			  const dbus_uint32_t types,
			  const Accessibility_EventListenerMode  *mode)
466
467
{
  DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1);
468
  key_listener->listener.bus_name = g_strdup(bus_name);
469
  key_listener->listener.path = g_strdup(path);
470
  key_listener->listener.type = SPI_DEVICE_TYPE_KBD;
471
  key_listener->keys = keys;
472
  key_listener->mask = spi_dec_translate_mask (mask);
473
  key_listener->listener.types = types;
474
  if (mode)
475
476
477
478
  {
    key_listener->mode = (Accessibility_EventListenerMode *) g_malloc(sizeof(Accessibility_EventListenerMode));
    memcpy(key_listener->mode, mode, sizeof(*mode));
  }
479
480
  else
    key_listener->mode = NULL;
481

482
#ifdef SPI_DEBUG
483
  g_print ("new listener, with mask %x, is_global %d, keys %p (%d)\n",
484
	   (unsigned int) key_listener->mask,
485
486
           (int) (mode ? mode->global : 0),
	   (void *) key_listener->keys,
487
	   (int) (key_listener->keys ? g_slist_length(key_listener->keys) : 0));
488
#endif
489

490
491
492
  return key_listener;	
}

493
static DEControllerListener *
494
spi_dec_listener_new (const char *bus_name,
495
496
		      const char *path,
		      dbus_uint32_t types)
497
498
{
  DEControllerListener *listener = g_new0 (DEControllerListener, 1);
499
  listener->bus_name = g_strdup(bus_name);
500
  listener->path = g_strdup(path);
501
  listener->type = SPI_DEVICE_TYPE_MOUSE;
502
  listener->types = types;
503
504
505
506
  return listener;	
}

static DEControllerListener *
507
spi_listener_clone (DEControllerListener *listener)
508
509
{
  DEControllerListener *clone = g_new0 (DEControllerListener, 1);
510
  clone->bus_name = g_strdup (listener->bus_name);
511
  clone->path = g_strdup (listener->path);
512
  clone->type = listener->type;
513
  clone->types = listener->types;
514
515
516
  return clone;
}

517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
static GSList *keylist_clone (GSList *s)
{
  GSList *d = NULL;
  GSList *l;

  for (l = s; l; l = g_slist_next(l))
  {
    Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
    if (kd)
    {
      Accessibility_KeyDefinition *kds = (Accessibility_KeyDefinition *)l->data;
      kd->keycode = kds->keycode;
      kd->keysym = kds->keysym;
      kd->keystring = g_strdup(kds->keystring);
      d = g_slist_append(d, kd);
    }
  }
  return d;
}

537
static DEControllerKeyListener *
538
spi_key_listener_clone (DEControllerKeyListener *key_listener)
539
540
{
  DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1);
541
  clone->listener.bus_name = g_strdup (key_listener->listener.bus_name);
542
  clone->listener.path = g_strdup (key_listener->listener.path);
543
  clone->listener.type = SPI_DEVICE_TYPE_KBD;
544
  clone->keys = keylist_clone (key_listener->keys);
545
  clone->mask = key_listener->mask;
546
  clone->listener.types = key_listener->listener.types;
547
  if (key_listener->mode)
548
549
550
551
  {
    clone->mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode));
    if (clone->mode) memcpy(clone->mode, key_listener->mode, sizeof(Accessibility_EventListenerMode));
  }
552
553
554
555
556
  else
    clone->mode = NULL;
  return clone;
}

557
558
559
560
561
562
563
564
565
566
567
568
569
static void keylist_free(GSList *keys)
{
  GSList *l;

  for (l = keys; l; l = g_slist_next(l))
  {
    Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)l->data;
    g_free(kd->keystring);
    g_free(kd);
  }
  g_slist_free (keys);
}

570
static void
571
spi_key_listener_data_free (DEControllerKeyListener *key_listener)
572
{
573
574
  keylist_free(key_listener->keys);
  if (key_listener->mode) g_free(key_listener->mode);
575
576
  g_free (key_listener->listener.bus_name);
  g_free (key_listener->listener.path);
577
578
579
  g_free (key_listener);
}

580
static void
581
spi_key_listener_clone_free (DEControllerKeyListener *clone)
582
{
583
  spi_key_listener_data_free (clone);
584
585
586
}

static void
587
spi_listener_clone_free (DEControllerListener *clone)
588
{
589
  g_free (clone->path);
590
  g_free (clone->bus_name);
591
592
593
594
  g_free (clone);
}

static void
595
spi_dec_listener_free (DEControllerListener    *listener)
596
{
597
  if (listener->type == SPI_DEVICE_TYPE_KBD) 
598
    spi_key_listener_data_free ((DEControllerKeyListener *) listener);
599
600
601
602
603
  else
  {
    g_free (listener->bus_name);
    g_free (listener->path);
  }
604
605
}

billh's avatar
billh committed
606
static void
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
_register_keygrab (SpiDEController      *controller,
		   DEControllerGrabMask *grab_mask)
{
  GList *l;

  l = g_list_find_custom (controller->keygrabs_list, grab_mask,
			  spi_grab_mask_compare_values);
  if (l)
    {
      DEControllerGrabMask *cur_mask = l->data;

      cur_mask->ref_count++;
      if (cur_mask->pending_remove)
        {
          cur_mask->pending_remove = FALSE;
	}
    }
  else
    {
      controller->keygrabs_list =
        g_list_prepend (controller->keygrabs_list,
			spi_grab_mask_clone (grab_mask));
    }
}

static void
_deregister_keygrab (SpiDEController      *controller,
		     DEControllerGrabMask *grab_mask)
635
{
636
637
638
639
640
641
642
643
644
645
  GList *l;

  l = g_list_find_custom (controller->keygrabs_list, grab_mask,
			  spi_grab_mask_compare_values);

  if (l)
    {
      DEControllerGrabMask *cur_mask = l->data;

      cur_mask->ref_count--;
646
647
648
649
      if (cur_mask->ref_count <= 0)
        {
          cur_mask->pending_remove = TRUE;
	}
650
    }
651
652
653
}

static void
654
655
656
657
handle_keygrab (SpiDEController         *controller,
		DEControllerKeyListener *key_listener,
		void                   (*process_cb) (SpiDEController *controller,
						      DEControllerGrabMask *grab_mask))
658
{
659
660
661
  DEControllerGrabMask grab_mask = { 0 };

  grab_mask.mod_mask = key_listener->mask;
662
  if (g_slist_length (key_listener->keys) == 0) /* special case means AnyKey/AllKeys */
663
    {
664
      grab_mask.key_val = 0L; /* AnyKey */
665
#ifdef SPI_DEBUG
padraigo's avatar
padraigo committed
666
      fprintf (stderr, "AnyKey grab!");
667
#endif
668
      process_cb (controller, &grab_mask);
669
670
671
    }
  else
    {
672
      GSList *l;
673

674
      for (l = key_listener->keys; l; l = g_slist_next(l))
675
        {
676
	  Accessibility_KeyDefinition *keydef = l->data;
Mike Gorse's avatar
Mike Gorse committed
677
678
679
680
	  long key_val;
	  key_val = spi_dec_plat_get_keycode (controller, keydef->keysym, keydef->keystring, FALSE, NULL);
	  if (!key_val)
	    key_val = keydef->keycode;
681
682
683
	  grab_mask.key_val = key_val;
	  process_cb (controller, &grab_mask);
	}
684
685
686
    }
}

687
static gboolean
688
689
690
691
spi_controller_register_global_keygrabs (SpiDEController         *controller,
					 DEControllerKeyListener *key_listener)
{
  handle_keygrab (controller, key_listener, _register_keygrab);
Mike Gorse's avatar
Mike Gorse committed
692
  return spi_controller_update_key_grabs (controller, NULL);
693
694
695
696
697
698
699
}

static void
spi_controller_deregister_global_keygrabs (SpiDEController         *controller,
					   DEControllerKeyListener *key_listener)
{
  handle_keygrab (controller, key_listener, _deregister_keygrab);
Mike Gorse's avatar
Mike Gorse committed
700
  spi_controller_update_key_grabs (controller, NULL);
701
702
}

703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
static void
append_keystroke_listener (DBusMessageIter *iter, DEControllerKeyListener *listener)
{
  dbus_uint32_t d_uint;
  DBusMessageIter iter_struct, iter_subarray, iter_substruct;
  GSList *kl;

  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
                                         &iter_struct))
    return;

  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING,
                                  &listener->listener.bus_name);
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
                                  &listener->listener.path);
  d_uint = listener->listener.type;
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
  d_uint = listener->listener.types;
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
  if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY,
                                         "(iisi)", &iter_subarray))
  {
    dbus_message_iter_close_container (iter, &iter_struct);
    return;
  }
  for (kl = listener->keys; kl; kl = kl->next)
  {
    Accessibility_KeyDefinition *kd = kl->data;
    if (!dbus_message_iter_open_container (&iter_subarray, DBUS_TYPE_STRUCT,
                                         NULL, &iter_substruct))
      break;
    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keycode);
    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keysym);
    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_STRING, &kd->keystring);
    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->unused);
    dbus_message_iter_close_container (&iter_subarray, &iter_substruct);
  }
  dbus_message_iter_close_container (&iter_struct, &iter_subarray);
  d_uint = listener->mask;
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
  if (dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT,
                                         NULL, &iter_substruct))
  {
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
    if (listener->mode)
    {
      dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
                                      &listener->mode->synchronous);
      dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
                                      &listener->mode->preemptive);
      dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
                                      &listener->mode->global);
    }
    else
    {
      dbus_bool_t dummy_val = FALSE;
      dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
                                      &dummy_val);
      dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
                                      &dummy_val);
      dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
                                      &dummy_val);
    }
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
    dbus_message_iter_close_container (&iter_struct, &iter_substruct);
  }
  dbus_message_iter_close_container (iter, &iter_struct);
}

static void
notify_keystroke_listener (SpiDEController *controller,
                           DEControllerKeyListener *listener,
                           gboolean enable)
{
  const char *path = SPI_DBUS_PATH_DEC;
  const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
  const char *name = (enable
                      ? "KeystrokeListenerRegistered"
                      : "KeystrokeListenerDeregistered");
  DBusMessage *signal;
  DBusMessageIter iter;

  signal = dbus_message_new_signal (path, interface, name);
  if (!signal)
    return;
  dbus_message_iter_init_append (signal, &iter);
  append_keystroke_listener (&iter, listener);
  dbus_connection_send (controller->bus, signal, NULL);
  dbus_message_unref (signal);
}

static void
append_mouse_listener (DBusMessageIter *iter, DEControllerListener *listener)
{
  DBusMessageIter iter_struct;
  dbus_uint32_t d_uint;

  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
                                         &iter_struct))
    return;
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING,
                                  &listener->bus_name);
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
                                  &listener->path);
  d_uint = listener->types;
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
  dbus_message_iter_close_container (iter, &iter_struct);
}

static void
notify_mouse_listener (SpiDEController *controller,
                       DEControllerListener *listener,
                       gboolean enable)
{
  const char *path = SPI_DBUS_PATH_DEC;
  const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
  const char *name = (enable
                      ? "DeviceListenerRegistered"
                      : "DeviceListenerDeregistered");
  DBusMessage *signal;
  DBusMessageIter iter;

  signal = dbus_message_new_signal (path, interface, name);
  if (!signal)
    return;
  dbus_message_iter_init_append (signal, &iter);
  append_mouse_listener (&iter, listener);
  dbus_connection_send (controller->bus, signal, NULL);
  dbus_message_unref (signal);
}

832
static gboolean
833
spi_controller_register_device_listener (SpiDEController      *controller,
834
					 DEControllerListener *listener)
billh's avatar
billh committed
835
{
836
  DEControllerKeyListener *key_listener;
837
  gboolean retval;
billh's avatar
billh committed
838
  
839
840
  switch (listener->type) {
  case SPI_DEVICE_TYPE_KBD:
841
842
843
844
      key_listener = (DEControllerKeyListener *) listener;

      controller->key_listeners = g_list_prepend (controller->key_listeners,
						  key_listener);
845
      spi_dbus_add_disconnect_match (controller->bus, key_listener->listener.bus_name);
846
      if (key_listener->mode->global)
847
        {
848
	  retval = spi_controller_register_global_keygrabs (controller, key_listener);
849
	}
850
      else
851
852
853
	  retval = TRUE;
      if (retval)
	notify_keystroke_listener (controller, key_listener, TRUE);
billh's avatar
billh committed
854
      break;
855
856
  case SPI_DEVICE_TYPE_MOUSE:
      controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
857
858
859
      if (!have_mouse_listener)
        {
          have_mouse_listener = TRUE;
Bastien Nocera's avatar
Bastien Nocera committed
860
861
862
863
864
          if (!have_mouse_event_listener) {
            guint id;
            id = g_timeout_add (100, spi_dec_poll_mouse_idle, controller);
            g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_idle");
          }
865
        }
866
      spi_dbus_add_disconnect_match (controller->bus, listener->bus_name);
867
      notify_mouse_listener (controller, listener, TRUE);
868
869
      break;
  default:
billh's avatar
billh committed
870
871
      break;
  }
872
  return FALSE;
billh's avatar
billh committed
873
874
}

875
876
877
878
879
880
881
882
static void
set_reply (DBusPendingCall *pending, void *user_data)
{
    void **replyptr = (void **)user_data;

    *replyptr = dbus_pending_call_steal_reply (pending);
}

883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
static GSList *hung_processes = NULL;

static void
reset_hung_process (DBusPendingCall *pending, void *data)
{
  DBusMessage *message = data;
  const char *dest = dbus_message_get_destination (message);
  GSList *l;

  /* At this point we don't care about the result */
  dbus_pending_call_unref (pending);

  for (l = hung_processes; l; l = l->next)
  {
    if (!strcmp (l->data, dest))
    {
899
      hung_processes = g_slist_remove (hung_processes, l->data);
900
      g_free (l->data);
901
902
903
904
905
906
907
908
909
910
911
912
913
914
      break;
    }
  }
}

static gint
time_elapsed (struct timeval *origin)
{
  struct timeval tv;

  gettimeofday (&tv, NULL);
  return (tv.tv_sec - origin->tv_sec) * 1000 + (tv.tv_usec - origin->tv_usec) / 1000;
}

915
916
917
918
919
920
921
922
923
static void
reset_hung_process_from_ping (DBusPendingCall *pending, void *data)
{
  GSList *l;

  for (l = hung_processes; l; l = l->next)
  {
    if (!strcmp (l->data, data))
    {
924
      hung_processes = g_slist_remove (hung_processes, l->data);
925
      g_free (l->data);
926
927
928
929
930
931
932
      break;
    }
  }
  g_free (data);
  dbus_pending_call_unref (pending);
}

933
934
935
936
937
static DBusMessage *
send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, int timeout, DBusError *error)
{
    DBusPendingCall *pending;
    DBusMessage *reply = NULL;
938
  struct timeval tv;
939
940
941
942
943
944

    if (!dbus_connection_send_with_reply (bus, message, &pending, -1))
    {
        return NULL;
    }
    dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
945
    gettimeofday (&tv, NULL);
946
947
    while (!reply)
    {
948
949
950
951
952
      if (!dbus_connection_read_write_dispatch (bus, timeout) ||
          time_elapsed (&tv) > timeout)
      {
        const char *dest = dbus_message_get_destination (message);
        GSList *l;
953
        gchar *bus_name_dup;
954
955
956
        dbus_message_ref (message);
        dbus_pending_call_set_notify (pending, reset_hung_process, message,
                                      (DBusFreeFunction) dbus_message_unref);
957
958
959
960
        message = dbus_message_new_method_call (dest, "/",
                                                "org.freedesktop.DBus.Peer",
                                                "Ping");
        if (!message)
961
          return NULL;
962
963
964
        dbus_connection_send_with_reply (bus, message, &pending, -1);
        dbus_message_unref (message);
        if (!pending)
965
          return NULL;
966
967
968
        bus_name_dup = g_strdup (dest);
        dbus_pending_call_set_notify (pending, reset_hung_process_from_ping,
                                      bus_name_dup, NULL);
969
970
971
972
        for (l = hung_processes; l; l = l->next)
          if (!strcmp (l->data, dest))
            return NULL;
        hung_processes = g_slist_prepend (hung_processes, g_strdup (dest));
973
        return NULL;
974
      }
975
    }
976
    dbus_pending_call_unref (pending);
977
978
    return reply;
}
979
static gboolean
980
Accessibility_DeviceEventListener_NotifyEvent(SpiDEController *controller,
981
982
983
                                              SpiRegistry *registry,
                                              DEControllerListener *listener,
                                              const Accessibility_DeviceEvent *key_event)
984
{
985
986
987
  DBusMessage *message = dbus_message_new_method_call(listener->bus_name,
                                                      listener->path,
                                                      SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER,
988
                                                      "NotifyEvent");
989
  dbus_bool_t consumed = FALSE;
990
  GSList *l;
991
  gboolean hung = FALSE;
992
993
994
995
996

  for (l = hung_processes; l; l = l->next)
  {
    if (!strcmp (l->data, listener->bus_name))
    {
997
998
999
      dbus_message_set_no_reply (message, TRUE);
      hung = TRUE;
      break;
1000
1001
    }
  }
1002

1003
  if (spi_dbus_marshal_deviceEvent(message, key_event))
1004
  {
William Jon McCann's avatar
William Jon McCann committed
1005
1006
    DBusMessage *reply;

1007
1008
1009
1010
1011
1012
    if (hung)
    {
      dbus_connection_send (controller->bus, message, NULL);
      dbus_message_unref (message);
      return FALSE;
    }
William Jon McCann's avatar
William Jon McCann committed
1013
1014

    reply = send_and_allow_reentry (controller->bus, message, 3000, NULL);
1015
1016
    if (reply)
    {
William Jon McCann's avatar
William Jon McCann committed
1017
      dbus_message_get_args(reply, NULL, DBUS_TYPE_BOOLEAN, &consumed, DBUS_TYPE_INVALID);
1018
1019
1020
1021
1022
1023
1024
      dbus_message_unref(reply);
    }
  }
  dbus_message_unref(message);
  return consumed;
}

Mike Gorse's avatar
Mike Gorse committed
1025
gboolean
1026
spi_controller_notify_mouselisteners (SpiDEController                 *controller,
1027
				      const Accessibility_DeviceEvent *event)
1028
1029
1030
1031
1032
{
  GList   *l;
  GSList  *notify = NULL, *l2;
  GList  **listeners = &controller->mouse_listeners;
  gboolean is_consumed;
1033
#ifdef SPI_KEYEVENT_DEBUG
1034
  gboolean found = FALSE;
1035
#endif
1036
1037
1038
1039
1040
1041
1042
1043
1044
  if (!listeners)
    {
      return FALSE;
    }

  for (l = *listeners; l; l = l->next)
    {
       DEControllerListener *listener = l->data;

Mike Gorse's avatar
Mike Gorse committed
1045
       if (eventtype_seq_contains_event (listener->types, event))
1046
         {
1047
1048
1049
	   /* we clone (don't dup) the listener, to avoid refcount inc. */
	   notify = g_slist_prepend (notify,
				     spi_listener_clone (listener));
1050
#ifdef SPI_KEYEVENT_DEBUG
1051
           found = TRUE;
1052
#endif
1053
1054
1055
1056
         }
    }

#ifdef SPI_KEYEVENT_DEBUG
1057
  if (!found)
1058
1059
1060
1061
1062
1063
1064
1065
    {
      g_print ("no match for event\n");
    }
#endif

  is_consumed = FALSE;
  for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
    {
1066
1067
      DEControllerListener *listener = l2->data;

1068
      is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, listener, event);
1069

1070
      spi_listener_clone_free ((DEControllerListener *) l2->data);
1071
1072
1073
1074
    }

  for (; l2; l2 = l2->next)
    {
1075
      DEControllerListener *listener = l2->data;
1076
      spi_listener_clone_free (listener);
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
      /* clone doesn't have its own ref, so don't use spi_device_listener_free */
    }

  g_slist_free (notify);

#ifdef SPI_DEBUG
  if (is_consumed) g_message ("consumed\n");
#endif
  return is_consumed;
}

1088
static gboolean
Mike Gorse's avatar
Mike Gorse committed
1089
key_set_contains_key (GSList                          *key_set,
1090
			  const Accessibility_DeviceEvent *key_event)
1091
1092
1093
{
  gint i;
  gint len;
1094
  GSList *l;
1095

1096
1097
  if (!key_set)
    {
1098
#ifdef SPI_DEBUG
1099
      g_print ("null key set!\n");
1100
#endif
1101
1102
      return TRUE;
    }
1103

1104
  len = g_slist_length (key_set);
1105
1106
1107
  
  if (len == 0) /* special case, means "all keys/any key" */
    {
1108
#ifdef SPI_DEBUG
1109
      g_print ("anykey\n");	    
1110
#endif
1111
1112
1113
      return TRUE;
    }

1114
  for (l = key_set,i = 0; l; l = g_slist_next(l),i++)
1115
    {
1116
      Accessibility_KeyDefinition *kd = l->data;
1117
#ifdef SPI_KEYEVENT_DEBUG	    
1118
1119
      g_print ("key_set[%d] event = %d, code = %d; key_event %d, code %d, string %s\n",
                i,
1120
1121
                (int) kd->keysym,
                (int) kd->keycode,
1122
1123
1124
                (int) key_event->id,
                (int) key_event->hw_code,
                key_event->event_string); 
1125
#endif
1126
      if (kd->keysym == (dbus_uint32_t) key_event->id)
1127
1128
1129
        {
          return TRUE;
	}
1130
      if (kd->keycode == (dbus_uint32_t) key_event->hw_code)
1131
1132
1133
        {
          return TRUE;
	}
billh's avatar
billh committed
1134
      if (key_event->event_string && key_event->event_string[0] &&
Mike Gorse's avatar