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
5ccbd3a821
commit
c96f95ab90
@ -21,13 +21,6 @@
|
|||||||
#include "shell-recorder-src.h"
|
#include "shell-recorder-src.h"
|
||||||
#include "shell-recorder.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 A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
|
||||||
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
|
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
|
||||||
|
|
||||||
@ -63,7 +56,6 @@ struct _ShellRecorder {
|
|||||||
|
|
||||||
GdkScreen *gdk_screen;
|
GdkScreen *gdk_screen;
|
||||||
|
|
||||||
gboolean have_pointer;
|
|
||||||
int pointer_x;
|
int pointer_x;
|
||||||
int pointer_y;
|
int pointer_y;
|
||||||
|
|
||||||
@ -555,156 +547,18 @@ on_cursor_changed (MetaCursorTracker *tracker,
|
|||||||
recorder_queue_redraw (recorder);
|
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
|
static void
|
||||||
recorder_update_pointer (ShellRecorder *recorder)
|
recorder_update_pointer (ShellRecorder *recorder)
|
||||||
{
|
{
|
||||||
Display *xdisplay = clutter_x11_get_default_display ();
|
int pointer_x, pointer_y;
|
||||||
Window xwindow = clutter_x11_get_stage_window (recorder->stage);
|
|
||||||
Window root, child;
|
|
||||||
int root_x,root_y;
|
|
||||||
int window_x, window_y;
|
|
||||||
guint mask;
|
|
||||||
|
|
||||||
if (recorder->have_pointer)
|
meta_cursor_tracker_get_pointer (recorder->cursor_tracker, &pointer_x, &pointer_y, NULL);
|
||||||
return;
|
|
||||||
|
|
||||||
if (XQueryPointer (xdisplay, xwindow,
|
if (pointer_x != recorder->pointer_x || pointer_y != recorder->pointer_y)
|
||||||
&root, &child, &root_x, &root_y, &window_x, &window_y, &mask))
|
|
||||||
{
|
{
|
||||||
if (window_x != recorder->pointer_x || window_y != recorder->pointer_y)
|
recorder->pointer_x = pointer_x;
|
||||||
{
|
recorder->pointer_y = pointer_y;
|
||||||
recorder->pointer_x = window_x;
|
recorder_queue_redraw (recorder);
|
||||||
recorder->pointer_y = window_y;
|
|
||||||
|
|
||||||
recorder_queue_redraw (recorder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,8 +600,6 @@ recorder_connect_stage_callbacks (ShellRecorder *recorder)
|
|||||||
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||||
g_signal_connect (recorder->stage, "notify::width",
|
g_signal_connect (recorder->stage, "notify::width",
|
||||||
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||||
|
|
||||||
clutter_x11_add_filter (recorder_event_filter, recorder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -763,8 +615,6 @@ recorder_disconnect_stage_callbacks (ShellRecorder *recorder)
|
|||||||
(void *)recorder_on_stage_notify_size,
|
(void *)recorder_on_stage_notify_size,
|
||||||
recorder);
|
recorder);
|
||||||
|
|
||||||
clutter_x11_remove_filter (recorder_event_filter, recorder);
|
|
||||||
|
|
||||||
/* We don't don't deselect for cursor changes in case someone else just
|
/* 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
|
* happened to be selecting for cursor events on the same window; sending
|
||||||
* us the events is close to free in any case.
|
* us the events is close to free in any case.
|
||||||
@ -793,40 +643,7 @@ recorder_set_stage (ShellRecorder *recorder,
|
|||||||
recorder->stage = stage;
|
recorder->stage = stage;
|
||||||
|
|
||||||
if (recorder->stage)
|
if (recorder->stage)
|
||||||
{
|
recorder_update_size (recorder);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1707,6 +1524,7 @@ shell_recorder_record (ShellRecorder *recorder,
|
|||||||
recorder->last_frame_time = 0;
|
recorder->last_frame_time = 0;
|
||||||
|
|
||||||
recorder->state = RECORDER_STATE_RECORDING;
|
recorder->state = RECORDER_STATE_RECORDING;
|
||||||
|
recorder_update_pointer (recorder);
|
||||||
recorder_add_update_pointer_timeout (recorder);
|
recorder_add_update_pointer_timeout (recorder);
|
||||||
|
|
||||||
/* Set up repaint hook */
|
/* Set up repaint hook */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user