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.
This commit is contained in:
Alexander Larsson 2013-11-12 16:11:15 +01:00
parent d21ac217d3
commit 82acc05cba
9 changed files with 165 additions and 6 deletions

View File

@ -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',
@ -75,6 +76,18 @@ typedef struct {
gint32 dir;
} BroadwayInputScrollMsg;
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 */
@ -118,6 +131,7 @@ typedef union {
BroadwayInputCrossingMsg crossing;
BroadwayInputButtonMsg button;
BroadwayInputScrollMsg scroll;
BroadwayInputTouchMsg touch;
BroadwayInputKeyMsg key;
BroadwayInputGrabReply grab_reply;
BroadwayInputConfigureNotify configure_notify;

View File

@ -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++);

View File

@ -2462,14 +2462,47 @@ function onMouseWheel(ev)
function onTouchStart(ev) {
event.preventDefault();
}
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", [0, id, touch.identifier, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState]);
}
}
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 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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -37,6 +37,7 @@ struct _GdkBroadwayDeviceManager
GdkDeviceManager parent_object;
GdkDevice *core_pointer;
GdkDevice *core_keyboard;
GdkDevice *touchscreen;
};
struct _GdkBroadwayDeviceManagerClass

View File

@ -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;

View File

@ -59,6 +59,8 @@ struct _GdkBroadwayDisplay
GdkBroadwayServer *server;
guint32 touch_sequence_down;
gpointer move_resize_data;
};

View File

@ -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));
@ -204,6 +208,63 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
_gdk_windowing_got_event (display, node, event, message->base.serial);
}
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:
@ -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);