recorder: port to XInput2

Pointer tracking is broken when the pointer is over the stage input
area.  This is apparently fallout from mutter going to XInput2.

This commit changes the mouse event handling code to also use XInput2.

https://bugzilla.gnome.org/show_bug.cgi?id=695324
This commit is contained in:
Ray Strode 2013-03-11 12:31:52 -04:00
parent e80795b7f0
commit ddced79475

View File

@ -19,6 +19,11 @@
#include <clutter/x11/clutter-x11.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
/* This is also hard-coded in mutter and GDK */
#define VIRTUAL_CORE_POINTER_ID 2
typedef enum {
RECORDER_STATE_CLOSED,
@ -57,6 +62,8 @@ struct _ShellRecorder {
gboolean have_xfixes;
int xfixes_event_base;
int xinput_opcode;
CoglHandle recording_icon; /* icon shown while playing */
cairo_surface_t *cursor_image;
@ -661,10 +668,15 @@ recorder_event_filter (XEvent *xev,
gpointer data)
{
ShellRecorder *recorder = data;
XIEvent *input_event = NULL;
if (xev->xany.window != clutter_x11_get_stage_window (recorder->stage))
return CLUTTER_X11_FILTER_CONTINUE;
if (xev->xany.type == GenericEvent &&
xev->xcookie.extension == recorder->xinput_opcode)
input_event = (XIEvent *) xev->xcookie.data;
if (xev->xany.type == recorder->xfixes_event_base + XFixesCursorNotify)
{
XFixesCursorNotifyEvent *notify_event = (XFixesCursorNotifyEvent *)xev;
@ -680,36 +692,53 @@ recorder_event_filter (XEvent *xev,
recorder_queue_redraw (recorder);
}
}
else if (xev->xany.type == MotionNotify)
else if (input_event != NULL &&
input_event->evtype == XI_Motion)
{
recorder->pointer_x = xev->xmotion.x;
recorder->pointer_y = xev->xmotion.y;
XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
if (device_event->deviceid == VIRTUAL_CORE_POINTER_ID)
{
recorder->pointer_x = device_event->event_x;
recorder->pointer_y = device_event->event_y;
recorder_queue_redraw (recorder);
recorder_queue_redraw (recorder);
}
}
/* We want to track whether the pointer is over the stage
* window itself, and not in a child window. A "virtual"
* crossing is one that goes directly from ancestor to child.
*/
else if (xev->xany.type == EnterNotify &&
(xev->xcrossing.detail != NotifyVirtual &&
xev->xcrossing.detail != NotifyNonlinearVirtual))
else if (input_event != NULL &&
input_event->evtype == XI_Enter)
{
recorder->have_pointer = TRUE;
recorder->pointer_x = xev->xcrossing.x;
recorder->pointer_y = xev->xcrossing.y;
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
recorder_queue_redraw (recorder);
if (enter_event->deviceid == VIRTUAL_CORE_POINTER_ID &&
(enter_event->detail != XINotifyVirtual &&
enter_event->detail != XINotifyNonlinearVirtual))
{
recorder->have_pointer = TRUE;
recorder->pointer_x = enter_event->event_x;
recorder->pointer_y = enter_event->event_y;
recorder_queue_redraw (recorder);
}
}
else if (xev->xany.type == LeaveNotify &&
(xev->xcrossing.detail != NotifyVirtual &&
xev->xcrossing.detail != NotifyNonlinearVirtual))
else if (input_event != NULL &&
input_event->evtype == XI_Leave)
{
recorder->have_pointer = FALSE;
recorder->pointer_x = xev->xcrossing.x;
recorder->pointer_y = xev->xcrossing.y;
XILeaveEvent *leave_event = (XILeaveEvent *) input_event;
recorder_queue_redraw (recorder);
if (leave_event->deviceid == VIRTUAL_CORE_POINTER_ID &&
(leave_event->detail != XINotifyVirtual &&
leave_event->detail != XINotifyNonlinearVirtual))
{
recorder->have_pointer = FALSE;
recorder->pointer_x = leave_event->event_x;
recorder->pointer_y = leave_event->event_y;
recorder_queue_redraw (recorder);
}
}
return CLUTTER_X11_FILTER_CONTINUE;
@ -862,7 +891,8 @@ recorder_set_stage (ShellRecorder *recorder,
if (recorder->stage)
{
int error_base;
int error_base, event_base;
int major = 2, minor = 3;
recorder->stage = stage;
g_signal_connect (recorder->stage, "destroy",
@ -886,6 +916,28 @@ recorder_set_stage (ShellRecorder *recorder,
clutter_x11_get_stage_window (stage),
XFixesDisplayCursorNotifyMask);
if (XQueryExtension (clutter_x11_get_default_display (),
"XInputExtension",
&recorder->xinput_opcode,
&error_base,
&event_base))
{
if (XIQueryVersion (clutter_x11_get_default_display (), &major, &minor) == Success)
{
int version = (major * 10) + minor;
if (version < 22)
g_warning("ShellRecorder: xinput version %d.%d is too old", major, minor);
}
else
{
g_warning("ShellRecorder: xinput version could not be queried");
}
}
else
{
g_warning("ShellRecorder: xinput extension unavailable");
}
clutter_stage_ensure_current (stage);
recorder_get_initial_cursor_position (recorder);