[gtk+] broadway: Add initial touch event support



commit 82acc05cba84eeb11cbfc97e9b5cb4c8763bb39b
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Nov 12 16:11:15 2013 +0100

    broadway: Add initial touch event support
    
    This seems to get something going on an ipad, but some events seem
    to get swallowed. For instance, window dragging doesn't work.

 gdk/broadway/broadway-protocol.h         |   14 +++++++
 gdk/broadway/broadway-server.c           |   22 ++++++++++
 gdk/broadway/broadway.js                 |   39 +++++++++++++++++-
 gdk/broadway/broadwayd.c                 |    2 +
 gdk/broadway/gdkdevicemanager-broadway.c |   24 +++++++++++
 gdk/broadway/gdkdevicemanager-broadway.h |    1 +
 gdk/broadway/gdkdisplay-broadway.c       |    2 +-
 gdk/broadway/gdkdisplay-broadway.h       |    2 +
 gdk/broadway/gdkeventsource.c            |   63 +++++++++++++++++++++++++++++-
 9 files changed, 164 insertions(+), 5 deletions(-)
---
diff --git a/gdk/broadway/broadway-protocol.h b/gdk/broadway/broadway-protocol.h
index 5fffd6c..5d53ad4 100644
--- a/gdk/broadway/broadway-protocol.h
+++ b/gdk/broadway/broadway-protocol.h
@@ -14,6 +14,7 @@ typedef enum {
   BROADWAY_EVENT_POINTER_MOVE = 'm',
   BROADWAY_EVENT_BUTTON_PRESS = 'b',
   BROADWAY_EVENT_BUTTON_RELEASE = 'B',
+  BROADWAY_EVENT_TOUCH = 't',
   BROADWAY_EVENT_SCROLL = 's',
   BROADWAY_EVENT_KEY_PRESS = 'k',
   BROADWAY_EVENT_KEY_RELEASE = 'K',
@@ -77,6 +78,18 @@ typedef struct {
 
 typedef struct {
   BroadwayInputBaseMsg base;
+  guint32 touch_type;
+  guint32 event_window_id;
+  guint32 sequence_id;
+  gint32 root_x;
+  gint32 root_y;
+  gint32 win_x;
+  gint32 win_y;
+  guint32 state;
+} BroadwayInputTouchMsg;
+
+typedef struct {
+  BroadwayInputBaseMsg base;
   guint32 mouse_window_id; /* The real window, not taking grabs into account */
   guint32 state;
   gint32 key;
@@ -118,6 +131,7 @@ typedef union {
   BroadwayInputCrossingMsg crossing;
   BroadwayInputButtonMsg button;
   BroadwayInputScrollMsg scroll;
+  BroadwayInputTouchMsg touch;
   BroadwayInputKeyMsg key;
   BroadwayInputGrabReply grab_reply;
   BroadwayInputConfigureNotify configure_notify;
diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c
index f648335..9fbd6b9 100644
--- a/gdk/broadway/broadway-server.c
+++ b/gdk/broadway/broadway-server.c
@@ -236,6 +236,9 @@ update_event_state (BroadwayServer *server,
     server->last_state = message->pointer.state;
     server->real_mouse_in_toplevel_id = message->pointer.mouse_window_id;
     break;
+  case BROADWAY_EVENT_TOUCH:
+    server->last_state = message->touch.state;
+    break;
   case BROADWAY_EVENT_KEY_PRESS:
   case BROADWAY_EVENT_KEY_RELEASE:
     server->last_state = message->key.state;
@@ -368,6 +371,21 @@ parse_pointer_data (guint32 *p, BroadwayInputPointerMsg *data)
   return p;
 }
 
+static guint32 *
+parse_touch_data (guint32 *p, BroadwayInputTouchMsg *data)
+{
+  data->touch_type = ntohl (*p++);
+  data->event_window_id = ntohl (*p++);
+  data->sequence_id = ntohl (*p++);
+  data->root_x = ntohl (*p++);
+  data->root_y = ntohl (*p++);
+  data->win_x = ntohl (*p++);
+  data->win_y = ntohl (*p++);
+  data->state = ntohl (*p++);
+
+  return p;
+}
+
 static void
 update_future_pointer_info (BroadwayServer *server, BroadwayInputPointerMsg *data)
 {
@@ -436,6 +454,10 @@ parse_input_message (BroadwayInput *input, const unsigned char *message)
     msg.scroll.dir = ntohl (*p++);
     break;
 
+  case BROADWAY_EVENT_TOUCH:
+    p = parse_touch_data (p, &msg.touch);
+    break;
+
   case BROADWAY_EVENT_KEY_PRESS:
   case BROADWAY_EVENT_KEY_RELEASE:
     msg.key.mouse_window_id = ntohl (*p++);
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index 18d0d7f..caea0c9 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -2462,14 +2462,47 @@ function onMouseWheel(ev)
 
 function onTouchStart(ev) {
     event.preventDefault();
+
+    updateForEvent(ev);
+
+    for (var i = 0; i < ev.changedTouches.length; i++) {
+        var touch = ev.changedTouches.item(i);
+
+        var id = getSurfaceId(touch);
+        var pos = getPositionsFromEvent(touch, id);
+
+        sendInput ("t", [0, id, touch.identifier, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState]);
+    }
 }
 
-function onTouchEnd(ev) {
+function onTouchMove(ev) {
     event.preventDefault();
+
+    updateForEvent(ev);
+
+    for (var i = 0; i < ev.changedTouches.length; i++) {
+        var touch = ev.changedTouches.item(i);
+
+        var id = getSurfaceId(touch);
+        var pos = getPositionsFromEvent(touch, id);
+
+        sendInput ("t", [1, id, touch.identifier, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState]);
+    }
 }
 
-function onTouchMove(ev) {
+function onTouchEnd(ev) {
     event.preventDefault();
+
+    updateForEvent(ev);
+
+    for (var i = 0; i < ev.changedTouches.length; i++) {
+        var touch = ev.changedTouches.item(i);
+
+        var id = getSurfaceId(touch);
+        var pos = getPositionsFromEvent(touch, id);
+
+        sendInput ("t", [2, id, touch.identifier, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState]);
+    }
 }
 
 function setupDocument(document)
@@ -2489,7 +2522,7 @@ function setupDocument(document)
       document.addEventListener('mousewheel', onMouseWheel, false);
       document.addEventListener('touchstart', onTouchStart, false);
       document.addEventListener('touchmove', onTouchMove, false);
-      document.addEventListener('touchstart', onTouchEnd, false);
+      document.addEventListener('touchend', onTouchEnd, false);
     } else if (document.attachEvent) {
       element.attachEvent("onmousewheel", onMouseWheel);
     }
diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c
index 8c24a4f..a4bed34 100644
--- a/gdk/broadway/broadwayd.c
+++ b/gdk/broadway/broadwayd.c
@@ -528,6 +528,8 @@ get_event_size (int type)
       return sizeof (BroadwayInputButtonMsg);
     case BROADWAY_EVENT_SCROLL:
       return sizeof (BroadwayInputScrollMsg);
+    case BROADWAY_EVENT_TOUCH:
+      return sizeof (BroadwayInputTouchMsg);
     case BROADWAY_EVENT_KEY_PRESS:
     case BROADWAY_EVENT_KEY_RELEASE:
       return  sizeof (BroadwayInputKeyMsg);
diff --git a/gdk/broadway/gdkdevicemanager-broadway.c b/gdk/broadway/gdkdevicemanager-broadway.c
index eeeeac2..8618eaf 100644
--- a/gdk/broadway/gdkdevicemanager-broadway.c
+++ b/gdk/broadway/gdkdevicemanager-broadway.c
@@ -79,6 +79,21 @@ create_core_keyboard (GdkDeviceManager *device_manager,
                        NULL);
 }
 
+static GdkDevice *
+create_touchscreen (GdkDeviceManager *device_manager,
+                    GdkDisplay       *display)
+{
+  return g_object_new (GDK_TYPE_BROADWAY_DEVICE,
+                       "name", "Touchscreen",
+                       "type", GDK_DEVICE_TYPE_SLAVE,
+                       "input-source", GDK_SOURCE_TOUCHSCREEN,
+                       "input-mode", GDK_MODE_SCREEN,
+                       "has-cursor", FALSE,
+                       "display", display,
+                       "device-manager", device_manager,
+                       NULL);
+}
+
 static void
 gdk_broadway_device_manager_init (GdkBroadwayDeviceManager *device_manager)
 {
@@ -93,6 +108,7 @@ gdk_broadway_device_manager_finalize (GObject *object)
 
   g_object_unref (device_manager->core_pointer);
   g_object_unref (device_manager->core_keyboard);
+  g_object_unref (device_manager->touchscreen);
 
   G_OBJECT_CLASS (gdk_broadway_device_manager_parent_class)->finalize (object);
 }
@@ -107,9 +123,12 @@ gdk_broadway_device_manager_constructed (GObject *object)
   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
   device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager), display);
   device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager), display);
+  device_manager->touchscreen = create_touchscreen (GDK_DEVICE_MANAGER (device_manager), display);
 
   _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
   _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
+  _gdk_device_set_associated_device (device_manager->touchscreen, device_manager->core_pointer);
+  _gdk_device_add_slave (device_manager->core_pointer, device_manager->touchscreen);
 }
 
 
@@ -126,6 +145,11 @@ gdk_broadway_device_manager_list_devices (GdkDeviceManager *device_manager,
       devices = g_list_prepend (devices, broadway_device_manager->core_pointer);
     }
 
+  if (type == GDK_DEVICE_TYPE_SLAVE)
+    {
+      devices = g_list_prepend (devices, broadway_device_manager->touchscreen);
+    }
+
   return devices;
 }
 
diff --git a/gdk/broadway/gdkdevicemanager-broadway.h b/gdk/broadway/gdkdevicemanager-broadway.h
index 5e5af7a..93bc275 100644
--- a/gdk/broadway/gdkdevicemanager-broadway.h
+++ b/gdk/broadway/gdkdevicemanager-broadway.h
@@ -37,6 +37,7 @@ struct _GdkBroadwayDeviceManager
   GdkDeviceManager parent_object;
   GdkDevice *core_pointer;
   GdkDevice *core_keyboard;
+  GdkDevice *touchscreen;
 };
 
 struct _GdkBroadwayDeviceManagerClass
diff --git a/gdk/broadway/gdkdisplay-broadway.c b/gdk/broadway/gdkdisplay-broadway.c
index 36ce569..94a324e 100644
--- a/gdk/broadway/gdkdisplay-broadway.c
+++ b/gdk/broadway/gdkdisplay-broadway.c
@@ -102,7 +102,7 @@ gdk_broadway_display_init_input (GdkDisplay *display)
 
   for (l = list; l; l = l->next)
     {
-      device = list->data;
+      device = l->data;
 
       if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
         continue;
diff --git a/gdk/broadway/gdkdisplay-broadway.h b/gdk/broadway/gdkdisplay-broadway.h
index 401ac6f..9066261 100644
--- a/gdk/broadway/gdkdisplay-broadway.h
+++ b/gdk/broadway/gdkdisplay-broadway.h
@@ -59,6 +59,8 @@ struct _GdkBroadwayDisplay
 
   GdkBroadwayServer *server;
 
+  guint32 touch_sequence_down;
+
   gpointer move_resize_data;
 };
 
diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c
index 5330d6b..a7d3c6e 100644
--- a/gdk/broadway/gdkeventsource.c
+++ b/gdk/broadway/gdkeventsource.c
@@ -18,6 +18,7 @@
 #include "config.h"
 
 #include "gdkeventsource.h"
+#include "gdkdevicemanager-broadway.h"
 
 #include "gdkinternals.h"
 
@@ -93,11 +94,14 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
 {
   GdkDisplay *display = gdk_display_get_default ();
   GdkBroadwayDisplay *display_broadway = GDK_BROADWAY_DISPLAY (display);
+  GdkBroadwayDeviceManager *device_manager;
   GdkScreen *screen;
   GdkWindow *window;
   GdkEvent *event = NULL;
   GList *node;
 
+  device_manager = GDK_BROADWAY_DEVICE_MANAGER (gdk_display_get_device_manager (display));
+
   switch (message->base.type) {
   case BROADWAY_EVENT_ENTER:
     window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER 
(message->pointer.event_window_id));
@@ -205,6 +209,63 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
       }
 
     break;
+  case BROADWAY_EVENT_TOUCH:
+    window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->touch.event_window_id));
+    if (window)
+      {
+        GdkEventType event_type = 0;
+        gboolean is_first_down = FALSE;
+
+        switch (message->touch.touch_type) {
+        case 0:
+          event_type = GDK_TOUCH_BEGIN;
+          break;
+        case 1:
+          event_type = GDK_TOUCH_UPDATE;
+          break;
+        case 2:
+          event_type = GDK_TOUCH_END;
+          break;
+        default:
+          g_printerr ("_gdk_broadway_events_got_input - Unknown touch type %d\n", message->touch.touch_type);
+        }
+
+        if (event_type == GDK_TOUCH_BEGIN &&
+            display_broadway->touch_sequence_down == 0)
+          display_broadway->touch_sequence_down = message->touch.sequence_id;
+
+        if (display_broadway->touch_sequence_down == message->touch.sequence_id)
+          is_first_down = TRUE;
+
+        if (event_type == GDK_TOUCH_END &&
+            display_broadway->touch_sequence_down == message->touch.sequence_id)
+          display_broadway->touch_sequence_down = 0;
+
+       event = gdk_event_new (event_type);
+       event->touch.window = g_object_ref (window);
+       event->touch.sequence = GUINT_TO_POINTER(message->touch.sequence_id);
+       event->touch.emulating_pointer = is_first_down;
+       event->touch.time = message->base.time;
+       event->touch.x = message->touch.win_x;
+       event->touch.y = message->touch.win_y;
+       event->touch.x_root = message->touch.root_x;
+       event->touch.y_root = message->touch.root_y;
+       event->touch.state = message->touch.state;
+
+       gdk_event_set_device (event, device_manager->core_pointer);
+       gdk_event_set_source_device (event, device_manager->touchscreen);
+
+        if (is_first_down)
+          _gdk_event_set_pointer_emulated (event, TRUE);
+
+        if (event_type == GDK_TOUCH_BEGIN || event_type == GDK_TOUCH_UPDATE)
+          event->touch.state |= GDK_BUTTON1_MASK;
+
+       node = _gdk_event_queue_append (display, event);
+       _gdk_windowing_got_event (display, node, event, message->base.serial);
+      }
+
+    break;
   case BROADWAY_EVENT_KEY_PRESS:
   case BROADWAY_EVENT_KEY_RELEASE:
     window = g_hash_table_lookup (display_broadway->id_ht,
@@ -218,7 +279,7 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
        event->key.state = message->key.state;
        event->key.hardware_keycode = message->key.key;
        event->key.length = 0;
-       gdk_event_set_device (event, display->core_pointer);
+       gdk_event_set_device (event, device_manager->core_keyboard);
 
        node = _gdk_event_queue_append (display, event);
        _gdk_windowing_got_event (display, node, event, message->base.serial);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]