display: Set an X11 passive touch grab on the root window

Touch events will be caught first by the compositor this way,
whenever the MetaGestureTracker notifies of the accepted/rejected
state of a sequence, XIAllowTouchEvents() will be called on it
accordingly, so it is handled exclusively by the compositor or
punted to clients.
This commit is contained in:
Carlos Garnacho 2014-06-19 23:13:38 +02:00
parent ba086dea8c
commit 8030a2972e

View File

@ -51,6 +51,8 @@
#include "meta-cursor-tracker-private.h"
#include "meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h>
#include "compositor-private.h"
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
@ -146,6 +148,11 @@ static void update_window_grab_modifiers (MetaDisplay *display);
static void prefs_changed_callback (MetaPreference pref,
void *data);
static void meta_display_grab_window_touch (MetaDisplay *display,
Window xwindow);
static void meta_display_ungrab_window_touch (MetaDisplay *display,
Window xwindow);
static void
meta_display_get_property(GObject *object,
guint prop_id,
@ -413,6 +420,28 @@ meta_set_gnome_wm_keybindings (const char *wm_keybindings)
gnome_wm_keybindings = wm_keybindings;
}
static void
gesture_tracker_state_changed (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state,
MetaDisplay *display)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
int event_mode;
if (state == META_SEQUENCE_ACCEPTED)
event_mode = XIAcceptTouch;
else if (state == META_SEQUENCE_REJECTED)
event_mode = XIRejectTouch;
else
return;
XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID,
clutter_x11_event_sequence_get_touch_detail (sequence),
DefaultRootWindow (display->xdisplay), event_mode);
}
/**
* meta_display_open:
*
@ -810,6 +839,10 @@ meta_display_open (void)
/* Set up touch support */
the_display->gesture_tracker = meta_gesture_tracker_new (0);
g_signal_connect (the_display->gesture_tracker, "state-changed",
G_CALLBACK (gesture_tracker_state_changed), the_display);
meta_display_grab_window_touch (the_display,
DefaultRootWindow (the_display->xdisplay));
/* We know that if mutter is running as a Wayland compositor,
* we start out with no windows.
@ -980,6 +1013,10 @@ meta_display_close (MetaDisplay *display,
meta_display_remove_autoraise_callback (display);
meta_display_ungrab_window_touch (display,
DefaultRootWindow (display->xdisplay));
g_clear_object (&display->gesture_tracker);
if (display->focus_timeout_id)
g_source_remove (display->focus_timeout_id);
display->focus_timeout_id = 0;
@ -2058,6 +2095,35 @@ meta_display_ungrab_window_buttons (MetaDisplay *display,
}
}
static void
meta_display_grab_window_touch (MetaDisplay *display,
Window xwindow)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID,
xwindow, False, &mask, 1, &mods);
}
static void
meta_display_ungrab_window_touch (MetaDisplay *display,
Window xwindow)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
XIGrabModifiers mods = { XIAnyModifier, 0 };
XIUngrabTouchBegin (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID, xwindow, 1, &mods);
}
/* Grab buttons we only grab while unfocused in click-to-focus mode */
#define MAX_FOCUS_BUTTON 4
void