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:
parent
83adb2a864
commit
91c4408d23
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user