Revved to 1.0.0; at-spi 1.0 is now API frozen.
[platform/core/uifw/at-spi2-atk.git] / registryd / deviceeventcontroller.c
index 3f7731c..c0bc354 100644 (file)
@@ -24,7 +24,8 @@
 
 #include <config.h>
 
-#undef SPI_DEBUG
+#undef  SPI_DEBUG
+#undef  SPI_KEYEVENT_DEBUG
 
 #include <string.h>
 #include <ctype.h>
@@ -83,18 +84,20 @@ typedef struct {
 static void     spi_controller_register_with_devices          (SpiDEController           *controller);
 static gboolean spi_controller_update_key_grabs               (SpiDEController           *controller,
                                                               Accessibility_DeviceEvent *recv);
-static void     spi_controller_register_device_listener       (SpiDEController           *controller,
+static gboolean spi_controller_register_device_listener       (SpiDEController           *controller,
                                                               DEControllerListener      *l,
                                                               CORBA_Environment         *ev);
 static void     spi_device_event_controller_forward_key_event (SpiDEController           *controller,
                                                               const XEvent              *event);
 
+#define spi_get_display() GDK_DISPLAY()
+
 /* Private methods */
 
 static KeyCode
 keycode_for_keysym (long keysym)
 {
-  return XKeysymToKeycode (GDK_DISPLAY (), (KeySym) keysym);
+  return XKeysymToKeycode (spi_get_display (), (KeySym) keysym);
 }
 
 static DEControllerGrabMask *
@@ -213,7 +216,10 @@ _deregister_keygrab (SpiDEController      *controller,
       DEControllerGrabMask *cur_mask = l->data;
 
       cur_mask->ref_count--;
-      cur_mask->pending_remove = TRUE;
+      if (cur_mask->ref_count <= 0)
+        {
+          cur_mask->pending_remove = TRUE;
+       }
     }
   else
     {
@@ -233,6 +239,9 @@ handle_keygrab (SpiDEController         *controller,
   if (key_listener->keys->_length == 0) /* special case means AnyKey/AllKeys */
     {
       grab_mask.key_val = AnyKey;
+#ifdef SPI_DEBUG
+      fprintf (stderr, "AnyKey grab!"); */
+#endif
       process_cb (controller, &grab_mask);
     }
   else
@@ -241,25 +250,33 @@ handle_keygrab (SpiDEController         *controller,
 
       for (i = 0; i < key_listener->keys->_length; ++i)
         {
-         long int key_val = key_listener->keys->_buffer[i];
+         Accessibility_KeyDefinition keydef = key_listener->keys->_buffer[i];  
+         long int key_val = keydef.keysym;
          /* X Grabs require keycodes, not keysyms */
-         if (key_val >= 0)
+         if (keydef.keystring && keydef.keystring[0])
+           {
+             key_val = XStringToKeysym(keydef.keystring);                  
+           }
+         if (key_val > 0)
+           {
+             key_val = XKeysymToKeycode (spi_get_display (), (KeySym) key_val);
+           }
+         else
            {
-             key_val = XKeysymToKeycode (GDK_DISPLAY (), (KeySym) key_val);
+             key_val = keydef.keycode;
            }
          grab_mask.key_val = key_val;
-
          process_cb (controller, &grab_mask);
        }
     }
 }
 
-static void
+static gboolean
 spi_controller_register_global_keygrabs (SpiDEController         *controller,
                                         DEControllerKeyListener *key_listener)
 {
   handle_keygrab (controller, key_listener, _register_keygrab);
-  spi_controller_update_key_grabs (controller, NULL);
+  return spi_controller_update_key_grabs (controller, NULL);
 }
 
 static void
@@ -270,7 +287,7 @@ spi_controller_deregister_global_keygrabs (SpiDEController         *controller,
   spi_controller_update_key_grabs (controller, NULL);
 }
 
-static void
+static gboolean
 spi_controller_register_device_listener (SpiDEController      *controller,
                                         DEControllerListener *listener,
                                         CORBA_Environment    *ev)
@@ -285,12 +302,15 @@ spi_controller_register_device_listener (SpiDEController      *controller,
                                                  key_listener);
       if (key_listener->mode->global)
         {
-         spi_controller_register_global_keygrabs (controller, key_listener);   
+         return spi_controller_register_global_keygrabs (controller, key_listener);    
        }
+      else
+             return TRUE;
       break;
     default:
       break;
   }
+  return FALSE; 
 }
 
 static GdkFilterReturn
@@ -318,10 +338,11 @@ _spi_controller_device_error_handler (Display *display, XErrorEvent *error)
   if (error->error_code == BadAccess) 
     {  
       g_message ("Could not complete key grab: grab already in use.\n");
+      return 0;
     }
   else 
     {
-      (*x_default_error_handler) (display, error);
+      return (*x_default_error_handler) (display, error);
     }
 }
 
@@ -338,12 +359,9 @@ spi_controller_register_with_devices (SpiDEController *controller)
                         GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
 
   x_default_error_handler = XSetErrorHandler (_spi_controller_device_error_handler);
-
-  XSelectInput (GDK_DISPLAY (),
-               DefaultRootWindow (GDK_DISPLAY ()),
-               KeyPressMask | KeyReleaseMask);
 }
 
+#define SPI_KEYEVENT_DEBUG
 static gboolean
 spi_key_set_contains_key (Accessibility_KeySet            *key_set,
                          const Accessibility_DeviceEvent *key_event)
@@ -368,15 +386,21 @@ spi_key_set_contains_key (Accessibility_KeySet            *key_set,
   for (i = 0; i < len; ++i)
     {
 #ifdef SPI_KEYEVENT_DEBUG          
-      g_print ("key_set[%d] = %d; key_event %d, code %d\n",
-               i, (int) key_set->_buffer[i],
-              (int) key_event->id, (int) key_event->hw_code); 
+      g_print ("key_set[%d] = %d; key_event %d, code %d, string %s\n",
+               i, (int) key_set->_buffer[i].keycode,
+              (int) key_event->id, (int) key_event->hw_code,
+              key_event->event_string); 
 #endif
-      if (key_set->_buffer[i] == (CORBA_long) key_event->id)
+      if (key_set->_buffer[i].keysym == (CORBA_long) key_event->id)
+        {
+          return TRUE;
+       }
+      if (key_set->_buffer[i].keycode == (CORBA_long) key_event->hw_code)
         {
           return TRUE;
        }
-      if (key_set->_buffer[i] == (CORBA_long) -key_event->hw_code)
+      if (key_event->event_string && key_event->event_string[0] &&
+         !strcmp (key_set->_buffer[i].keystring, key_event->event_string))
         {
           return TRUE;
        }
@@ -472,7 +496,7 @@ spi_notify_keylisteners (GList                          **key_listeners,
 #ifdef SPI_KEYEVENT_DEBUG
   if (!notify)
     {
-      g_print ("no match for listener %d\n", i);
+      g_print ("no match for event\n");
     }
 #endif
 
@@ -498,7 +522,10 @@ spi_notify_keylisteners (GList                          **key_listeners,
     }
 
   g_slist_free (notify);
-  
+
+#ifdef SPI_DEBUG
+  if (is_consumed) g_message ("consumed\n");
+#endif
   return is_consumed;
 }
 
@@ -529,6 +556,9 @@ spi_keystroke_from_x_key_event (XKeyEvent *x_key_event)
         key_event.event_string = CORBA_string_dup ("space");
         break;
       case XK_Tab:
+#ifdef SPI_KEYEVENT_DEBUG
+       fprintf(stderr, "Tab\n");
+#endif
         key_event.event_string = CORBA_string_dup ("Tab");
        break;
       case XK_BackSpace:
@@ -537,6 +567,69 @@ spi_keystroke_from_x_key_event (XKeyEvent *x_key_event)
       case XK_Return:
         key_event.event_string = CORBA_string_dup ("Return");
        break;
+      case XK_Home:
+        key_event.event_string = CORBA_string_dup ("Home");
+       break;
+      case XK_Page_Down:
+        key_event.event_string = CORBA_string_dup ("Page_Down");
+       break;
+      case XK_Page_Up:
+        key_event.event_string = CORBA_string_dup ("Page_Up");
+       break;
+      case XK_F1:
+        key_event.event_string = CORBA_string_dup ("F1");
+       break;
+      case XK_F2:
+        key_event.event_string = CORBA_string_dup ("F2");
+       break;
+      case XK_F3:
+        key_event.event_string = CORBA_string_dup ("F3");
+       break;
+      case XK_F4:
+        key_event.event_string = CORBA_string_dup ("F4");
+       break;
+      case XK_F5:
+        key_event.event_string = CORBA_string_dup ("F5");
+       break;
+      case XK_F6:
+        key_event.event_string = CORBA_string_dup ("F6");
+       break;
+      case XK_F7:
+        key_event.event_string = CORBA_string_dup ("F7");
+       break;
+      case XK_F8:
+        key_event.event_string = CORBA_string_dup ("F8");
+       break;
+      case XK_F9:
+        key_event.event_string = CORBA_string_dup ("F9");
+       break;
+      case XK_F10:
+        key_event.event_string = CORBA_string_dup ("F10");
+       break;
+      case XK_F11:
+        key_event.event_string = CORBA_string_dup ("F11");
+       break;
+      case XK_F12:
+        key_event.event_string = CORBA_string_dup ("F12");
+       break;
+      case XK_End:
+        key_event.event_string = CORBA_string_dup ("End");
+       break;
+      case XK_Escape:
+        key_event.event_string = CORBA_string_dup ("Escape");
+       break;
+      case XK_Up:
+        key_event.event_string = CORBA_string_dup ("Up");
+       break;
+      case XK_Down:
+        key_event.event_string = CORBA_string_dup ("Down");
+       break;
+      case XK_Left:
+        key_event.event_string = CORBA_string_dup ("Left");
+       break;
+      case XK_Right:
+        key_event.event_string = CORBA_string_dup ("Right");
+       break;
       default:
         if (XLookupString (x_key_event, cbuf, cbuf_bytes, &keysym, NULL) > 0)
           {
@@ -595,6 +688,7 @@ spi_controller_update_key_grabs (SpiDEController           *controller,
       next = l->next;
 
       re_issue_grab = recv &&
+/*           (recv->type == Accessibility_KEY_RELEASED) && - (?) */
              (recv->modifiers & grab_mask->mod_mask) &&
              (grab_mask->key_val == keycode_for_keysym (recv->id));
 
@@ -618,7 +712,7 @@ spi_controller_update_key_grabs (SpiDEController           *controller,
 #ifdef SPI_DEBUG
       fprintf (stderr, "ungrabbing, mask=%x\n", grab_mask->mod_mask);
 #endif
-         XUngrabKey (GDK_DISPLAY (),
+         XUngrabKey (spi_get_display (),
                      grab_mask->key_val,
                      grab_mask->mod_mask,
                      gdk_x11_get_default_root_xwindow ());
@@ -631,7 +725,7 @@ spi_controller_update_key_grabs (SpiDEController           *controller,
 #ifdef SPI_DEBUG
          fprintf (stderr, "grab with mask %x\n", grab_mask->mod_mask);
 #endif
-          XGrabKey (GDK_DISPLAY (),
+          XGrabKey (spi_get_display (),
                    grab_mask->key_val,
                    grab_mask->mod_mask,
                    gdk_x11_get_default_root_xwindow (),
@@ -673,7 +767,7 @@ spi_device_event_controller_object_finalize (GObject *object)
   fprintf(stderr, "spi_device_event_controller_object_finalize called\n");
 #endif
   /* disconnect any special listeners, get rid of outstanding keygrabs */
-  XUngrabKey (GDK_DISPLAY (), AnyKey, AnyModifier, DefaultRootWindow (GDK_DISPLAY ()));
+  XUngrabKey (spi_get_display (), AnyKey, AnyModifier, DefaultRootWindow (spi_get_display ()));
        
   spi_device_event_controller_parent_class->finalize (object);
 }
@@ -682,7 +776,7 @@ spi_device_event_controller_object_finalize (GObject *object)
  * CORBA Accessibility::DEController::registerKeystrokeListener
  *     method implementation
  */
-static void
+static CORBA_boolean
 impl_register_keystroke_listener (PortableServer_Servant                  servant,
                                  const Accessibility_DeviceEventListener l,
                                  const Accessibility_KeySet             *keys,
@@ -699,8 +793,8 @@ impl_register_keystroke_listener (PortableServer_Servant                  servan
           (void *) l, (unsigned long) mask);
 #endif
   dec_listener = spi_dec_key_listener_new (l, keys, mask, type, mode, ev);
-  spi_controller_register_device_listener (
-    controller, (DEControllerListener *) dec_listener, ev);
+  return spi_controller_register_device_listener (
+         controller, (DEControllerListener *) dec_listener, ev);
 }
 
 
@@ -819,17 +913,17 @@ impl_generate_keyboard_event (PortableServer_Servant           servant,
   switch (synth_type)
     {
       case Accessibility_KEY_PRESS:
-        XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, True, CurrentTime);
+        XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, True, CurrentTime);
        break;
       case Accessibility_KEY_PRESSRELEASE:
-       XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, True, CurrentTime);
+       XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, True, CurrentTime);
       case Accessibility_KEY_RELEASE:
-       XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, False, CurrentTime);
+       XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, False, CurrentTime);
        break;
       case Accessibility_KEY_SYM:
        key_synth_code = keycode_for_keysym (keycode);
-       XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) key_synth_code, True, CurrentTime);
-       XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) key_synth_code, False, CurrentTime);
+       XTestFakeKeyEvent (spi_get_display (), (unsigned int) key_synth_code, True, CurrentTime);
+       XTestFakeKeyEvent (spi_get_display (), (unsigned int) key_synth_code, False, CurrentTime);
        break;
       case Accessibility_KEY_STRING:
        fprintf (stderr, "Not yet implemented\n");
@@ -849,11 +943,58 @@ impl_generate_mouse_event (PortableServer_Servant servant,
                           const CORBA_char      *eventName,
                           CORBA_Environment     *ev)
 {
+  int button;
+  gboolean error = FALSE;
+  Display *display = spi_get_display ();
 #ifdef SPI_DEBUG
   fprintf (stderr, "generating mouse %s event at %ld, %ld\n",
           eventName, (long int) x, (long int) y);
 #endif
-  g_warning ("not yet implemented");
+  g_message ("mouse event synthesis\n");
+  switch (eventName[0])
+    {
+      case 'b':
+        switch (eventName[1])
+         {
+         /* TODO: check number of buttons before parsing */
+         case '1':
+                   button = 1;
+                   break;
+         case '2':
+                 button = 2;
+                 break;
+         case '3':
+                 button = 3;
+                 break;
+         default:
+                 error = TRUE;
+         }
+       if (!error)
+         {
+           if (x != -1 && y != -1)
+             {
+               XTestFakeMotionEvent (display, DefaultScreen (display),
+                                     x, y, 0);
+             }
+           XTestFakeButtonEvent (display, button, !(eventName[2] == 'r'), 0);
+           if (eventName[2] == 'c')
+             XTestFakeButtonEvent (display, button, FALSE, 1);
+           else if (eventName[2] == 'd')
+             {
+             XTestFakeButtonEvent (display, button, FALSE, 1);
+             XTestFakeButtonEvent (display, button, TRUE, 2);
+             XTestFakeButtonEvent (display, button, FALSE, 3);
+             }
+         }
+       break;
+      case 'r': /* relative motion */ 
+       XTestFakeRelativeMotionEvent (display, x, y, 0);
+        break;
+      case 'a': /* absolute motion */
+       XTestFakeMotionEvent (display, DefaultScreen (display),
+                             x, y, 0);
+        break;
+    }
 }
 
 /* Accessibility::DEController::notifyListenersSync */
@@ -934,6 +1075,9 @@ spi_device_event_controller_forward_key_event (SpiDEController *controller,
   CORBA_exception_init (&ev);
 
   key_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event);
+
+  spi_controller_update_key_grabs (controller, &key_event);
+
   /* relay to listeners, and decide whether to consume it or not */
   is_consumed = spi_notify_keylisteners (
     &controller->key_listeners, &key_event, CORBA_TRUE, &ev);
@@ -942,14 +1086,12 @@ spi_device_event_controller_forward_key_event (SpiDEController *controller,
 
   if (is_consumed)
     {
-      XAllowEvents (GDK_DISPLAY (), AsyncKeyboard, CurrentTime);
+      XAllowEvents (spi_get_display (), AsyncKeyboard, CurrentTime);
     }
   else
     {
-      XAllowEvents (GDK_DISPLAY (), ReplayKeyboard, CurrentTime);
+      XAllowEvents (spi_get_display (), ReplayKeyboard, CurrentTime);
     }
-
-  spi_controller_update_key_grabs (controller, &key_event);
 }
 
 SpiDEController *