[mutter/wip/multitouch: 7/8] window: Implement window moving through touch events
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/multitouch: 7/8] window: Implement window moving through touch events
- Date: Sat, 6 Aug 2011 09:16:33 +0000 (UTC)
commit 1546cba268581d7a4da27eadf7f85c14957a5ad8
Author: Carlos Garnacho <carlosg gnome org>
Date: Tue Aug 2 19:29:07 2011 +0200
window: Implement window moving through touch events
Window moving is triggered by 3-4 simultaneous touch events on
the window, the hotspot being in the center of the touch area
bounding rect.
src/core/display-private.h | 7 ++
src/core/display.c | 27 +++++++++
src/core/window-private.h | 7 ++
src/core/window.c | 137 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 178 insertions(+), 0 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 24711f9..ae83e93 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -59,6 +59,7 @@ typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
typedef struct _MetaGrabInfo MetaGrabInfo;
typedef struct _MetaFocusInfo MetaFocusInfo;
+typedef struct _MetaTouchInfo MetaTouchInfo;
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
Window xwindow,
@@ -147,6 +148,12 @@ struct _MetaFocusInfo
guint32 last_focus_time;
};
+struct _MetaTouchInfo
+{
+ gdouble root_x;
+ gdouble root_y;
+};
+
struct _MetaDisplay
{
GObject parent_instance;
diff --git a/src/core/display.c b/src/core/display.c
index b349c6f..44d0806 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1761,6 +1761,9 @@ event_callback (XEvent *event,
gdouble ev_root_x, ev_root_y;
MetaDevice *device;
+ if (meta_input_event_ignore (display, event))
+ return FALSE;
+
if (window && !window->override_redirect &&
((evtype == KeyPress) || (evtype == ButtonPress)))
{
@@ -1808,6 +1811,14 @@ event_callback (XEvent *event,
filter_out_event = bypass_compositor = TRUE;
break;
case ButtonPress:
+ if (window &&
+ meta_input_event_get_touch_id (display, event, NULL))
+ {
+ meta_window_update_touch (window, event);
+ filter_out_event = TRUE;
+ break;
+ }
+
meta_input_event_get_button (display, event, &n_button);
meta_input_event_get_state (display, event, &state);
meta_input_event_get_coordinates (display, event,
@@ -2023,6 +2034,14 @@ event_callback (XEvent *event,
}
break;
case ButtonRelease:
+ if (window &&
+ meta_input_event_get_touch_id (display, event, NULL))
+ {
+ meta_window_end_touch (window, event);
+ filter_out_event = TRUE;
+ break;
+ }
+
if (grab_info && grab_info->grab_op == META_GRAB_OP_COMPOSITOR)
break;
@@ -2032,6 +2051,14 @@ event_callback (XEvent *event,
meta_window_handle_mouse_grab_op_event (window, event);
break;
case MotionNotify:
+ if (window &&
+ meta_input_event_get_touch_id (display, event, NULL))
+ {
+ meta_window_update_touch (window, event);
+ filter_out_event = TRUE;
+ break;
+ }
+
if (grab_info && grab_info->grab_op == META_GRAB_OP_COMPOSITOR)
break;
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 9a78d45..687c140 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -411,6 +411,8 @@ struct _MetaWindow
/* Focus info if the window is focused, or NULL */
MetaFocusInfo *cur_focus;
+
+ GHashTable *cur_touches;
};
struct _MetaWindowClass
@@ -671,4 +673,9 @@ MetaDevice * meta_window_get_client_pointer (MetaWindow *window);
MetaDevice * meta_window_guess_grab_pointer (MetaWindow *window);
+gboolean meta_window_update_touch (MetaWindow *window,
+ XEvent *event);
+void meta_window_end_touch (MetaWindow *window,
+ XEvent *event);
+
#endif
diff --git a/src/core/window.c b/src/core/window.c
index ae84d9d..6dc9fd2 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -200,6 +200,9 @@ meta_window_finalize (GObject *object)
if (window->menu)
meta_ui_window_menu_free (window->menu);
+ if (window->cur_touches)
+ g_hash_table_destroy (window->cur_touches);
+
meta_icon_cache_free (&window->icon_cache);
g_free (window->sm_client_id);
@@ -10566,3 +10569,137 @@ meta_window_guess_grab_pointer (MetaWindow *window)
return meta_window_get_client_pointer (window);
}
+
+typedef struct
+{
+ gdouble top_left_x;
+ gdouble top_left_y;
+ gdouble bottom_right_x;
+ gdouble bottom_right_y;
+} BoundingRectCoords;
+
+static void
+calculate_touch_bounding_rect (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ BoundingRectCoords *bounding_rect = user_data;
+ MetaTouchInfo *touch_info = value;
+
+ if (touch_info->root_x < bounding_rect->top_left_x)
+ bounding_rect->top_left_x = touch_info->root_x;
+ if (touch_info->root_x > bounding_rect->bottom_right_x)
+ bounding_rect->bottom_right_x = touch_info->root_x;
+
+ if (touch_info->root_y < bounding_rect->top_left_y)
+ bounding_rect->top_left_y = touch_info->root_y;
+ if (touch_info->root_y > bounding_rect->bottom_right_y)
+ bounding_rect->bottom_right_y = touch_info->root_y;
+}
+
+gboolean
+meta_window_update_touch (MetaWindow *window,
+ XEvent *event)
+{
+ gdouble root_x, root_y;
+ MetaTouchInfo *touch_info;
+ gboolean new_touch = FALSE;
+ MetaDevice *device;
+ guint touch_id, n_touches;
+ Time evtime;
+
+ if (!window->cur_touches)
+ window->cur_touches = g_hash_table_new (NULL, NULL);
+
+ meta_input_event_get_touch_id (window->display,
+ event, &touch_id);
+
+ touch_info = g_hash_table_lookup (window->cur_touches,
+ GUINT_TO_POINTER (touch_id));
+
+ if (!touch_info &&
+ g_hash_table_size (window->cur_touches) == 3)
+ return FALSE;
+
+ meta_input_event_get_coordinates (window->display, event,
+ NULL, NULL,
+ &root_x, &root_y);
+ evtime = meta_input_event_get_time (window->display, event);
+ device = meta_input_event_get_device (window->display, event);
+
+ if (!touch_info)
+ {
+ touch_info = g_slice_new (MetaTouchInfo);
+ g_hash_table_insert (window->cur_touches,
+ GUINT_TO_POINTER (touch_id),
+ touch_info);
+ new_touch = TRUE;
+ }
+
+ touch_info->root_x = root_x;
+ touch_info->root_y = root_y;
+ n_touches = g_hash_table_size (window->cur_touches);
+
+ if (n_touches == 3)
+ {
+ gdouble x, y, width, height;
+ BoundingRectCoords bounding_rect = { DBL_MAX, DBL_MAX,
+ DBL_MIN, DBL_MIN };
+
+ g_hash_table_foreach (window->cur_touches,
+ calculate_touch_bounding_rect,
+ &bounding_rect);
+
+ /* Get x/y coordinates at the middle of the bounding box,
+ * this will be the hotspot for the window moving operation
+ */
+ width = bounding_rect.bottom_right_x - bounding_rect.top_left_x;
+ height = bounding_rect.bottom_right_y - bounding_rect.top_left_y;
+ x = bounding_rect.top_left_x + (width / 2);
+ y = bounding_rect.top_left_y + (height / 2);
+
+ if (new_touch)
+ {
+ /* Start window move operation with the
+ * bounding rectangle center as the hotspot
+ */
+ meta_display_begin_grab_op (window->display,
+ window->screen,
+ window,
+ device,
+ META_GRAB_OP_MOVING,
+ TRUE, FALSE,
+ 1, 0,
+ evtime,
+ x, y);
+ }
+ else if (window->cur_grab)
+ update_move (window, device, FALSE, x, y);
+ }
+
+ return FALSE;
+}
+
+void
+meta_window_end_touch (MetaWindow *window,
+ XEvent *event)
+{
+ guint touch_id;
+ Time evtime;
+
+ meta_input_event_get_touch_id (window->display, event, &touch_id);
+ evtime = meta_input_event_get_time (window->display, event);
+
+ if (!g_hash_table_remove (window->cur_touches,
+ GUINT_TO_POINTER (touch_id)))
+ return;
+
+ if (g_hash_table_size (window->cur_touches) == 2)
+ {
+ MetaDevice *device;
+
+ device = meta_input_event_get_device (window->display, event);
+ meta_display_end_grab_op (window->display, device, evtime);
+ }
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]