shell-recorder: Don't use XI2 in the recorder to query the pointer

Just use the normal MetaCursorTracker, which works under Wayland.
This commit is contained in:
Jasper St. Pierre 2014-07-26 10:27:12 -04:00
parent 83adb2a864
commit 91c4408d23

View File

@ -21,13 +21,6 @@
#include "shell-recorder-src.h"
#include "shell-recorder.h"
#include <clutter/x11/clutter-x11.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
#define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
@ -63,7 +56,6 @@ struct _ShellRecorder {
GdkScreen *gdk_screen;
gboolean have_pointer;
int pointer_x;
int pointer_y;
@ -559,156 +551,18 @@ on_cursor_changed (MetaCursorTracker *tracker,
recorder_queue_redraw (recorder);
}
/* We use an event filter on the stage to get the XFixesCursorNotifyEvent
* and also to track cursor position (when the cursor is over the stage's
* input area); tracking cursor position here rather than with ClutterEvent
* allows us to avoid worrying about event propagation and competing
* signal handlers.
*/
static ClutterX11FilterReturn
recorder_event_filter (XEvent *xev,
ClutterEvent *cev,
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 (input_event != NULL &&
input_event->evtype == XI_Motion)
{
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);
}
}
/* 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 (input_event != NULL &&
input_event->evtype == XI_Enter)
{
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
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 (input_event != NULL &&
input_event->evtype == XI_Leave)
{
XILeaveEvent *leave_event = (XILeaveEvent *) input_event;
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;
}
/* We optimize out querying the server for the pointer position if the
* pointer is in the input area of the ClutterStage. We track changes to
* that with Enter/Leave events, but we need to 100% accurate about the
* initial condition, which is a little involved.
*/
static void
recorder_get_initial_cursor_position (ShellRecorder *recorder)
{
Display *xdisplay = clutter_x11_get_default_display ();
Window xwindow = clutter_x11_get_stage_window (recorder->stage);
XWindowAttributes xwa;
Window root, child, parent;
Window *children;
guint n_children;
int root_x,root_y;
int window_x, window_y;
guint mask;
XGrabServer(xdisplay);
XGetWindowAttributes (xdisplay, xwindow, &xwa);
XQueryTree (xdisplay, xwindow, &root, &parent, &children, &n_children);
XFree (children);
if (xwa.map_state == IsViewable &&
XQueryPointer (xdisplay, parent,
&root, &child, &root_x, &root_y, &window_x, &window_y, &mask) &&
child == xwindow)
{
/* The point of this call is not actually to translate the coordinates -
* we could do that ourselves using xwa.{x,y} - but rather to see if
* the pointer is in a child of the window, which we count as "not in
* window", because we aren't guaranteed to get pointer events.
*/
XTranslateCoordinates(xdisplay, parent, xwindow,
window_x, window_y,
&window_x, &window_y, &child);
if (child == None)
{
recorder->have_pointer = TRUE;
recorder->pointer_x = window_x;
recorder->pointer_y = window_y;
}
}
else
recorder->have_pointer = FALSE;
XUngrabServer(xdisplay);
XFlush(xdisplay);
}
/* When the cursor is not over the stage's input area, we query for the
* pointer position in a timeout.
*/
static void
recorder_update_pointer (ShellRecorder *recorder)
{
Display *xdisplay = clutter_x11_get_default_display ();
Window xwindow = clutter_x11_get_stage_window (recorder->stage);
Window root, child;
int root_x,root_y;
int window_x, window_y;
guint mask;
int pointer_x, pointer_y;
if (recorder->have_pointer)
return;
meta_cursor_tracker_get_pointer (recorder->cursor_tracker, &pointer_x, &pointer_y, NULL);
if (XQueryPointer (xdisplay, xwindow,
&root, &child, &root_x, &root_y, &window_x, &window_y, &mask))
if (pointer_x != recorder->pointer_x || pointer_y != recorder->pointer_y)
{
if (window_x != recorder->pointer_x || window_y != recorder->pointer_y)
{
recorder->pointer_x = window_x;
recorder->pointer_y = window_y;
recorder_queue_redraw (recorder);
}
recorder->pointer_x = pointer_x;
recorder->pointer_y = pointer_y;
recorder_queue_redraw (recorder);
}
}
@ -753,8 +607,6 @@ recorder_connect_stage_callbacks (ShellRecorder *recorder)
G_CALLBACK (recorder_on_stage_notify_size), recorder);
g_signal_connect (recorder->stage, "notify::height",
G_CALLBACK (recorder_on_stage_notify_size), recorder);
clutter_x11_add_filter (recorder_event_filter, recorder);
}
static void
@ -770,8 +622,6 @@ recorder_disconnect_stage_callbacks (ShellRecorder *recorder)
(void *)recorder_on_stage_notify_size,
recorder);
clutter_x11_remove_filter (recorder_event_filter, recorder);
/* We don't don't deselect for cursor changes in case someone else just
* happened to be selecting for cursor events on the same window; sending
* us the events is close to free in any case.
@ -800,40 +650,7 @@ recorder_set_stage (ShellRecorder *recorder,
recorder->stage = stage;
if (recorder->stage)
{
int error_base, event_base;
int major = 2, minor = 3;
recorder->stage = stage;
recorder_update_size (recorder);
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);
}
recorder_update_size (recorder);
}
static void
@ -1715,6 +1532,7 @@ shell_recorder_record (ShellRecorder *recorder,
recorder->last_frame_time = 0;
recorder->state = RECORDER_STATE_RECORDING;
recorder_update_pointer (recorder);
recorder_add_update_pointer_timeout (recorder);
/* Set up repaint hook */