mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
Move all picking-related operations inside InputDevice
The InputDevice objects stores pointer coordinates, state, stage and the actor under the cursor, so if the current backend provides us with one attached to the Event structure then we want the InputDevice itself to update its state and give us the ClutterActor underneath the pointer's cursor.
This commit is contained in:
parent
1f87cac069
commit
9506510d1c
@ -144,3 +144,27 @@ _clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
|
||||
|
||||
device_manager->devices = g_slist_remove (device_manager->devices, device);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_device_manager_update_devices (ClutterDeviceManager *device_manager)
|
||||
{
|
||||
GSList *d;
|
||||
|
||||
/* perform a pick() on the stage at the coordinates of every
|
||||
* input device, and store the actor currently under the pointer
|
||||
*/
|
||||
for (d = device_manager->devices; d != NULL; d = d->next)
|
||||
{
|
||||
ClutterInputDevice *device = d->data;
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
if (device_type != CLUTTER_POINTER_DEVICE)
|
||||
continue;
|
||||
|
||||
if (device->stage == NULL)
|
||||
continue;
|
||||
|
||||
_clutter_input_device_update (device);
|
||||
}
|
||||
}
|
||||
|
@ -787,39 +787,3 @@ clutter_get_current_event (void)
|
||||
|
||||
return context->current_event;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_get_device_type:
|
||||
* @device: a #ClutterInputDevice
|
||||
*
|
||||
* Retrieves the type of @device
|
||||
*
|
||||
* Return value: the type of the device
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterInputDeviceType
|
||||
clutter_input_device_get_device_type (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (device != NULL, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
return device->device_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_get_device_id:
|
||||
* @device: a #ClutterInputDevice
|
||||
*
|
||||
* Retrieves the unique identifier of @device
|
||||
*
|
||||
* Return value: the identifier of the device
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
gint
|
||||
clutter_input_device_get_device_id (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (device != NULL, -1);
|
||||
|
||||
return device->id;
|
||||
}
|
||||
|
@ -110,13 +110,13 @@ clutter_input_device_init (ClutterInputDevice *self)
|
||||
|
||||
void
|
||||
_clutter_input_device_set_coords (ClutterInputDevice *device,
|
||||
gfloat x,
|
||||
gfloat y)
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
device->previous_x = floorf (x) + 0.5;
|
||||
device->previous_y = floorf (y) + 0.5;
|
||||
device->previous_x = x;
|
||||
device->previous_y = y;
|
||||
}
|
||||
|
||||
void
|
||||
@ -137,6 +137,45 @@ _clutter_input_device_set_time (ClutterInputDevice *device,
|
||||
device->previous_time = time_;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
device->stage = stage;
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_weak_unref (gpointer user_data,
|
||||
GObject *object_pointer)
|
||||
{
|
||||
ClutterInputDevice *device = user_data;
|
||||
|
||||
device->cursor_actor = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
if (device->cursor_actor != NULL)
|
||||
{
|
||||
_clutter_actor_set_has_pointer (device->cursor_actor, FALSE);
|
||||
g_object_weak_unref (G_OBJECT (device->cursor_actor),
|
||||
cursor_weak_unref,
|
||||
device);
|
||||
}
|
||||
|
||||
device->cursor_actor = actor;
|
||||
g_object_weak_ref (G_OBJECT (device->cursor_actor),
|
||||
cursor_weak_unref,
|
||||
device);
|
||||
_clutter_actor_set_has_pointer (device->cursor_actor, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_get_device_type:
|
||||
* @device: a #ClutterInputDevice
|
||||
@ -173,3 +212,47 @@ clutter_input_device_get_device_id (ClutterInputDevice *device)
|
||||
|
||||
return device->id;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_input_device_get_device_coords (ClutterInputDevice *device,
|
||||
gint *x,
|
||||
gint *y)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
if (x)
|
||||
*x = device->previous_x;
|
||||
|
||||
if (y)
|
||||
*y = device->previous_y;
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
_clutter_input_device_update (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterStage *stage;
|
||||
ClutterActor *new_cursor_actor;
|
||||
ClutterActor *old_cursor_actor;
|
||||
gint x, y;
|
||||
|
||||
clutter_input_device_get_device_coords (device, &x, &y);
|
||||
|
||||
stage = device->stage;
|
||||
old_cursor_actor = device->cursor_actor;
|
||||
new_cursor_actor = _clutter_do_pick (stage, x, y, CLUTTER_PICK_REACTIVE);
|
||||
|
||||
if (new_cursor_actor == NULL)
|
||||
new_cursor_actor = CLUTTER_ACTOR (stage);
|
||||
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"Actor under cursor (device %d, at %d, %d): %s",
|
||||
clutter_input_device_get_device_id (device),
|
||||
x, y,
|
||||
clutter_actor_get_name (new_cursor_actor) != NULL
|
||||
? clutter_actor_get_name (new_cursor_actor)
|
||||
: G_OBJECT_TYPE_NAME (new_cursor_actor));
|
||||
|
||||
_clutter_input_device_set_actor (device, new_cursor_actor);
|
||||
|
||||
return device->cursor_actor;
|
||||
}
|
||||
|
@ -56,8 +56,11 @@ struct _ClutterInputDeviceClass
|
||||
|
||||
GType clutter_input_device_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterInputDeviceType clutter_input_device_get_device_type (ClutterInputDevice *device);
|
||||
gint clutter_input_device_get_device_id (ClutterInputDevice *device);
|
||||
ClutterInputDeviceType clutter_input_device_get_device_type (ClutterInputDevice *device);
|
||||
gint clutter_input_device_get_device_id (ClutterInputDevice *device);
|
||||
void clutter_input_device_get_device_coords (ClutterInputDevice *device,
|
||||
gint *x,
|
||||
gint *y);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -2118,7 +2118,7 @@ emit_event (ClutterEvent *event,
|
||||
ClutterActor *actor;
|
||||
gint i = 0;
|
||||
|
||||
if (!event->any.source)
|
||||
if (event->any.source == NULL)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "No source set, discarding event");
|
||||
return;
|
||||
@ -2445,6 +2445,24 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
if (device == NULL)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
device = event->button.device;
|
||||
break;
|
||||
case CLUTTER_SCROLL:
|
||||
device = event->scroll.device;
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
/* already handled in the MOTION case of the switch */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only do a pick to find the source if source is not already set
|
||||
* (as it could be in a synthetic event)
|
||||
*/
|
||||
@ -2467,13 +2485,24 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Map the event to a reactive actor */
|
||||
actor = _clutter_do_pick (CLUTTER_STAGE (stage),
|
||||
x, y,
|
||||
CLUTTER_PICK_REACTIVE);
|
||||
/* if the backend provides a device then we should
|
||||
* already have everything we need to update it and
|
||||
* get the actor underneath
|
||||
*/
|
||||
if (device == NULL)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "No device found: picking");
|
||||
|
||||
/* Map the event to a reactive actor */
|
||||
actor = _clutter_do_pick (CLUTTER_STAGE (stage),
|
||||
x, y,
|
||||
CLUTTER_PICK_REACTIVE);
|
||||
}
|
||||
else
|
||||
actor = _clutter_input_device_update (device);
|
||||
|
||||
event->any.source = actor;
|
||||
if (!actor)
|
||||
if (actor == NULL)
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -2482,7 +2511,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
actor = event->any.source;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: for an optimisation should check if there are
|
||||
* actually any reactive actors and avoid the pick all together
|
||||
* (signalling just the stage). Should be big help for gles.
|
||||
@ -2502,24 +2530,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
event_click_count_generate (event);
|
||||
}
|
||||
|
||||
if (device == NULL)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
device = event->button.device;
|
||||
break;
|
||||
case CLUTTER_SCROLL:
|
||||
device = event->scroll.device;
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
/* already handled in the MOTION case of the switch */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emit_pointer_event (event, device);
|
||||
break;
|
||||
}
|
||||
|
@ -288,14 +288,13 @@ clutter_clock_dispatch (GSource *source,
|
||||
* event handling
|
||||
*/
|
||||
stages = clutter_stage_manager_list_stages (stage_manager);
|
||||
g_slist_foreach (stages, (GFunc)g_object_ref, NULL);
|
||||
g_slist_foreach (stages, (GFunc) g_object_ref, NULL);
|
||||
|
||||
CLUTTER_TIMER_START (_clutter_uprof_context, master_event_process);
|
||||
|
||||
master_clock->updated_stages = FALSE;
|
||||
|
||||
/* Process queued events
|
||||
*/
|
||||
/* Process queued events */
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
_clutter_stage_process_queued_events (l->data);
|
||||
|
||||
@ -311,7 +310,7 @@ clutter_clock_dispatch (GSource *source,
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
master_clock->updated_stages |= _clutter_stage_do_update (l->data);
|
||||
|
||||
g_slist_foreach (stages, (GFunc)g_object_unref, NULL);
|
||||
g_slist_foreach (stages, (GFunc) g_object_unref, NULL);
|
||||
g_slist_free (stages);
|
||||
|
||||
master_clock->prev_tick = master_clock->cur_tick;
|
||||
|
@ -91,13 +91,16 @@ struct _ClutterInputDevice
|
||||
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
ClutterActor *cursor_actor;
|
||||
|
||||
ClutterActor *pointer_grab_actor;
|
||||
ClutterActor *motion_last_actor;
|
||||
|
||||
gint click_count;
|
||||
|
||||
gfloat previous_x;
|
||||
gfloat previous_y;
|
||||
ClutterStage *stage;
|
||||
gint previous_x;
|
||||
gint previous_y;
|
||||
guint32 previous_time;
|
||||
gint previous_button_number;
|
||||
ClutterModifierType previous_state;
|
||||
@ -189,19 +192,25 @@ PangoContext *_clutter_context_get_pango_context (ClutterMainContext *self);
|
||||
#define I_(str) (g_intern_static_string ((str)))
|
||||
|
||||
/* device manager */
|
||||
void _clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device);
|
||||
void _clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device);
|
||||
void _clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device);
|
||||
void _clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device);
|
||||
void _clutter_device_manager_update_devices (ClutterDeviceManager *device_manager);
|
||||
|
||||
/* input device */
|
||||
void _clutter_input_device_set_coords (ClutterInputDevice *device,
|
||||
gfloat x,
|
||||
gfloat y);
|
||||
void _clutter_input_device_set_state (ClutterInputDevice *device,
|
||||
ClutterModifierType state);
|
||||
void _clutter_input_device_set_time (ClutterInputDevice *device,
|
||||
guint32 time_);
|
||||
void _clutter_input_device_set_coords (ClutterInputDevice *device,
|
||||
gint x,
|
||||
gint y);
|
||||
void _clutter_input_device_set_state (ClutterInputDevice *device,
|
||||
ClutterModifierType state);
|
||||
void _clutter_input_device_set_time (ClutterInputDevice *device,
|
||||
guint32 time_);
|
||||
void _clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||
ClutterStage *stage);
|
||||
void _clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||
ClutterActor *actor);
|
||||
ClutterActor *_clutter_input_device_update (ClutterInputDevice *device);
|
||||
|
||||
/* stage manager */
|
||||
void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
||||
@ -223,6 +232,7 @@ void _clutter_stage_queue_event (ClutterStage *stage,
|
||||
ClutterEvent *event);
|
||||
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
|
||||
void _clutter_stage_process_queued_events (ClutterStage *stage);
|
||||
void _clutter_stage_update_input_devices (ClutterStage *stage);
|
||||
|
||||
/* vfuncs implemented by backend */
|
||||
GType _clutter_backend_impl_get_type (void);
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "clutter-id-pool.h"
|
||||
#include "clutter-container.h"
|
||||
#include "clutter-profile.h"
|
||||
#include "clutter-input-device.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
@ -454,6 +455,7 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
gboolean first_event;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
@ -461,14 +463,32 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
||||
|
||||
first_event = priv->event_queue->length == 0;
|
||||
|
||||
g_queue_push_tail (priv->event_queue,
|
||||
clutter_event_copy (event));
|
||||
g_queue_push_tail (priv->event_queue, clutter_event_copy (event));
|
||||
|
||||
if (first_event)
|
||||
{
|
||||
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
|
||||
_clutter_master_clock_start_running (master_clock);
|
||||
}
|
||||
|
||||
/* if needed, update the state of the input device of the event.
|
||||
* we do it here to avoid calling the same code from every backend
|
||||
* event processing function
|
||||
*/
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
{
|
||||
ClutterModifierType event_state = clutter_event_get_state (event);
|
||||
guint32 event_time = clutter_event_get_time (event);
|
||||
gfloat event_x, event_y;
|
||||
|
||||
clutter_event_get_coords (event, &event_x, &event_y);
|
||||
|
||||
_clutter_input_device_set_coords (device, event_x, event_y);
|
||||
_clutter_input_device_set_state (device, event_state);
|
||||
_clutter_input_device_set_time (device, event_time);
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -487,7 +507,7 @@ void
|
||||
_clutter_stage_process_queued_events (ClutterStage *stage)
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
GList *events, *l;;
|
||||
GList *events, *l;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
@ -506,7 +526,7 @@ _clutter_stage_process_queued_events (ClutterStage *stage)
|
||||
priv->event_queue->tail = NULL;
|
||||
priv->event_queue->length = 0;
|
||||
|
||||
for (l = events; l; l = l->next)
|
||||
for (l = events; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterEvent *event;
|
||||
ClutterEvent *next_event;
|
||||
|
@ -624,9 +624,10 @@ event_translate (ClutterBackend *backend,
|
||||
|
||||
case KeyPress:
|
||||
event->key.type = event->type = CLUTTER_KEY_PRESS;
|
||||
translate_key_event (backend, event, xevent);
|
||||
|
||||
/* default key device if no XInput support is defined */
|
||||
event->key.device = clutter_device_manager_get_device (manager, 1);
|
||||
translate_key_event (backend, event, xevent);
|
||||
|
||||
set_user_time (backend_x11, &xwindow, xevent->xkey.time);
|
||||
break;
|
||||
@ -659,9 +660,10 @@ event_translate (ClutterBackend *backend,
|
||||
}
|
||||
|
||||
event->key.type = event->type = CLUTTER_KEY_RELEASE;
|
||||
translate_key_event (backend, event, xevent);
|
||||
|
||||
/* default key device if no XInput support is defined */
|
||||
event->key.device = clutter_device_manager_get_device (manager, 1);
|
||||
translate_key_event (backend, event, xevent);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -763,6 +765,10 @@ event_translate (ClutterBackend *backend,
|
||||
event->motion.modifier_state = xevent->xcrossing.state;
|
||||
event->motion.device =
|
||||
clutter_device_manager_get_device (manager, 0);
|
||||
|
||||
/* we know that we are entering the stage here */
|
||||
_clutter_input_device_set_stage (event->motion.device, stage);
|
||||
CLUTTER_NOTE (EVENT, "Entering the stage");
|
||||
break;
|
||||
|
||||
case LeaveNotify:
|
||||
@ -770,8 +776,12 @@ event_translate (ClutterBackend *backend,
|
||||
event->crossing.time = xevent->xcrossing.time;
|
||||
event->crossing.x = xevent->xcrossing.x;
|
||||
event->crossing.y = xevent->xcrossing.y;
|
||||
event->motion.device =
|
||||
event->crossing.device =
|
||||
clutter_device_manager_get_device (manager, 0);
|
||||
|
||||
/* we know that we are leaving the stage here */
|
||||
_clutter_input_device_set_stage (event->crossing.device, NULL);
|
||||
CLUTTER_NOTE (EVENT, "Leaving the stage");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -784,10 +794,16 @@ event_translate (ClutterBackend *backend,
|
||||
{ /* XInput fun.. Needs clean up. */
|
||||
#ifdef HAVE_XINPUT
|
||||
int *ev_types = backend_x11->event_types;
|
||||
int button_press, button_release;
|
||||
int motion_notify;
|
||||
|
||||
button_press = ev_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
|
||||
button_release = ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
|
||||
motion_notify = ev_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT];
|
||||
|
||||
CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type);
|
||||
|
||||
if (xevent->type == ev_types [CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT])
|
||||
if (xevent->type == button_press)
|
||||
{
|
||||
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent;
|
||||
|
||||
@ -833,8 +849,7 @@ event_translate (ClutterBackend *backend,
|
||||
|
||||
set_user_time (backend_x11, &xwindow, xbev->time);
|
||||
}
|
||||
else if (xevent->type
|
||||
== ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT])
|
||||
else if (xevent->type == button_release)
|
||||
{
|
||||
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
|
||||
|
||||
@ -860,8 +875,7 @@ event_translate (ClutterBackend *backend,
|
||||
event->button.button = xbev->button;
|
||||
event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||
}
|
||||
else if (xevent->type
|
||||
== ev_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT])
|
||||
else if (xevent->type == motion_notify)
|
||||
{
|
||||
XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
|
||||
|
||||
@ -883,8 +897,7 @@ event_translate (ClutterBackend *backend,
|
||||
* not generate events even when the window has focus
|
||||
*/
|
||||
|
||||
else if (xevent->type
|
||||
== ev_types [CLUTTER_X11_XINPUT_KEY_PRESS_EVENT])
|
||||
else if (xevent->type == ev_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT])
|
||||
{
|
||||
XEvent xevent_converted;
|
||||
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *)xevent;
|
||||
@ -896,8 +909,7 @@ event_translate (ClutterBackend *backend,
|
||||
|
||||
set_user_time (backend_x11, &xwindow, xkev->time);
|
||||
}
|
||||
else if (xevent->type
|
||||
== ev_types [CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT])
|
||||
else if (xevent->type == ev_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT])
|
||||
{
|
||||
XEvent xevent_converted;
|
||||
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *)xevent;
|
||||
|
Loading…
Reference in New Issue
Block a user