mirror of
https://github.com/brl/mutter.git
synced 2025-02-18 06:04:10 +00:00
compositor: Move event spoofing code to MetaBackendX11
This is now where we handle device events.
This commit is contained in:
parent
61b714c666
commit
e9eb3c32a9
@ -46,6 +46,10 @@ struct _MetaBackendX11Private
|
|||||||
|
|
||||||
int xsync_event_base;
|
int xsync_event_base;
|
||||||
int xsync_error_base;
|
int xsync_error_base;
|
||||||
|
|
||||||
|
int xinput_opcode;
|
||||||
|
int xinput_event_base;
|
||||||
|
int xinput_error_base;
|
||||||
};
|
};
|
||||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
||||||
|
|
||||||
@ -62,6 +66,47 @@ handle_alarm_notify (MetaBackend *backend,
|
|||||||
meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
|
meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clutter makes the assumption that there is only one X window
|
||||||
|
* per stage, which is a valid assumption to make for a generic
|
||||||
|
* application toolkit. As such, it will ignore any events sent
|
||||||
|
* to the a stage that isn't its X window.
|
||||||
|
*
|
||||||
|
* When running as an X window manager, we need to respond to
|
||||||
|
* events from lots of windows. Trick Clutter into translating
|
||||||
|
* these events by pretending we got an event on the stage window.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
||||||
|
XEvent *event)
|
||||||
|
{
|
||||||
|
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||||
|
|
||||||
|
if (event->type == GenericEvent &&
|
||||||
|
event->xcookie.extension == priv->xinput_opcode)
|
||||||
|
{
|
||||||
|
XGetEventData (priv->xdisplay, &event->xcookie);
|
||||||
|
|
||||||
|
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
||||||
|
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||||
|
|
||||||
|
switch (input_event->evtype)
|
||||||
|
{
|
||||||
|
case XI_Motion:
|
||||||
|
case XI_ButtonPress:
|
||||||
|
case XI_ButtonRelease:
|
||||||
|
case XI_KeyPress:
|
||||||
|
case XI_KeyRelease:
|
||||||
|
{
|
||||||
|
ClutterStage *stage = CLUTTER_STAGE (clutter_stage_get_default ());
|
||||||
|
device_event->event = clutter_x11_get_stage_window (stage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_host_xevent (MetaBackend *backend,
|
handle_host_xevent (MetaBackend *backend,
|
||||||
XEvent *xevent)
|
XEvent *xevent)
|
||||||
@ -83,6 +128,8 @@ handle_host_xevent (MetaBackend *backend,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybe_spoof_event_as_stage_event (x11, xevent);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!bypass_clutter)
|
if (!bypass_clutter)
|
||||||
clutter_x11_handle_event (xevent);
|
clutter_x11_handle_event (xevent);
|
||||||
@ -181,6 +228,28 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
|||||||
!XSyncInitialize (priv->xdisplay, &major, &minor))
|
!XSyncInitialize (priv->xdisplay, &major, &minor))
|
||||||
meta_fatal ("Could not initialize XSync");
|
meta_fatal ("Could not initialize XSync");
|
||||||
|
|
||||||
|
{
|
||||||
|
int major = 2, minor = 3;
|
||||||
|
gboolean has_xi = FALSE;
|
||||||
|
|
||||||
|
if (XQueryExtension (priv->xdisplay,
|
||||||
|
"XInputExtension",
|
||||||
|
&priv->xinput_opcode,
|
||||||
|
&priv->xinput_error_base,
|
||||||
|
&priv->xinput_event_base))
|
||||||
|
{
|
||||||
|
if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success)
|
||||||
|
{
|
||||||
|
int version = (major * 10) + minor;
|
||||||
|
if (version >= 22)
|
||||||
|
has_xi = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_xi)
|
||||||
|
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
|
||||||
|
}
|
||||||
|
|
||||||
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,82 +752,6 @@ meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
|||||||
meta_window_actor_update_surface (window_actor);
|
meta_window_actor_update_surface (window_actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
event_is_passive_button_grab (MetaDisplay *display,
|
|
||||||
XIDeviceEvent *device_event)
|
|
||||||
{
|
|
||||||
/* see display.c for which events are passive button
|
|
||||||
grabs (meta_display_grab_window_buttons() and
|
|
||||||
meta_display_handle_events())
|
|
||||||
we need to filter them here because normally they
|
|
||||||
would be sent to gtk+ (they are on gtk+ frame xwindow),
|
|
||||||
but we want to redirect them to clutter
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (device_event->evtype != XI_ButtonPress)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (display->window_grab_modifiers == 0)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if ((device_event->mods.effective & display->window_grab_modifiers) !=
|
|
||||||
display->window_grab_modifiers)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return device_event->detail < 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clutter makes the assumption that there is only one X window
|
|
||||||
* per stage, which is a valid assumption to make for a generic
|
|
||||||
* application toolkit. As such, it will ignore any events sent
|
|
||||||
* to the a stage that isn't its X window.
|
|
||||||
*
|
|
||||||
* When running as an X window manager, we need to respond to
|
|
||||||
* events from lots of windows. Trick Clutter into translating
|
|
||||||
* these events by pretending we got an event on the stage window.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
maybe_spoof_event_as_stage_event (MetaCompositor *compositor,
|
|
||||||
MetaWindow *window,
|
|
||||||
XEvent *event)
|
|
||||||
{
|
|
||||||
MetaDisplay *display = compositor->display;
|
|
||||||
|
|
||||||
if (event->type == GenericEvent &&
|
|
||||||
event->xcookie.extension == display->xinput_opcode)
|
|
||||||
{
|
|
||||||
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
|
||||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
|
||||||
|
|
||||||
switch (input_event->evtype)
|
|
||||||
{
|
|
||||||
case XI_Motion:
|
|
||||||
case XI_ButtonPress:
|
|
||||||
case XI_ButtonRelease:
|
|
||||||
/* If this is a window frame, and we think GTK+ needs to handle the event,
|
|
||||||
let GTK+ handle it without mangling */
|
|
||||||
if (window && window->frame && device_event->event == window->frame->xwindow &&
|
|
||||||
(meta_grab_op_is_clicking (display->grab_op) ||
|
|
||||||
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XI_KeyPress:
|
|
||||||
case XI_KeyRelease:
|
|
||||||
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
|
|
||||||
* it as-is without mangling. */
|
|
||||||
if (meta_ui_window_is_widget (display->screen->ui, device_event->event))
|
|
||||||
break;
|
|
||||||
|
|
||||||
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
|
||||||
device_event->event_x = device_event->root_x;
|
|
||||||
device_event->event_y = device_event->root_y;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_compositor_process_event: (skip)
|
* meta_compositor_process_event: (skip)
|
||||||
* @compositor:
|
* @compositor:
|
||||||
@ -840,11 +764,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
|||||||
XEvent *event,
|
XEvent *event,
|
||||||
MetaWindow *window)
|
MetaWindow *window)
|
||||||
{
|
{
|
||||||
MetaDisplay *display = compositor->display;
|
|
||||||
|
|
||||||
if (!meta_is_wayland_compositor ())
|
|
||||||
maybe_spoof_event_as_stage_event (compositor, window, event);
|
|
||||||
|
|
||||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user