1247452d19
We only need to wake up the other side of the GAsyncQueue if we transition from 0 to 1 item in the queue. Otherwise, we can be certain that the other side has received a wakeup and will eventually flush the queue. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4007>
2732 lines
77 KiB
C
2732 lines
77 KiB
C
/*
|
|
* Clutter.
|
|
*
|
|
* An OpenGL based 'interactive canvas' library.
|
|
*
|
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
|
*
|
|
* Copyright (C) 2006 OpenedHand
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "clutter/clutter-backend-private.h"
|
|
#include "clutter/clutter-context-private.h"
|
|
#include "clutter/clutter-debug.h"
|
|
#include "clutter/clutter-event-private.h"
|
|
#include "clutter/clutter-keysyms.h"
|
|
#include "clutter/clutter-input-device-tool.h"
|
|
#include "clutter/clutter-private.h"
|
|
|
|
#include <math.h>
|
|
|
|
struct _ClutterAnyEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
};
|
|
|
|
struct _ClutterKeyEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
ClutterModifierSet raw_modifiers;
|
|
ClutterModifierType modifier_state;
|
|
uint32_t keyval;
|
|
uint16_t hardware_keycode;
|
|
gunichar unicode_value;
|
|
uint32_t evdev_code;
|
|
};
|
|
|
|
struct _ClutterButtonEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
float x;
|
|
float y;
|
|
ClutterModifierType modifier_state;
|
|
uint32_t button;
|
|
double *axes;
|
|
ClutterInputDeviceTool *tool;
|
|
uint32_t evdev_code;
|
|
};
|
|
|
|
struct _ClutterProximityEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
ClutterInputDeviceTool *tool;
|
|
};
|
|
|
|
struct _ClutterCrossingEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
float x;
|
|
float y;
|
|
ClutterEventSequence *sequence;
|
|
ClutterActor *source;
|
|
ClutterActor *related;
|
|
};
|
|
|
|
struct _ClutterMotionEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
float x;
|
|
float y;
|
|
ClutterModifierType modifier_state;
|
|
double *axes;
|
|
ClutterInputDeviceTool *tool;
|
|
|
|
double dx;
|
|
double dy;
|
|
double dx_unaccel;
|
|
double dy_unaccel;
|
|
double dx_constrained;
|
|
double dy_constrained;
|
|
};
|
|
|
|
struct _ClutterScrollEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
float x;
|
|
float y;
|
|
double delta_x;
|
|
double delta_y;
|
|
ClutterScrollDirection direction;
|
|
ClutterModifierType modifier_state;
|
|
double *axes;
|
|
ClutterInputDeviceTool *tool;
|
|
ClutterScrollSource scroll_source;
|
|
ClutterScrollFinishFlags finish_flags;
|
|
};
|
|
|
|
struct _ClutterTouchEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
float x;
|
|
float y;
|
|
ClutterEventSequence *sequence;
|
|
ClutterModifierType modifier_state;
|
|
double *axes; /* reserved */
|
|
};
|
|
|
|
struct _ClutterTouchpadPinchEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
ClutterTouchpadGesturePhase phase;
|
|
float x;
|
|
float y;
|
|
float dx;
|
|
float dy;
|
|
float dx_unaccel;
|
|
float dy_unaccel;
|
|
float angle_delta;
|
|
float scale;
|
|
uint32_t n_fingers;
|
|
};
|
|
|
|
struct _ClutterTouchpadSwipeEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
ClutterTouchpadGesturePhase phase;
|
|
uint32_t n_fingers;
|
|
float x;
|
|
float y;
|
|
float dx;
|
|
float dy;
|
|
float dx_unaccel;
|
|
float dy_unaccel;
|
|
};
|
|
|
|
struct _ClutterTouchpadHoldEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
ClutterTouchpadGesturePhase phase;
|
|
uint32_t n_fingers;
|
|
float x;
|
|
float y;
|
|
};
|
|
|
|
struct _ClutterPadButtonEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
uint32_t button;
|
|
uint32_t group;
|
|
uint32_t mode;
|
|
};
|
|
|
|
struct _ClutterPadStripEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
ClutterInputDevicePadSource strip_source;
|
|
uint32_t strip_number;
|
|
uint32_t group;
|
|
double value;
|
|
uint32_t mode;
|
|
};
|
|
|
|
struct _ClutterPadRingEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
ClutterInputDevicePadSource ring_source;
|
|
uint32_t ring_number;
|
|
uint32_t group;
|
|
double angle;
|
|
uint32_t mode;
|
|
};
|
|
|
|
struct _ClutterDeviceEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
};
|
|
|
|
struct _ClutterIMEvent
|
|
{
|
|
ClutterEventType type;
|
|
int64_t time_us;
|
|
ClutterEventFlags flags;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDevice *source_device;
|
|
|
|
char *text;
|
|
int32_t offset;
|
|
int32_t anchor;
|
|
uint32_t len;
|
|
ClutterPreeditResetMode mode;
|
|
};
|
|
|
|
union _ClutterEvent
|
|
{
|
|
/*< private >*/
|
|
ClutterEventType type;
|
|
|
|
ClutterAnyEvent any;
|
|
ClutterButtonEvent button;
|
|
ClutterKeyEvent key;
|
|
ClutterMotionEvent motion;
|
|
ClutterScrollEvent scroll;
|
|
ClutterCrossingEvent crossing;
|
|
ClutterTouchEvent touch;
|
|
ClutterTouchpadPinchEvent touchpad_pinch;
|
|
ClutterTouchpadSwipeEvent touchpad_swipe;
|
|
ClutterTouchpadHoldEvent touchpad_hold;
|
|
ClutterProximityEvent proximity;
|
|
ClutterPadButtonEvent pad_button;
|
|
ClutterPadStripEvent pad_strip;
|
|
ClutterPadRingEvent pad_ring;
|
|
ClutterDeviceEvent device;
|
|
ClutterIMEvent im;
|
|
};
|
|
|
|
typedef struct _ClutterEventFilter {
|
|
int id;
|
|
|
|
ClutterStage *stage;
|
|
ClutterEventFilterFunc func;
|
|
GDestroyNotify notify;
|
|
gpointer user_data;
|
|
} ClutterEventFilter;
|
|
|
|
G_DEFINE_BOXED_TYPE (ClutterEvent, clutter_event,
|
|
clutter_event_copy,
|
|
clutter_event_free);
|
|
|
|
static ClutterEventSequence *
|
|
clutter_event_sequence_copy (ClutterEventSequence *sequence)
|
|
{
|
|
/* Nothing to copy here */
|
|
return sequence;
|
|
}
|
|
|
|
static void
|
|
clutter_event_sequence_free (ClutterEventSequence *sequence)
|
|
{
|
|
/* Nothing to free here */
|
|
}
|
|
|
|
G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence,
|
|
clutter_event_sequence_copy,
|
|
clutter_event_sequence_free);
|
|
|
|
/**
|
|
* clutter_event_type:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Retrieves the type of the event.
|
|
*
|
|
* Return value: a #ClutterEventType
|
|
*/
|
|
ClutterEventType
|
|
clutter_event_type (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, CLUTTER_NOTHING);
|
|
|
|
return event->type;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_time:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Retrieves the time of the event.
|
|
*
|
|
* Return value: the time of the event, or %CLUTTER_CURRENT_TIME
|
|
*/
|
|
guint32
|
|
clutter_event_get_time (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, CLUTTER_CURRENT_TIME);
|
|
|
|
return us2ms (event->any.time_us);
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_state:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Retrieves the modifier state of the event. In case the window system
|
|
* supports reporting latched and locked modifiers, this function returns
|
|
* the effective state.
|
|
*
|
|
* Return value: the modifier state parameter, or 0
|
|
*/
|
|
ClutterModifierType
|
|
clutter_event_get_state (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_KEY_PRESS:
|
|
case CLUTTER_KEY_RELEASE:
|
|
return event->key.modifier_state;
|
|
|
|
case CLUTTER_BUTTON_PRESS:
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
return event->button.modifier_state;
|
|
|
|
case CLUTTER_TOUCH_BEGIN:
|
|
case CLUTTER_TOUCH_UPDATE:
|
|
case CLUTTER_TOUCH_END:
|
|
case CLUTTER_TOUCH_CANCEL:
|
|
return event->touch.modifier_state;
|
|
|
|
case CLUTTER_MOTION:
|
|
return event->motion.modifier_state;
|
|
|
|
case CLUTTER_SCROLL:
|
|
return event->scroll.modifier_state;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_coords:
|
|
* @event: a #ClutterEvent
|
|
* @x: (out): return location for the X coordinate, or %NULL
|
|
* @y: (out): return location for the Y coordinate, or %NULL
|
|
*
|
|
* Retrieves the coordinates of @event and puts them into @x and @y.
|
|
*/
|
|
void
|
|
clutter_event_get_coords (const ClutterEvent *event,
|
|
gfloat *x,
|
|
gfloat *y)
|
|
{
|
|
graphene_point_t coords;
|
|
|
|
g_return_if_fail (event != NULL);
|
|
|
|
clutter_event_get_position (event, &coords);
|
|
|
|
if (x != NULL)
|
|
*x = coords.x;
|
|
|
|
if (y != NULL)
|
|
*y = coords.y;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_position:
|
|
* @event: a #ClutterEvent
|
|
* @position: a #graphene_point_t
|
|
*
|
|
* Retrieves the event coordinates as a #graphene_point_t.
|
|
*/
|
|
void
|
|
clutter_event_get_position (const ClutterEvent *event,
|
|
graphene_point_t *position)
|
|
{
|
|
g_return_if_fail (event != NULL);
|
|
g_return_if_fail (position != NULL);
|
|
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_NOTHING:
|
|
case CLUTTER_KEY_PRESS:
|
|
case CLUTTER_KEY_RELEASE:
|
|
case CLUTTER_EVENT_LAST:
|
|
case CLUTTER_PROXIMITY_IN:
|
|
case CLUTTER_PROXIMITY_OUT:
|
|
case CLUTTER_PAD_BUTTON_PRESS:
|
|
case CLUTTER_PAD_BUTTON_RELEASE:
|
|
case CLUTTER_PAD_STRIP:
|
|
case CLUTTER_PAD_RING:
|
|
case CLUTTER_DEVICE_ADDED:
|
|
case CLUTTER_DEVICE_REMOVED:
|
|
case CLUTTER_IM_COMMIT:
|
|
case CLUTTER_IM_DELETE:
|
|
case CLUTTER_IM_PREEDIT:
|
|
graphene_point_init (position, 0.f, 0.f);
|
|
break;
|
|
|
|
case CLUTTER_ENTER:
|
|
case CLUTTER_LEAVE:
|
|
graphene_point_init (position, event->crossing.x, event->crossing.y);
|
|
break;
|
|
|
|
case CLUTTER_BUTTON_PRESS:
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
graphene_point_init (position, event->button.x, event->button.y);
|
|
break;
|
|
|
|
case CLUTTER_MOTION:
|
|
graphene_point_init (position, event->motion.x, event->motion.y);
|
|
break;
|
|
|
|
case CLUTTER_TOUCH_BEGIN:
|
|
case CLUTTER_TOUCH_UPDATE:
|
|
case CLUTTER_TOUCH_END:
|
|
case CLUTTER_TOUCH_CANCEL:
|
|
graphene_point_init (position, event->touch.x, event->touch.y);
|
|
break;
|
|
|
|
case CLUTTER_SCROLL:
|
|
graphene_point_init (position, event->scroll.x, event->scroll.y);
|
|
break;
|
|
|
|
case CLUTTER_TOUCHPAD_PINCH:
|
|
graphene_point_init (position, event->touchpad_pinch.x,
|
|
event->touchpad_pinch.y);
|
|
break;
|
|
|
|
case CLUTTER_TOUCHPAD_SWIPE:
|
|
graphene_point_init (position, event->touchpad_swipe.x,
|
|
event->touchpad_swipe.y);
|
|
break;
|
|
|
|
case CLUTTER_TOUCHPAD_HOLD:
|
|
graphene_point_init (position, event->touchpad_hold.x,
|
|
event->touchpad_hold.y);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_source:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Retrieves the source #ClutterActor the event originated from, or
|
|
* NULL if the event has no source.
|
|
*
|
|
* Return value: (transfer none): a #ClutterActor
|
|
*/
|
|
ClutterActor *
|
|
clutter_event_get_source (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, NULL);
|
|
|
|
if (event->type == CLUTTER_ENTER ||
|
|
event->type == CLUTTER_LEAVE)
|
|
return event->crossing.source;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_flags:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Retrieves the #ClutterEventFlags of @event
|
|
*
|
|
* Return value: the event flags
|
|
*/
|
|
ClutterEventFlags
|
|
clutter_event_get_flags (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, CLUTTER_EVENT_NONE);
|
|
|
|
return event->any.flags;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_related:
|
|
* @event: a #ClutterEvent of type %CLUTTER_ENTER or of
|
|
* type %CLUTTER_LEAVE
|
|
*
|
|
* Retrieves the related actor of a crossing event.
|
|
*
|
|
* Return value: (transfer none): the related #ClutterActor, or %NULL
|
|
*/
|
|
ClutterActor *
|
|
clutter_event_get_related (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, NULL);
|
|
g_return_val_if_fail (event->type == CLUTTER_ENTER ||
|
|
event->type == CLUTTER_LEAVE, NULL);
|
|
|
|
return event->crossing.related;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_scroll_delta:
|
|
* @event: a #ClutterEvent of type %CLUTTER_SCROLL
|
|
* @dx: (out): return location for the delta on the horizontal axis
|
|
* @dy: (out): return location for the delta on the vertical axis
|
|
*
|
|
* Retrieves the precise scrolling information of @event.
|
|
*
|
|
* The @event has to have a #ClutterScrollEvent.direction value
|
|
* of %CLUTTER_SCROLL_SMOOTH.
|
|
*/
|
|
void
|
|
clutter_event_get_scroll_delta (const ClutterEvent *event,
|
|
gdouble *dx,
|
|
gdouble *dy)
|
|
{
|
|
g_return_if_fail (event != NULL);
|
|
g_return_if_fail (event->type == CLUTTER_SCROLL);
|
|
g_return_if_fail (event->scroll.direction == CLUTTER_SCROLL_SMOOTH);
|
|
|
|
if (dx != NULL)
|
|
*dx = event->scroll.delta_x;
|
|
|
|
if (dy != NULL)
|
|
*dy = event->scroll.delta_y;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_scroll_direction:
|
|
* @event: a #ClutterEvent of type %CLUTTER_SCROLL
|
|
*
|
|
* Retrieves the direction of the scrolling of @event
|
|
*
|
|
* Return value: the scrolling direction
|
|
*/
|
|
ClutterScrollDirection
|
|
clutter_event_get_scroll_direction (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_UP);
|
|
g_return_val_if_fail (event->type == CLUTTER_SCROLL, CLUTTER_SCROLL_UP);
|
|
|
|
return event->scroll.direction;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_button:
|
|
* @event: a #ClutterEvent of type %CLUTTER_BUTTON_PRESS or
|
|
* of type %CLUTTER_BUTTON_RELEASE
|
|
*
|
|
* Retrieves the button number of @event
|
|
*
|
|
* Return value: the button number
|
|
*/
|
|
guint32
|
|
clutter_event_get_button (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_BUTTON_PRESS ||
|
|
event->type == CLUTTER_BUTTON_RELEASE ||
|
|
event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
|
event->type == CLUTTER_PAD_BUTTON_RELEASE, 0);
|
|
|
|
if (event->type == CLUTTER_BUTTON_PRESS ||
|
|
event->type == CLUTTER_BUTTON_RELEASE)
|
|
return event->button.button;
|
|
else
|
|
return event->pad_button.button;
|
|
}
|
|
|
|
/* keys */
|
|
|
|
/**
|
|
* clutter_event_get_key_symbol:
|
|
* @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or
|
|
* of type %CLUTTER_KEY_RELEASE
|
|
*
|
|
* Retrieves the key symbol of @event
|
|
*
|
|
* Return value: the key symbol representing the key
|
|
*/
|
|
guint
|
|
clutter_event_get_key_symbol (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
|
|
event->type == CLUTTER_KEY_RELEASE, 0);
|
|
|
|
return event->key.keyval;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_key_code:
|
|
* @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or
|
|
* of type %CLUTTER_KEY_RELEASE
|
|
*
|
|
* Retrieves the keycode of the key that caused @event
|
|
*
|
|
* Return value: The keycode representing the key
|
|
*/
|
|
guint16
|
|
clutter_event_get_key_code (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
|
|
event->type == CLUTTER_KEY_RELEASE, 0);
|
|
|
|
return event->key.hardware_keycode;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_key_unicode:
|
|
* @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS
|
|
* or %CLUTTER_KEY_RELEASE
|
|
*
|
|
* Retrieves the unicode value for the key that caused @keyev.
|
|
*
|
|
* Return value: The unicode value representing the key
|
|
*/
|
|
gunichar
|
|
clutter_event_get_key_unicode (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
|
|
event->type == CLUTTER_KEY_RELEASE, 0);
|
|
|
|
if (event->key.unicode_value)
|
|
return event->key.unicode_value;
|
|
else
|
|
return clutter_keysym_to_unicode (event->key.keyval);
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_key_state:
|
|
* @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS
|
|
* or %CLUTTER_KEY_RELEASE
|
|
* @pressed: (out): Return location for pressed modifiers
|
|
* @latched: (out): Return location for latched modifiers
|
|
* @locked: (out): Return location for locked modifiers
|
|
*
|
|
* Returns the modifier state decomposed into independent
|
|
* pressed/latched/locked states. The effective state is a
|
|
* composition of these 3 states, see [method@Clutter.Event.get_state].
|
|
**/
|
|
void
|
|
clutter_event_get_key_state (const ClutterEvent *event,
|
|
ClutterModifierType *pressed,
|
|
ClutterModifierType *latched,
|
|
ClutterModifierType *locked)
|
|
{
|
|
g_return_if_fail (event != NULL);
|
|
g_return_if_fail (event->type == CLUTTER_KEY_PRESS ||
|
|
event->type == CLUTTER_KEY_RELEASE);
|
|
|
|
if (pressed)
|
|
*pressed = event->key.raw_modifiers.pressed;
|
|
if (latched)
|
|
*latched = event->key.raw_modifiers.latched;
|
|
if (locked)
|
|
*locked = event->key.raw_modifiers.locked;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_event_sequence:
|
|
* @event: a #ClutterEvent of type %CLUTTER_TOUCH_BEGIN,
|
|
* %CLUTTER_TOUCH_UPDATE, %CLUTTER_TOUCH_END, or
|
|
* %CLUTTER_TOUCH_CANCEL
|
|
*
|
|
* Retrieves the #ClutterEventSequence of @event.
|
|
*
|
|
* Return value: (transfer none): the event sequence, or %NULL
|
|
*/
|
|
ClutterEventSequence *
|
|
clutter_event_get_event_sequence (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, NULL);
|
|
|
|
if (event->type == CLUTTER_TOUCH_BEGIN ||
|
|
event->type == CLUTTER_TOUCH_UPDATE ||
|
|
event->type == CLUTTER_TOUCH_END ||
|
|
event->type == CLUTTER_TOUCH_CANCEL)
|
|
return event->touch.sequence;
|
|
else if (event->type == CLUTTER_ENTER ||
|
|
event->type == CLUTTER_LEAVE)
|
|
return event->crossing.sequence;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_device_type:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Retrieves the type of the device for @event
|
|
*
|
|
* Return value: the #ClutterInputDeviceType for the device, if
|
|
* any is set
|
|
*/
|
|
ClutterInputDeviceType
|
|
clutter_event_get_device_type (const ClutterEvent *event)
|
|
{
|
|
ClutterInputDevice *device = NULL;
|
|
|
|
g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
|
|
|
|
device = clutter_event_get_device (event);
|
|
if (device != NULL)
|
|
return clutter_input_device_get_device_type (device);
|
|
|
|
return CLUTTER_POINTER_DEVICE;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_device:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Retrieves the #ClutterInputDevice for the event.
|
|
* If you want the physical device the event originated from, use
|
|
* [method@Clutter.Event.get_source_device].
|
|
*
|
|
* The #ClutterInputDevice structure is completely opaque and should
|
|
* be cast to the platform-specific implementation.
|
|
*
|
|
* Return value: (transfer none): the #ClutterInputDevice or %NULL. The
|
|
* returned device is owned by the #ClutterEvent and it should not
|
|
* be unreferenced
|
|
*/
|
|
ClutterInputDevice *
|
|
clutter_event_get_device (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, NULL);
|
|
|
|
return event->any.device;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_device_tool:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Returns the device tool that originated this event
|
|
*
|
|
* Returns: (transfer none): The tool of this event8
|
|
**/
|
|
ClutterInputDeviceTool *
|
|
clutter_event_get_device_tool (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, NULL);
|
|
|
|
switch (event->any.type)
|
|
{
|
|
case CLUTTER_BUTTON_PRESS:
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
return event->button.tool;
|
|
case CLUTTER_MOTION:
|
|
return event->motion.tool;
|
|
case CLUTTER_SCROLL:
|
|
return event->scroll.tool;
|
|
case CLUTTER_PROXIMITY_IN:
|
|
case CLUTTER_PROXIMITY_OUT:
|
|
return event->proximity.tool;
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static ClutterEvent *
|
|
clutter_event_new (ClutterEventType type)
|
|
{
|
|
ClutterEvent *new_event;
|
|
|
|
new_event = g_new0 (ClutterEvent, 1);
|
|
new_event->any.type = type;
|
|
|
|
return new_event;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_copy:
|
|
* @event: A #ClutterEvent.
|
|
*
|
|
* Copies @event.
|
|
*
|
|
* Return value: (transfer full): A newly allocated #ClutterEvent
|
|
*/
|
|
ClutterEvent *
|
|
clutter_event_copy (const ClutterEvent *event)
|
|
{
|
|
ClutterEvent *new_event;
|
|
|
|
g_return_val_if_fail (event != NULL, NULL);
|
|
|
|
new_event = clutter_event_new (CLUTTER_NOTHING);
|
|
|
|
g_set_object (&new_event->any.device, event->any.device);
|
|
g_set_object (&new_event->any.source_device, event->any.source_device);
|
|
*new_event = *event;
|
|
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_BUTTON_PRESS:
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
if (event->button.axes != NULL)
|
|
{
|
|
new_event->button.axes =
|
|
g_memdup2 (event->button.axes,
|
|
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
|
}
|
|
break;
|
|
|
|
case CLUTTER_SCROLL:
|
|
if (event->scroll.axes != NULL)
|
|
{
|
|
new_event->scroll.axes =
|
|
g_memdup2 (event->scroll.axes,
|
|
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
|
}
|
|
break;
|
|
|
|
case CLUTTER_MOTION:
|
|
if (event->motion.axes != NULL)
|
|
{
|
|
new_event->motion.axes =
|
|
g_memdup2 (event->motion.axes,
|
|
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
|
}
|
|
break;
|
|
|
|
case CLUTTER_TOUCH_BEGIN:
|
|
case CLUTTER_TOUCH_UPDATE:
|
|
case CLUTTER_TOUCH_END:
|
|
case CLUTTER_TOUCH_CANCEL:
|
|
if (event->touch.axes != NULL)
|
|
{
|
|
new_event->touch.axes =
|
|
g_memdup2 (event->touch.axes,
|
|
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
|
}
|
|
break;
|
|
|
|
case CLUTTER_IM_COMMIT:
|
|
case CLUTTER_IM_PREEDIT:
|
|
new_event->im.text = g_strdup (event->im.text);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return new_event;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_free:
|
|
* @event: A #ClutterEvent.
|
|
*
|
|
* Frees all resources used by @event.
|
|
*/
|
|
void
|
|
clutter_event_free (ClutterEvent *event)
|
|
{
|
|
if (G_LIKELY (event != NULL))
|
|
{
|
|
g_clear_object (&event->any.device);
|
|
g_clear_object (&event->any.source_device);
|
|
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_BUTTON_PRESS:
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
g_free (event->button.axes);
|
|
break;
|
|
|
|
case CLUTTER_MOTION:
|
|
g_free (event->motion.axes);
|
|
break;
|
|
|
|
case CLUTTER_SCROLL:
|
|
g_free (event->scroll.axes);
|
|
break;
|
|
|
|
case CLUTTER_TOUCH_BEGIN:
|
|
case CLUTTER_TOUCH_UPDATE:
|
|
case CLUTTER_TOUCH_END:
|
|
case CLUTTER_TOUCH_CANCEL:
|
|
g_free (event->touch.axes);
|
|
break;
|
|
|
|
case CLUTTER_IM_COMMIT:
|
|
case CLUTTER_IM_PREEDIT:
|
|
g_free (event->im.text);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
g_free (event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get:
|
|
*
|
|
* Pops an event off the event queue. Applications should not need to call
|
|
* this.
|
|
*
|
|
* Return value: A #ClutterEvent or NULL if queue empty
|
|
*/
|
|
ClutterEvent *
|
|
clutter_event_get (void)
|
|
{
|
|
ClutterContext *context = _clutter_context_get_default ();
|
|
ClutterEvent *event;
|
|
|
|
event = g_async_queue_try_pop (context->events_queue);
|
|
|
|
return event;
|
|
}
|
|
|
|
void
|
|
_clutter_event_push (const ClutterEvent *event,
|
|
gboolean do_copy)
|
|
{
|
|
ClutterContext *context = _clutter_context_get_default ();
|
|
|
|
g_assert (context != NULL);
|
|
|
|
if (do_copy)
|
|
{
|
|
ClutterEvent *copy;
|
|
|
|
copy = clutter_event_copy (event);
|
|
event = copy;
|
|
}
|
|
|
|
g_async_queue_lock (context->events_queue);
|
|
g_async_queue_push_unlocked (context->events_queue, (gpointer) event);
|
|
if (g_async_queue_length_unlocked (context->events_queue) == 1)
|
|
g_main_context_wakeup (NULL);
|
|
g_async_queue_unlock (context->events_queue);
|
|
}
|
|
|
|
/**
|
|
* clutter_event_put:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Puts a copy of the event on the back of the event queue. The event will
|
|
* have the %CLUTTER_EVENT_FLAG_SYNTHETIC flag set. If the source is set
|
|
* event signals will be emitted for this source and capture/bubbling for
|
|
* its ancestors. If the source is not set it will be generated by picking
|
|
* or use the actor that currently has keyboard focus
|
|
*/
|
|
void
|
|
clutter_event_put (const ClutterEvent *event)
|
|
{
|
|
_clutter_event_push (event, TRUE);
|
|
}
|
|
|
|
/**
|
|
* clutter_events_pending:
|
|
*
|
|
* Checks if events are pending in the event queue.
|
|
*
|
|
* Return value: TRUE if there are pending events, FALSE otherwise.
|
|
*/
|
|
gboolean
|
|
clutter_events_pending (void)
|
|
{
|
|
ClutterContext *context = _clutter_context_get_default ();
|
|
|
|
g_return_val_if_fail (context != NULL, FALSE);
|
|
|
|
return g_async_queue_length (context->events_queue) > 0;
|
|
}
|
|
|
|
/**
|
|
* clutter_get_current_event_time:
|
|
*
|
|
* Retrieves the timestamp of the last event, if there is an
|
|
* event or if the event has a timestamp.
|
|
*
|
|
* Return value: the event timestamp, or %CLUTTER_CURRENT_TIME
|
|
*/
|
|
guint32
|
|
clutter_get_current_event_time (void)
|
|
{
|
|
const ClutterEvent* event;
|
|
|
|
event = clutter_get_current_event ();
|
|
|
|
if (event != NULL)
|
|
return clutter_event_get_time (event);
|
|
|
|
return CLUTTER_CURRENT_TIME;
|
|
}
|
|
|
|
/**
|
|
* clutter_get_current_event:
|
|
*
|
|
* If an event is currently being processed, return that event.
|
|
* This function is intended to be used to access event state
|
|
* that might not be exposed by higher-level widgets. For
|
|
* example, to get the key modifier state from a Button 'clicked'
|
|
* event.
|
|
*
|
|
* Return value: (transfer none): The current ClutterEvent, or %NULL if none
|
|
*/
|
|
const ClutterEvent *
|
|
clutter_get_current_event (void)
|
|
{
|
|
ClutterContext *context = _clutter_context_get_default ();
|
|
|
|
g_return_val_if_fail (context != NULL, NULL);
|
|
|
|
return context->current_event != NULL ? context->current_event->data : NULL;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_source_device:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Retrieves the hardware device that originated the event.
|
|
*
|
|
* If you need the virtual device, use [method@Clutter.Event.get_device].
|
|
*
|
|
* If no hardware device originated this event, this function will
|
|
* return the same device as [method@Clutter.Event.get_device].
|
|
*
|
|
* Return value: (transfer none): a pointer to a #ClutterInputDevice
|
|
* or %NULL
|
|
*/
|
|
ClutterInputDevice *
|
|
clutter_event_get_source_device (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, NULL);
|
|
|
|
if (event->any.source_device)
|
|
return event->any.source_device;
|
|
else
|
|
return clutter_event_get_device (event);
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_axes:
|
|
* @event: a #ClutterEvent
|
|
* @n_axes: (out): return location for the number of axes returned
|
|
*
|
|
* Retrieves the array of axes values attached to the event.
|
|
*
|
|
* Return value: (transfer none): an array of axis values
|
|
*/
|
|
gdouble *
|
|
clutter_event_get_axes (const ClutterEvent *event,
|
|
guint *n_axes)
|
|
{
|
|
gdouble *retval = NULL;
|
|
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_NOTHING:
|
|
case CLUTTER_ENTER:
|
|
case CLUTTER_LEAVE:
|
|
case CLUTTER_KEY_PRESS:
|
|
case CLUTTER_KEY_RELEASE:
|
|
case CLUTTER_EVENT_LAST:
|
|
case CLUTTER_PROXIMITY_IN:
|
|
case CLUTTER_PROXIMITY_OUT:
|
|
case CLUTTER_DEVICE_ADDED:
|
|
case CLUTTER_DEVICE_REMOVED:
|
|
break;
|
|
|
|
case CLUTTER_SCROLL:
|
|
retval = event->scroll.axes;
|
|
break;
|
|
|
|
case CLUTTER_BUTTON_PRESS:
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
retval = event->button.axes;
|
|
break;
|
|
|
|
case CLUTTER_TOUCH_BEGIN:
|
|
case CLUTTER_TOUCH_UPDATE:
|
|
case CLUTTER_TOUCH_END:
|
|
case CLUTTER_TOUCH_CANCEL:
|
|
retval = event->touch.axes;
|
|
break;
|
|
|
|
case CLUTTER_MOTION:
|
|
retval = event->motion.axes;
|
|
break;
|
|
|
|
case CLUTTER_TOUCHPAD_PINCH:
|
|
case CLUTTER_TOUCHPAD_SWIPE:
|
|
case CLUTTER_TOUCHPAD_HOLD:
|
|
case CLUTTER_PAD_BUTTON_PRESS:
|
|
case CLUTTER_PAD_BUTTON_RELEASE:
|
|
case CLUTTER_PAD_STRIP:
|
|
case CLUTTER_PAD_RING:
|
|
case CLUTTER_IM_COMMIT:
|
|
case CLUTTER_IM_DELETE:
|
|
case CLUTTER_IM_PREEDIT:
|
|
break;
|
|
}
|
|
|
|
if (n_axes)
|
|
*n_axes = CLUTTER_INPUT_AXIS_LAST;
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_distance:
|
|
* @source: a #ClutterEvent
|
|
* @target: a #ClutterEvent
|
|
*
|
|
* Retrieves the distance between two events, a @source and a @target.
|
|
*
|
|
* Return value: the distance between two #ClutterEvent
|
|
*/
|
|
float
|
|
clutter_event_get_distance (const ClutterEvent *source,
|
|
const ClutterEvent *target)
|
|
{
|
|
graphene_point_t p0, p1;
|
|
|
|
clutter_event_get_position (source, &p0);
|
|
clutter_event_get_position (source, &p1);
|
|
|
|
return graphene_point_distance (&p0, &p1, NULL, NULL);
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_angle:
|
|
* @source: a #ClutterEvent
|
|
* @target: a #ClutterEvent
|
|
*
|
|
* Retrieves the angle relative from @source to @target.
|
|
*
|
|
* The direction of the angle is from the position X axis towards
|
|
* the positive Y axis.
|
|
*
|
|
* Return value: the angle between two #ClutterEvent
|
|
*/
|
|
double
|
|
clutter_event_get_angle (const ClutterEvent *source,
|
|
const ClutterEvent *target)
|
|
{
|
|
graphene_point_t p0, p1;
|
|
float x_distance, y_distance;
|
|
double angle;
|
|
|
|
clutter_event_get_position (source, &p0);
|
|
clutter_event_get_position (target, &p1);
|
|
|
|
if (graphene_point_equal (&p0, &p1))
|
|
return 0;
|
|
|
|
graphene_point_distance (&p0, &p1, &x_distance, &y_distance);
|
|
|
|
angle = atan2 (x_distance, y_distance);
|
|
|
|
/* invert the angle, and shift it by 90 degrees */
|
|
angle = (2.0 * G_PI) - angle;
|
|
angle += G_PI / 2.0;
|
|
|
|
/* keep the angle within the [ 0, 360 ] interval */
|
|
angle = fmod (angle, 2.0 * G_PI);
|
|
|
|
return angle;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_has_shift_modifier:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Checks whether @event has the Shift modifier mask set.
|
|
*
|
|
* Return value: %TRUE if the event has the Shift modifier mask set
|
|
*/
|
|
gboolean
|
|
clutter_event_has_shift_modifier (const ClutterEvent *event)
|
|
{
|
|
return (clutter_event_get_state (event) & CLUTTER_SHIFT_MASK) != FALSE;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_has_control_modifier:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Checks whether @event has the Control modifier mask set.
|
|
*
|
|
* Return value: %TRUE if the event has the Control modifier mask set
|
|
*/
|
|
gboolean
|
|
clutter_event_has_control_modifier (const ClutterEvent *event)
|
|
{
|
|
return (clutter_event_get_state (event) & CLUTTER_CONTROL_MASK) != FALSE;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_is_pointer_emulated:
|
|
* @event: a #ClutterEvent
|
|
*
|
|
* Checks whether a pointer @event has been generated by the windowing
|
|
* system. The returned value can be used to distinguish between events
|
|
* synthesized by the windowing system itself (as opposed by Clutter).
|
|
*
|
|
* Return value: %TRUE if the event is pointer emulated
|
|
*/
|
|
gboolean
|
|
clutter_event_is_pointer_emulated (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, FALSE);
|
|
|
|
return !!(event->any.flags & CLUTTER_EVENT_FLAG_POINTER_EMULATED);
|
|
}
|
|
|
|
gboolean
|
|
_clutter_event_process_filters (ClutterEvent *event,
|
|
ClutterActor *event_actor)
|
|
{
|
|
ClutterContext *context = _clutter_context_get_default ();
|
|
GList *l, *next;
|
|
|
|
/* Event filters are handled in order from least recently added to
|
|
* most recently added */
|
|
|
|
for (l = context->event_filters; l; l = next)
|
|
{
|
|
ClutterEventFilter *event_filter = l->data;
|
|
|
|
next = l->next;
|
|
|
|
if (event_filter->stage &&
|
|
event_filter->stage != CLUTTER_STAGE (clutter_actor_get_stage (event_actor)))
|
|
continue;
|
|
|
|
if (event_filter->func (event, event_actor, event_filter->user_data) == CLUTTER_EVENT_STOP)
|
|
return CLUTTER_EVENT_STOP;
|
|
}
|
|
|
|
return CLUTTER_EVENT_PROPAGATE;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_add_filter:
|
|
* @stage: (allow-none): The #ClutterStage to capture events for
|
|
* @func: The callback function which will be passed all events.
|
|
* @notify: A #GDestroyNotify
|
|
* @user_data: A data pointer to pass to the function.
|
|
*
|
|
* Adds a function which will be called for all events that Clutter
|
|
* processes. The function will be called before any signals are
|
|
* emitted for the event and it will take precedence over any grabs.
|
|
*
|
|
* Return value: an identifier for the event filter, to be used
|
|
* with [func@Clutter.Event.remove_filter].
|
|
*/
|
|
guint
|
|
clutter_event_add_filter (ClutterStage *stage,
|
|
ClutterEventFilterFunc func,
|
|
GDestroyNotify notify,
|
|
gpointer user_data)
|
|
{
|
|
ClutterContext *context = _clutter_context_get_default ();
|
|
ClutterEventFilter *event_filter = g_new0 (ClutterEventFilter, 1);
|
|
static guint event_filter_id = 0;
|
|
|
|
event_filter->stage = stage;
|
|
event_filter->id = ++event_filter_id;
|
|
event_filter->func = func;
|
|
event_filter->notify = notify;
|
|
event_filter->user_data = user_data;
|
|
|
|
/* The event filters are kept in order from least recently added to
|
|
* most recently added so we must add it to the end */
|
|
context->event_filters = g_list_append (context->event_filters, event_filter);
|
|
|
|
return event_filter->id;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_remove_filter:
|
|
* @id: The ID of the event filter, as returned from [func@Clutter.Event.add_filter]
|
|
*
|
|
* Removes an event filter that was previously added with
|
|
* [func@Clutter.Event.add_filter].
|
|
*/
|
|
void
|
|
clutter_event_remove_filter (guint id)
|
|
{
|
|
ClutterContext *context = _clutter_context_get_default ();
|
|
GList *l;
|
|
|
|
for (l = context->event_filters; l; l = l->next)
|
|
{
|
|
ClutterEventFilter *event_filter = l->data;
|
|
|
|
if (event_filter->id == id)
|
|
{
|
|
if (event_filter->notify)
|
|
event_filter->notify (event_filter->user_data);
|
|
|
|
context->event_filters = g_list_delete_link (context->event_filters, l);
|
|
g_free (event_filter);
|
|
return;
|
|
}
|
|
}
|
|
|
|
g_warning ("No event filter found for id: %d\n", id);
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_touchpad_gesture_finger_count:
|
|
* @event: a touchpad swipe/pinch event
|
|
*
|
|
* Returns the number of fingers that is triggering the touchpad gesture.
|
|
*
|
|
* Returns: the number of fingers in the gesture.4
|
|
**/
|
|
guint
|
|
clutter_event_get_touchpad_gesture_finger_count (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_SWIPE ||
|
|
event->type == CLUTTER_TOUCHPAD_PINCH ||
|
|
event->type == CLUTTER_TOUCHPAD_HOLD, 0);
|
|
|
|
if (event->type == CLUTTER_TOUCHPAD_SWIPE)
|
|
return event->touchpad_swipe.n_fingers;
|
|
else if (event->type == CLUTTER_TOUCHPAD_PINCH)
|
|
return event->touchpad_pinch.n_fingers;
|
|
else if (event->type == CLUTTER_TOUCHPAD_HOLD)
|
|
return event->touchpad_hold.n_fingers;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_gesture_pinch_angle_delta:
|
|
* @event: a touchpad pinch event
|
|
*
|
|
* Returns the angle delta reported by this specific event.
|
|
*
|
|
* Returns: The angle delta relative to the previous event.4
|
|
**/
|
|
gdouble
|
|
clutter_event_get_gesture_pinch_angle_delta (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH, 0);
|
|
|
|
return event->touchpad_pinch.angle_delta;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_gesture_pinch_scale:
|
|
* @event: a touchpad pinch event
|
|
*
|
|
* Returns the current scale as reported by @event, 1.0 being the original
|
|
* distance at the time the corresponding event with phase
|
|
* %CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN is received.
|
|
* is received.
|
|
*
|
|
* Returns: the current pinch gesture scale4
|
|
**/
|
|
gdouble
|
|
clutter_event_get_gesture_pinch_scale (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH, 0);
|
|
|
|
return event->touchpad_pinch.scale;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_gesture_phase:
|
|
* @event: a touchpad gesture event
|
|
*
|
|
* Returns the phase of the event, See #ClutterTouchpadGesturePhase.
|
|
*
|
|
* Returns: the phase of the gesture event.
|
|
**/
|
|
ClutterTouchpadGesturePhase
|
|
clutter_event_get_gesture_phase (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
|
|
event->type == CLUTTER_TOUCHPAD_SWIPE ||
|
|
event->type == CLUTTER_TOUCHPAD_HOLD, 0);
|
|
|
|
if (event->type == CLUTTER_TOUCHPAD_PINCH)
|
|
return event->touchpad_pinch.phase;
|
|
else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
|
|
return event->touchpad_swipe.phase;
|
|
else if (event->type == CLUTTER_TOUCHPAD_HOLD)
|
|
return event->touchpad_hold.phase;
|
|
|
|
/* Shouldn't ever happen */
|
|
return CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN;
|
|
};
|
|
|
|
/**
|
|
* clutter_event_get_gesture_motion_delta:
|
|
* @event: A clutter touchpad gesture event
|
|
* @dx: (out) (allow-none): the displacement relative to the pointer
|
|
* position in the X axis, or %NULL
|
|
* @dy: (out) (allow-none): the displacement relative to the pointer
|
|
* position in the Y axis, or %NULL
|
|
*
|
|
* Returns the gesture motion deltas relative to the current pointer
|
|
* position.4
|
|
**/
|
|
void
|
|
clutter_event_get_gesture_motion_delta (const ClutterEvent *event,
|
|
gdouble *dx,
|
|
gdouble *dy)
|
|
{
|
|
g_return_if_fail (event != NULL);
|
|
g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
|
|
event->type == CLUTTER_TOUCHPAD_SWIPE ||
|
|
event->type == CLUTTER_TOUCHPAD_HOLD);
|
|
|
|
if (event->type == CLUTTER_TOUCHPAD_PINCH)
|
|
{
|
|
if (dx)
|
|
*dx = event->touchpad_pinch.dx;
|
|
if (dy)
|
|
*dy = event->touchpad_pinch.dy;
|
|
}
|
|
else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
|
|
{
|
|
if (dx)
|
|
*dx = event->touchpad_swipe.dx;
|
|
if (dy)
|
|
*dy = event->touchpad_swipe.dy;
|
|
}
|
|
else if (event->type == CLUTTER_TOUCHPAD_HOLD)
|
|
{
|
|
if (dx)
|
|
*dx = 0;
|
|
if (dy)
|
|
*dy = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_gesture_motion_delta_unaccelerated:
|
|
* @event: A clutter touchpad gesture event
|
|
* @dx: (out) (allow-none): the displacement relative to the pointer
|
|
* position in the X axis, or %NULL
|
|
* @dy: (out) (allow-none): the displacement relative to the pointer
|
|
* position in the Y axis, or %NULL
|
|
*
|
|
* Returns the unaccelerated gesture motion deltas relative to the current
|
|
* pointer position. Unlike [method@Clutter.Event.get_gesture_motion_delta],
|
|
* pointer acceleration is ignored.
|
|
**/
|
|
void
|
|
clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
|
|
gdouble *dx,
|
|
gdouble *dy)
|
|
{
|
|
g_return_if_fail (event != NULL);
|
|
g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
|
|
event->type == CLUTTER_TOUCHPAD_SWIPE ||
|
|
event->type == CLUTTER_TOUCHPAD_HOLD);
|
|
|
|
if (event->type == CLUTTER_TOUCHPAD_PINCH)
|
|
{
|
|
if (dx)
|
|
*dx = event->touchpad_pinch.dx_unaccel;
|
|
if (dy)
|
|
*dy = event->touchpad_pinch.dy_unaccel;
|
|
}
|
|
else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
|
|
{
|
|
if (dx)
|
|
*dx = event->touchpad_swipe.dx_unaccel;
|
|
if (dy)
|
|
*dy = event->touchpad_swipe.dy_unaccel;
|
|
}
|
|
else if (event->type == CLUTTER_TOUCHPAD_HOLD)
|
|
{
|
|
if (dx)
|
|
*dx = 0;
|
|
if (dy)
|
|
*dy = 0;
|
|
}
|
|
}
|
|
/**
|
|
* clutter_event_get_scroll_source:
|
|
* @event: an scroll event
|
|
*
|
|
* Returns the #ClutterScrollSource that applies to an scroll event.
|
|
*
|
|
* Returns: The source of scroll events6
|
|
**/
|
|
ClutterScrollSource
|
|
clutter_event_get_scroll_source (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_SOURCE_UNKNOWN);
|
|
g_return_val_if_fail (event->type == CLUTTER_SCROLL,
|
|
CLUTTER_SCROLL_SOURCE_UNKNOWN);
|
|
|
|
return event->scroll.scroll_source;
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_scroll_finish_flags:
|
|
* @event: an scroll event
|
|
*
|
|
* Returns the #ClutterScrollFinishFlags of an scroll event. Those
|
|
* can be used to determine whether post-scroll effects like kinetic
|
|
* scrolling should be applied.
|
|
*
|
|
* Returns: The scroll finish flags6
|
|
**/
|
|
ClutterScrollFinishFlags
|
|
clutter_event_get_scroll_finish_flags (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_FINISHED_NONE);
|
|
g_return_val_if_fail (event->type == CLUTTER_SCROLL,
|
|
CLUTTER_SCROLL_FINISHED_NONE);
|
|
|
|
return event->scroll.finish_flags;
|
|
}
|
|
|
|
guint
|
|
clutter_event_get_mode_group (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
|
event->type == CLUTTER_PAD_BUTTON_RELEASE ||
|
|
event->type == CLUTTER_PAD_RING ||
|
|
event->type == CLUTTER_PAD_STRIP, 0);
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_PAD_BUTTON_PRESS:
|
|
case CLUTTER_PAD_BUTTON_RELEASE:
|
|
return event->pad_button.group;
|
|
case CLUTTER_PAD_RING:
|
|
return event->pad_ring.group;
|
|
case CLUTTER_PAD_STRIP:
|
|
return event->pad_strip.group;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_event_get_pad_details:
|
|
* @event: a pad event
|
|
* @number: (out) (optional): ring/strip/button number
|
|
* @mode: (out) (optional): pad mode as per the event
|
|
* @source: (out) (optional): source of the event
|
|
* @value: (out) (optional): event axis value
|
|
*
|
|
* Returns the details of a pad event.
|
|
*
|
|
* Returns: #TRUE if event details could be obtained
|
|
**/
|
|
gboolean
|
|
clutter_event_get_pad_details (const ClutterEvent *event,
|
|
guint *number,
|
|
guint *mode,
|
|
ClutterInputDevicePadSource *source,
|
|
gdouble *value)
|
|
{
|
|
ClutterInputDevicePadSource s;
|
|
guint n, m;
|
|
gdouble v;
|
|
|
|
g_return_val_if_fail (event != NULL, FALSE);
|
|
g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
|
event->type == CLUTTER_PAD_BUTTON_RELEASE ||
|
|
event->type == CLUTTER_PAD_RING ||
|
|
event->type == CLUTTER_PAD_STRIP, FALSE);
|
|
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_PAD_BUTTON_PRESS:
|
|
case CLUTTER_PAD_BUTTON_RELEASE:
|
|
n = event->pad_button.button;
|
|
m = event->pad_button.mode;
|
|
s = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN;
|
|
v = 0.0;
|
|
break;
|
|
case CLUTTER_PAD_RING:
|
|
n = event->pad_ring.ring_number;
|
|
m = event->pad_ring.mode;
|
|
s = event->pad_ring.ring_source;
|
|
v = event->pad_ring.angle;
|
|
break;
|
|
case CLUTTER_PAD_STRIP:
|
|
n = event->pad_strip.strip_number;
|
|
m = event->pad_strip.mode;
|
|
s = event->pad_strip.strip_source;
|
|
v = event->pad_strip.value;
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
if (number)
|
|
*number = n;
|
|
if (mode)
|
|
*mode = m;
|
|
if (source)
|
|
*source = s;
|
|
if (value)
|
|
*value = v;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
uint32_t
|
|
clutter_event_get_event_code (const ClutterEvent *event)
|
|
{
|
|
if (event->type == CLUTTER_KEY_PRESS ||
|
|
event->type == CLUTTER_KEY_RELEASE)
|
|
return event->key.evdev_code;
|
|
else if (event->type == CLUTTER_BUTTON_PRESS ||
|
|
event->type == CLUTTER_BUTTON_RELEASE)
|
|
return event->button.evdev_code;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t
|
|
clutter_event_sequence_get_slot (const ClutterEventSequence *sequence)
|
|
{
|
|
g_return_val_if_fail (sequence != NULL, -1);
|
|
|
|
return GPOINTER_TO_INT (sequence) - 1;
|
|
}
|
|
|
|
int64_t
|
|
clutter_event_get_time_us (const ClutterEvent *event)
|
|
{
|
|
return event->any.time_us;
|
|
}
|
|
|
|
gboolean
|
|
clutter_event_get_relative_motion (const ClutterEvent *event,
|
|
double *dx,
|
|
double *dy,
|
|
double *dx_unaccel,
|
|
double *dy_unaccel,
|
|
double *dx_constrained,
|
|
double *dy_constrained)
|
|
{
|
|
if (event->type == CLUTTER_MOTION &&
|
|
event->motion.flags & CLUTTER_EVENT_FLAG_RELATIVE_MOTION)
|
|
{
|
|
if (dx)
|
|
*dx = event->motion.dx;
|
|
if (dy)
|
|
*dy = event->motion.dy;
|
|
if (dx_unaccel)
|
|
*dx_unaccel = event->motion.dx_unaccel;
|
|
if (dy_unaccel)
|
|
*dy_unaccel = event->motion.dy_unaccel;
|
|
if (dx_constrained)
|
|
*dx_constrained = event->motion.dx_constrained;
|
|
if (dy_constrained)
|
|
*dy_constrained = event->motion.dy_constrained;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
const char *
|
|
clutter_event_get_im_text (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, NULL);
|
|
g_return_val_if_fail (event->type == CLUTTER_IM_COMMIT ||
|
|
event->type == CLUTTER_IM_PREEDIT, NULL);
|
|
|
|
return event->im.text;
|
|
}
|
|
|
|
gboolean
|
|
clutter_event_get_im_location (const ClutterEvent *event,
|
|
int32_t *offset,
|
|
int32_t *anchor)
|
|
{
|
|
g_return_val_if_fail (event != NULL, FALSE);
|
|
g_return_val_if_fail (event->type == CLUTTER_IM_DELETE ||
|
|
event->type == CLUTTER_IM_PREEDIT, FALSE);
|
|
|
|
if (offset)
|
|
*offset = event->im.offset;
|
|
if (anchor)
|
|
*anchor = event->im.anchor;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
uint32_t
|
|
clutter_event_get_im_delete_length (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, 0);
|
|
g_return_val_if_fail (event->type == CLUTTER_IM_DELETE, 0);
|
|
|
|
return event->im.len;
|
|
}
|
|
|
|
ClutterPreeditResetMode
|
|
clutter_event_get_im_preedit_reset_mode (const ClutterEvent *event)
|
|
{
|
|
g_return_val_if_fail (event != NULL, CLUTTER_PREEDIT_RESET_CLEAR);
|
|
g_return_val_if_fail (event->type == CLUTTER_IM_COMMIT ||
|
|
event->type == CLUTTER_IM_PREEDIT,
|
|
CLUTTER_PREEDIT_RESET_CLEAR);
|
|
|
|
return event->im.mode;
|
|
}
|
|
|
|
const char *
|
|
clutter_event_get_name (const ClutterEvent *event)
|
|
{
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_KEY_PRESS:
|
|
return "key-press";
|
|
case CLUTTER_KEY_RELEASE:
|
|
return "key-release";
|
|
case CLUTTER_MOTION:
|
|
return "motion";
|
|
case CLUTTER_ENTER:
|
|
return "enter";
|
|
case CLUTTER_LEAVE:
|
|
return "leave";
|
|
case CLUTTER_BUTTON_PRESS:
|
|
return "button-press";
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
return "button-release";
|
|
case CLUTTER_SCROLL:
|
|
return "scroll";
|
|
case CLUTTER_TOUCH_BEGIN:
|
|
return "touch-begin";
|
|
case CLUTTER_TOUCH_UPDATE:
|
|
return "touch-update";
|
|
case CLUTTER_TOUCH_END:
|
|
return "touch-end";
|
|
case CLUTTER_TOUCH_CANCEL:
|
|
return "touch-cancel";
|
|
case CLUTTER_TOUCHPAD_PINCH:
|
|
return "touchpad-pinch";
|
|
case CLUTTER_TOUCHPAD_SWIPE:
|
|
return "touchpad-swipe";
|
|
case CLUTTER_TOUCHPAD_HOLD:
|
|
return "touchpad-hold";
|
|
case CLUTTER_PROXIMITY_IN:
|
|
return "proximity-in";
|
|
case CLUTTER_PROXIMITY_OUT:
|
|
return "proximity-out";
|
|
case CLUTTER_PAD_BUTTON_PRESS:
|
|
return "pad-button-press";
|
|
case CLUTTER_PAD_BUTTON_RELEASE:
|
|
return "pad-button-release";
|
|
case CLUTTER_PAD_STRIP:
|
|
return "pad-strip";
|
|
case CLUTTER_PAD_RING:
|
|
return "pad-ring";
|
|
case CLUTTER_DEVICE_ADDED:
|
|
return "device-added";
|
|
case CLUTTER_DEVICE_REMOVED:
|
|
return "device-removed";
|
|
case CLUTTER_IM_COMMIT:
|
|
return "im-commit";
|
|
case CLUTTER_IM_DELETE:
|
|
return "im-delete";
|
|
case CLUTTER_IM_PREEDIT:
|
|
return "im-preedit";
|
|
case CLUTTER_NOTHING:
|
|
case CLUTTER_EVENT_LAST:
|
|
break;
|
|
}
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_key_new (ClutterEventType type,
|
|
ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterModifierSet raw_modifiers,
|
|
ClutterModifierType modifiers,
|
|
uint32_t keyval,
|
|
uint32_t evcode,
|
|
uint32_t keycode,
|
|
gunichar unicode_value)
|
|
{
|
|
ClutterEvent *event;
|
|
ClutterSeat *seat;
|
|
|
|
g_return_val_if_fail (type == CLUTTER_KEY_PRESS ||
|
|
type == CLUTTER_KEY_RELEASE, NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
|
|
event = clutter_event_new (type);
|
|
|
|
event->key.time_us = timestamp_us;
|
|
event->key.flags = flags;
|
|
event->key.raw_modifiers = raw_modifiers;
|
|
event->key.modifier_state = modifiers;
|
|
event->key.keyval = keyval;
|
|
event->key.hardware_keycode = keycode;
|
|
event->key.unicode_value = unicode_value;
|
|
event->key.evdev_code = evcode;
|
|
g_set_object (&event->key.device, clutter_seat_get_keyboard (seat));
|
|
g_set_object (&event->key.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_button_new (ClutterEventType type,
|
|
ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterInputDeviceTool *tool,
|
|
ClutterModifierType modifiers,
|
|
graphene_point_t coords,
|
|
int button,
|
|
uint32_t evcode,
|
|
double *axes)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (type == CLUTTER_BUTTON_PRESS ||
|
|
type == CLUTTER_BUTTON_RELEASE, NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
g_return_val_if_fail (!tool || CLUTTER_IS_INPUT_DEVICE_TOOL (tool), NULL);
|
|
|
|
event = clutter_event_new (type);
|
|
|
|
event->button.time_us = timestamp_us;
|
|
event->button.flags = flags;
|
|
event->button.x = coords.x;
|
|
event->button.y = coords.y;
|
|
event->button.modifier_state = modifiers;
|
|
event->button.button = button;
|
|
event->button.axes = axes;
|
|
event->button.evdev_code = evcode;
|
|
event->button.tool = tool;
|
|
|
|
g_set_object (&event->button.source_device, source_device);
|
|
|
|
if (clutter_input_device_get_device_mode (source_device) ==
|
|
CLUTTER_INPUT_MODE_FLOATING)
|
|
{
|
|
g_set_object (&event->button.device, source_device);
|
|
}
|
|
else
|
|
{
|
|
ClutterSeat *seat;
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
g_set_object (&event->button.device, clutter_seat_get_pointer (seat));
|
|
}
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_motion_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterInputDeviceTool *tool,
|
|
ClutterModifierType modifiers,
|
|
graphene_point_t coords,
|
|
graphene_point_t delta,
|
|
graphene_point_t delta_unaccel,
|
|
graphene_point_t delta_constrained,
|
|
double *axes)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
g_return_val_if_fail (!tool || CLUTTER_IS_INPUT_DEVICE_TOOL (tool), NULL);
|
|
|
|
event = clutter_event_new (CLUTTER_MOTION);
|
|
|
|
event->motion.time_us = timestamp_us;
|
|
event->motion.flags = flags;
|
|
event->motion.x = coords.x;
|
|
event->motion.y = coords.y;
|
|
event->motion.modifier_state = modifiers;
|
|
event->motion.axes = axes;
|
|
event->motion.dx = delta.x;
|
|
event->motion.dy = delta.y;
|
|
event->motion.dx_unaccel = delta_unaccel.x;
|
|
event->motion.dy_unaccel = delta_unaccel.y;
|
|
event->motion.dx_constrained = delta_constrained.x;
|
|
event->motion.dy_constrained = delta_constrained.y;
|
|
event->motion.tool = tool;
|
|
|
|
g_set_object (&event->motion.source_device, source_device);
|
|
|
|
if (clutter_input_device_get_device_mode (source_device) ==
|
|
CLUTTER_INPUT_MODE_FLOATING)
|
|
{
|
|
g_set_object (&event->motion.device, source_device);
|
|
}
|
|
else
|
|
{
|
|
ClutterSeat *seat;
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
g_set_object (&event->motion.device, clutter_seat_get_pointer (seat));
|
|
}
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_scroll_smooth_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterInputDeviceTool *tool,
|
|
ClutterModifierType modifiers,
|
|
graphene_point_t coords,
|
|
graphene_point_t delta,
|
|
ClutterScrollSource scroll_source,
|
|
ClutterScrollFinishFlags finish_flags)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
g_return_val_if_fail (!tool || CLUTTER_IS_INPUT_DEVICE_TOOL (tool), NULL);
|
|
|
|
event = clutter_event_new (CLUTTER_SCROLL);
|
|
|
|
event->scroll.time_us = timestamp_us;
|
|
event->scroll.flags = flags;
|
|
event->scroll.x = coords.x;
|
|
event->scroll.y = coords.y;
|
|
event->scroll.delta_x = delta.x;
|
|
event->scroll.delta_y = delta.y;
|
|
event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
|
|
event->scroll.modifier_state = modifiers;
|
|
event->scroll.scroll_source = scroll_source;
|
|
event->scroll.finish_flags = finish_flags;
|
|
event->scroll.tool = tool;
|
|
|
|
g_set_object (&event->scroll.source_device, source_device);
|
|
|
|
if (clutter_input_device_get_device_mode (source_device) ==
|
|
CLUTTER_INPUT_MODE_FLOATING)
|
|
{
|
|
g_set_object (&event->scroll.device, source_device);
|
|
}
|
|
else
|
|
{
|
|
ClutterSeat *seat;
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
g_set_object (&event->scroll.device, clutter_seat_get_pointer (seat));
|
|
}
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_scroll_discrete_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterInputDeviceTool *tool,
|
|
ClutterModifierType modifiers,
|
|
graphene_point_t coords,
|
|
ClutterScrollSource scroll_source,
|
|
ClutterScrollDirection direction)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
g_return_val_if_fail (!tool || CLUTTER_IS_INPUT_DEVICE_TOOL (tool), NULL);
|
|
|
|
event = clutter_event_new (CLUTTER_SCROLL);
|
|
|
|
event->scroll.time_us = timestamp_us;
|
|
event->scroll.flags = flags;
|
|
event->scroll.x = coords.x;
|
|
event->scroll.y = coords.y;
|
|
event->scroll.direction = direction;
|
|
event->scroll.scroll_source = scroll_source;
|
|
event->scroll.modifier_state = modifiers;
|
|
event->scroll.tool = tool;
|
|
|
|
g_set_object (&event->scroll.source_device, source_device);
|
|
|
|
if (clutter_input_device_get_device_mode (source_device) ==
|
|
CLUTTER_INPUT_MODE_FLOATING)
|
|
{
|
|
g_set_object (&event->scroll.device, source_device);
|
|
}
|
|
else
|
|
{
|
|
ClutterSeat *seat;
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
g_set_object (&event->scroll.device, clutter_seat_get_pointer (seat));
|
|
}
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_crossing_new (ClutterEventType type,
|
|
ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterEventSequence *sequence,
|
|
graphene_point_t coords,
|
|
ClutterActor *source,
|
|
ClutterActor *related)
|
|
{
|
|
ClutterInputDevice *device;
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (type == CLUTTER_ENTER ||
|
|
type == CLUTTER_LEAVE, NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
if (clutter_input_device_get_device_mode (source_device) ==
|
|
CLUTTER_INPUT_MODE_FLOATING)
|
|
{
|
|
device = source_device;
|
|
}
|
|
else
|
|
{
|
|
ClutterSeat *seat;
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
device = clutter_seat_get_pointer (seat);
|
|
}
|
|
|
|
event = clutter_event_new (type);
|
|
|
|
event->crossing.time_us = timestamp_us;
|
|
event->crossing.flags = flags;
|
|
event->crossing.x = coords.x;
|
|
event->crossing.y = coords.y;
|
|
event->crossing.sequence = sequence;
|
|
event->crossing.source = source;
|
|
event->crossing.related = related;
|
|
g_set_object (&event->crossing.device, device);
|
|
g_set_object (&event->crossing.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_touch_new (ClutterEventType type,
|
|
ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterEventSequence *sequence,
|
|
ClutterModifierType modifiers,
|
|
graphene_point_t coords)
|
|
{
|
|
ClutterEvent *event;
|
|
ClutterSeat *seat;
|
|
|
|
g_return_val_if_fail (type == CLUTTER_TOUCH_BEGIN ||
|
|
type == CLUTTER_TOUCH_UPDATE ||
|
|
type == CLUTTER_TOUCH_END, NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
g_return_val_if_fail (sequence != NULL, NULL);
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
|
|
event = clutter_event_new (type);
|
|
|
|
event->touch.time_us = timestamp_us;
|
|
event->touch.flags = flags;
|
|
event->touch.x = coords.x;
|
|
event->touch.y = coords.y;
|
|
event->touch.modifier_state = modifiers;
|
|
event->touch.sequence = sequence;
|
|
|
|
/* This has traditionally been the virtual pointer device */
|
|
g_set_object (&event->touch.device, clutter_seat_get_pointer (seat));
|
|
g_set_object (&event->touch.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_touch_cancel_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterEventSequence *sequence)
|
|
{
|
|
ClutterEvent *event;
|
|
ClutterSeat *seat;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
g_return_val_if_fail (sequence != NULL, NULL);
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
|
|
event = clutter_event_new (CLUTTER_TOUCH_CANCEL);
|
|
|
|
event->touch.time_us = timestamp_us;
|
|
event->touch.flags = flags;
|
|
event->touch.sequence = sequence;
|
|
|
|
/* This has traditionally been the virtual pointer device */
|
|
g_set_object (&event->touch.device, clutter_seat_get_pointer (seat));
|
|
g_set_object (&event->touch.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_proximity_new (ClutterEventType type,
|
|
ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterInputDeviceTool *tool)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (type == CLUTTER_PROXIMITY_IN ||
|
|
type == CLUTTER_PROXIMITY_OUT, NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), NULL);
|
|
|
|
event = clutter_event_new (type);
|
|
|
|
event->proximity.time_us = timestamp_us;
|
|
event->proximity.flags = flags;
|
|
event->proximity.tool = tool;
|
|
|
|
g_set_object (&event->proximity.device, source_device);
|
|
g_set_object (&event->proximity.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_touchpad_pinch_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterTouchpadGesturePhase phase,
|
|
uint32_t fingers,
|
|
graphene_point_t coords,
|
|
graphene_point_t delta,
|
|
graphene_point_t delta_unaccel,
|
|
float angle,
|
|
float scale)
|
|
{
|
|
ClutterEvent *event;
|
|
ClutterSeat *seat;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
|
|
event = clutter_event_new (CLUTTER_TOUCHPAD_PINCH);
|
|
|
|
event->touchpad_pinch.time_us = timestamp_us;
|
|
event->touchpad_pinch.flags = flags;
|
|
event->touchpad_pinch.phase = phase;
|
|
event->touchpad_pinch.x = coords.x;
|
|
event->touchpad_pinch.y = coords.y;
|
|
event->touchpad_pinch.dx = delta.x;
|
|
event->touchpad_pinch.dy = delta.y;
|
|
event->touchpad_pinch.dx_unaccel = delta_unaccel.x;
|
|
event->touchpad_pinch.dy_unaccel = delta_unaccel.y;
|
|
event->touchpad_pinch.angle_delta = angle;
|
|
event->touchpad_pinch.scale = scale;
|
|
event->touchpad_pinch.n_fingers = fingers;
|
|
|
|
g_set_object (&event->touchpad_pinch.device, clutter_seat_get_pointer (seat));
|
|
g_set_object (&event->touchpad_pinch.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_touchpad_swipe_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterTouchpadGesturePhase phase,
|
|
uint32_t fingers,
|
|
graphene_point_t coords,
|
|
graphene_point_t delta,
|
|
graphene_point_t delta_unaccel)
|
|
{
|
|
ClutterEvent *event;
|
|
ClutterSeat *seat;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
|
|
event = clutter_event_new (CLUTTER_TOUCHPAD_SWIPE);
|
|
|
|
event->touchpad_swipe.time_us = timestamp_us;
|
|
event->touchpad_swipe.flags = flags;
|
|
event->touchpad_swipe.phase = phase;
|
|
event->touchpad_swipe.x = coords.x;
|
|
event->touchpad_swipe.y = coords.y;
|
|
event->touchpad_swipe.dx = delta.x;
|
|
event->touchpad_swipe.dy = delta.y;
|
|
event->touchpad_swipe.dx_unaccel = delta_unaccel.x;
|
|
event->touchpad_swipe.dy_unaccel = delta_unaccel.y;
|
|
event->touchpad_swipe.n_fingers = fingers;
|
|
|
|
g_set_object (&event->touchpad_swipe.device, clutter_seat_get_pointer (seat));
|
|
g_set_object (&event->touchpad_swipe.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_touchpad_hold_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterTouchpadGesturePhase phase,
|
|
uint32_t fingers,
|
|
graphene_point_t coords)
|
|
{
|
|
ClutterEvent *event;
|
|
ClutterSeat *seat;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
seat = clutter_input_device_get_seat (source_device);
|
|
|
|
event = clutter_event_new (CLUTTER_TOUCHPAD_HOLD);
|
|
|
|
event->touchpad_hold.time_us = timestamp_us;
|
|
event->touchpad_hold.flags = flags;
|
|
event->touchpad_hold.phase = phase;
|
|
event->touchpad_hold.x = coords.x;
|
|
event->touchpad_hold.y = coords.y;
|
|
event->touchpad_hold.n_fingers = fingers;
|
|
|
|
g_set_object (&event->touchpad_hold.device, clutter_seat_get_pointer (seat));
|
|
g_set_object (&event->touchpad_hold.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_pad_button_new (ClutterEventType type,
|
|
ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
uint32_t button,
|
|
uint32_t group,
|
|
uint32_t mode)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (type == CLUTTER_PAD_BUTTON_PRESS ||
|
|
type == CLUTTER_PAD_BUTTON_RELEASE, NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
event = clutter_event_new (type);
|
|
|
|
event->pad_button.time_us = timestamp_us;
|
|
event->pad_button.flags = flags;
|
|
event->pad_button.button = button;
|
|
event->pad_button.group = group;
|
|
event->pad_button.mode = mode;
|
|
|
|
g_set_object (&event->pad_button.device, source_device);
|
|
g_set_object (&event->pad_button.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_pad_strip_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterInputDevicePadSource strip_source,
|
|
uint32_t strip,
|
|
uint32_t group,
|
|
double value,
|
|
uint32_t mode)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
event = clutter_event_new (CLUTTER_PAD_STRIP);
|
|
|
|
event->pad_strip.time_us = timestamp_us;
|
|
event->pad_strip.flags = flags;
|
|
event->pad_strip.strip_source = strip_source;
|
|
event->pad_strip.strip_number = strip;
|
|
event->pad_strip.group = group;
|
|
event->pad_strip.value = value;
|
|
event->pad_strip.mode = mode;
|
|
|
|
g_set_object (&event->pad_strip.device, source_device);
|
|
g_set_object (&event->pad_strip.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_pad_ring_new (ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device,
|
|
ClutterInputDevicePadSource ring_source,
|
|
uint32_t ring,
|
|
uint32_t group,
|
|
double angle,
|
|
uint32_t mode)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
event = clutter_event_new (CLUTTER_PAD_RING);
|
|
|
|
event->pad_ring.time_us = timestamp_us;
|
|
event->pad_ring.flags = flags;
|
|
event->pad_ring.ring_source = ring_source;
|
|
event->pad_ring.ring_number = ring;
|
|
event->pad_ring.group = group;
|
|
event->pad_ring.angle = angle;
|
|
event->pad_ring.mode = mode;
|
|
|
|
g_set_object (&event->pad_ring.device, source_device);
|
|
g_set_object (&event->pad_ring.source_device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_device_notify_new (ClutterEventType type,
|
|
ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterInputDevice *source_device)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (type == CLUTTER_DEVICE_ADDED ||
|
|
type == CLUTTER_DEVICE_REMOVED, NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (source_device), NULL);
|
|
|
|
event = clutter_event_new (type);
|
|
|
|
event->device.time_us = timestamp_us;
|
|
event->device.flags = flags;
|
|
|
|
g_set_object (&event->device.device, source_device);
|
|
|
|
return event;
|
|
}
|
|
|
|
ClutterEvent *
|
|
clutter_event_im_new (ClutterEventType type,
|
|
ClutterEventFlags flags,
|
|
int64_t timestamp_us,
|
|
ClutterSeat *seat,
|
|
const char *text,
|
|
int32_t offset,
|
|
int32_t anchor,
|
|
uint32_t len,
|
|
ClutterPreeditResetMode mode)
|
|
{
|
|
ClutterEvent *event;
|
|
|
|
g_return_val_if_fail (type == CLUTTER_IM_COMMIT ||
|
|
type == CLUTTER_IM_DELETE ||
|
|
type == CLUTTER_IM_PREEDIT, NULL);
|
|
|
|
event = clutter_event_new (type);
|
|
|
|
event->im.time_us = timestamp_us;
|
|
event->im.flags = flags;
|
|
event->im.text = g_strdup (text);
|
|
event->im.offset = offset;
|
|
event->im.anchor = anchor;
|
|
event->im.len = len;
|
|
event->im.mode = mode;
|
|
|
|
g_set_object (&event->im.device, clutter_seat_get_keyboard (seat));
|
|
|
|
return event;
|
|
}
|
|
|
|
static const char *
|
|
scroll_source_to_string (ClutterScrollSource scroll_source)
|
|
{
|
|
switch (scroll_source)
|
|
{
|
|
case CLUTTER_SCROLL_SOURCE_UNKNOWN:
|
|
return "unknown";
|
|
case CLUTTER_SCROLL_SOURCE_WHEEL:
|
|
return "wheel";
|
|
case CLUTTER_SCROLL_SOURCE_FINGER:
|
|
return "finger";
|
|
case CLUTTER_SCROLL_SOURCE_CONTINUOUS:
|
|
return "continuous";
|
|
}
|
|
g_return_val_if_reached ("");
|
|
}
|
|
|
|
static const char *
|
|
touchpad_gesture_phase_to_string (ClutterTouchpadGesturePhase phase)
|
|
{
|
|
switch (phase)
|
|
{
|
|
case CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN:
|
|
return "begin";
|
|
case CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE:
|
|
return "update";
|
|
case CLUTTER_TOUCHPAD_GESTURE_PHASE_END:
|
|
return "end";
|
|
case CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL:
|
|
return "cancel";
|
|
}
|
|
g_return_val_if_reached ("");
|
|
}
|
|
|
|
static const char *
|
|
pad_source_to_string (ClutterInputDevicePadSource pad_source)
|
|
{
|
|
switch (pad_source)
|
|
{
|
|
case CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN:
|
|
return "unknown";
|
|
case CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER:
|
|
return "finger";
|
|
}
|
|
g_return_val_if_reached ("");
|
|
}
|
|
|
|
static const char *
|
|
scroll_direction_to_string (ClutterScrollDirection scroll_direction)
|
|
{
|
|
switch (scroll_direction)
|
|
{
|
|
case CLUTTER_SCROLL_SMOOTH:
|
|
g_warn_if_reached ();
|
|
return "";
|
|
case CLUTTER_SCROLL_LEFT:
|
|
return "left";
|
|
case CLUTTER_SCROLL_RIGHT:
|
|
return "right";
|
|
case CLUTTER_SCROLL_UP:
|
|
return "up";
|
|
case CLUTTER_SCROLL_DOWN:
|
|
return "down";
|
|
}
|
|
g_return_val_if_reached ("");
|
|
}
|
|
|
|
static char *
|
|
generate_event_description (const ClutterEvent *event)
|
|
{
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_KEY_PRESS:
|
|
case CLUTTER_KEY_RELEASE:
|
|
if (g_strcmp0 (g_getenv ("MUTTER_DEBUG_LOG_KEYCODES"), "1") == 0)
|
|
{
|
|
char unicode[7] = {};
|
|
|
|
if (event->key.unicode_value)
|
|
g_unichar_to_utf8 (event->key.unicode_value, unicode);
|
|
return g_strdup_printf ("keycode=%u, evdev=%u, "
|
|
"keysym=%u, unicode='%s'",
|
|
event->key.hardware_keycode,
|
|
event->key.evdev_code,
|
|
event->key.keyval,
|
|
event->key.unicode_value ? unicode : "N\\A");
|
|
}
|
|
else
|
|
{
|
|
return g_strdup ("(hidden)");
|
|
}
|
|
case CLUTTER_MOTION:
|
|
return g_strdup_printf ("abs=(%f, %f), rel=(%f, %f), unaccel-rel=(%f, %f)",
|
|
event->motion.x,
|
|
event->motion.y,
|
|
event->motion.dx,
|
|
event->motion.dy,
|
|
event->motion.dx_unaccel,
|
|
event->motion.dy_unaccel);
|
|
case CLUTTER_BUTTON_PRESS:
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
return g_strdup_printf ("button=%u, evdev=%u",
|
|
event->button.button,
|
|
event->button.evdev_code);
|
|
case CLUTTER_SCROLL:
|
|
if (event->scroll.direction == CLUTTER_SCROLL_SMOOTH)
|
|
{
|
|
double dx, dy;
|
|
ClutterScrollSource scroll_source;
|
|
|
|
clutter_event_get_scroll_delta (event, &dx, &dy);
|
|
scroll_source = event->scroll.scroll_source;
|
|
return g_strdup_printf ("source=%s, rel: (%f, %f)",
|
|
scroll_source_to_string (scroll_source),
|
|
dx, dy);
|
|
}
|
|
else
|
|
{
|
|
ClutterScrollDirection direction = event->scroll.direction;
|
|
|
|
return g_strdup_printf ("direction=%s",
|
|
scroll_direction_to_string (direction));
|
|
}
|
|
case CLUTTER_TOUCH_BEGIN:
|
|
case CLUTTER_TOUCH_UPDATE:
|
|
case CLUTTER_TOUCH_END:
|
|
case CLUTTER_TOUCH_CANCEL:
|
|
return g_strdup_printf ("slot=%d, abs=(%f, %f)",
|
|
GPOINTER_TO_INT (event->touch.sequence),
|
|
event->touch.x,
|
|
event->touch.y);
|
|
case CLUTTER_TOUCHPAD_PINCH:
|
|
return g_strdup_printf ("phase=%s, rel=(%f, %f), unaccel-rel=(%f, %f), "
|
|
"angle-delta=%f, scale=%f, n-fingers=%d",
|
|
touchpad_gesture_phase_to_string (event->touchpad_pinch.phase),
|
|
event->touchpad_pinch.dx,
|
|
event->touchpad_pinch.dy,
|
|
event->touchpad_pinch.dx_unaccel,
|
|
event->touchpad_pinch.dy_unaccel,
|
|
event->touchpad_pinch.angle_delta,
|
|
event->touchpad_pinch.scale,
|
|
event->touchpad_pinch.n_fingers);
|
|
case CLUTTER_TOUCHPAD_SWIPE:
|
|
return g_strdup_printf ("phase=%s, rel=(%f, %f), unaccel-rel=(%f, %f), "
|
|
"n-fingers=%d",
|
|
touchpad_gesture_phase_to_string (event->touchpad_pinch.phase),
|
|
event->touchpad_swipe.dx,
|
|
event->touchpad_swipe.dy,
|
|
event->touchpad_swipe.dx_unaccel,
|
|
event->touchpad_swipe.dy_unaccel,
|
|
event->touchpad_swipe.n_fingers);
|
|
case CLUTTER_TOUCHPAD_HOLD:
|
|
return g_strdup_printf ("phase=%s, n-fingers=%d",
|
|
touchpad_gesture_phase_to_string (event->touchpad_pinch.phase),
|
|
event->touchpad_hold.n_fingers);
|
|
case CLUTTER_PROXIMITY_IN:
|
|
case CLUTTER_PROXIMITY_OUT:
|
|
return g_strdup ("");
|
|
case CLUTTER_PAD_BUTTON_PRESS:
|
|
case CLUTTER_PAD_BUTTON_RELEASE:
|
|
return g_strdup_printf ("button=%u, group=%u, mode=%u",
|
|
event->pad_button.button,
|
|
event->pad_button.group,
|
|
event->pad_button.mode);
|
|
case CLUTTER_PAD_STRIP:
|
|
return g_strdup_printf ("source=%s (%d), value=%f, group=%u, mode=%u",
|
|
pad_source_to_string (event->pad_strip.strip_source),
|
|
event->pad_strip.strip_number,
|
|
event->pad_strip.value,
|
|
event->pad_strip.group,
|
|
event->pad_strip.mode);
|
|
case CLUTTER_PAD_RING:
|
|
return g_strdup_printf ("source=%s (%d), angle=%f, group=%u, mode=%u",
|
|
pad_source_to_string (event->pad_ring.ring_source),
|
|
event->pad_ring.ring_number,
|
|
event->pad_ring.angle,
|
|
event->pad_ring.group,
|
|
event->pad_ring.mode);
|
|
case CLUTTER_DEVICE_ADDED:
|
|
case CLUTTER_DEVICE_REMOVED:
|
|
{
|
|
ClutterInputDevice *device;
|
|
|
|
device = clutter_event_get_device (event);
|
|
return g_strdup_printf ("%s (%s)",
|
|
clutter_input_device_get_device_name (device),
|
|
clutter_input_device_get_device_node (device));
|
|
}
|
|
default:
|
|
g_warn_if_reached ();
|
|
return g_strdup ("");
|
|
}
|
|
}
|
|
|
|
static char *
|
|
generate_modifiers_description (const ClutterEvent *event)
|
|
{
|
|
ClutterModifierType modifiers;
|
|
GString *str;
|
|
|
|
modifiers = clutter_event_get_state (event);
|
|
|
|
if (modifiers == 0)
|
|
return g_strdup ("none");
|
|
|
|
str = g_string_new (NULL);
|
|
|
|
if (modifiers & CLUTTER_SHIFT_MASK)
|
|
g_string_append (str, "shift ");
|
|
if (modifiers & CLUTTER_LOCK_MASK)
|
|
g_string_append (str, "lock ");
|
|
if (modifiers & CLUTTER_CONTROL_MASK)
|
|
g_string_append (str, "control ");
|
|
if (modifiers & CLUTTER_MOD1_MASK)
|
|
g_string_append (str, "mod1 ");
|
|
if (modifiers & CLUTTER_MOD2_MASK)
|
|
g_string_append (str, "mod2 ");
|
|
if (modifiers & CLUTTER_MOD3_MASK)
|
|
g_string_append (str, "mod3 ");
|
|
if (modifiers & CLUTTER_MOD4_MASK)
|
|
g_string_append (str, "mod4 ");
|
|
if (modifiers & CLUTTER_MOD5_MASK)
|
|
g_string_append (str, "mod5 ");
|
|
if (modifiers & CLUTTER_BUTTON1_MASK)
|
|
g_string_append (str, "button1 ");
|
|
if (modifiers & CLUTTER_BUTTON2_MASK)
|
|
g_string_append (str, "button2 ");
|
|
if (modifiers & CLUTTER_BUTTON3_MASK)
|
|
g_string_append (str, "button3 ");
|
|
if (modifiers & CLUTTER_BUTTON4_MASK)
|
|
g_string_append (str, "button4 ");
|
|
if (modifiers & CLUTTER_BUTTON5_MASK)
|
|
g_string_append (str, "button5 ");
|
|
if (modifiers & CLUTTER_SUPER_MASK)
|
|
g_string_append (str, "super ");
|
|
if (modifiers & CLUTTER_HYPER_MASK)
|
|
g_string_append (str, "hyper ");
|
|
if (modifiers & CLUTTER_META_MASK)
|
|
g_string_append (str, "meta ");
|
|
if (modifiers & CLUTTER_RELEASE_MASK)
|
|
g_string_append (str, "release ");
|
|
|
|
/* Delete trailing space */
|
|
g_string_erase (str, str->len - 1, 1);
|
|
|
|
return g_string_free_and_steal (str);
|
|
}
|
|
|
|
char *
|
|
clutter_event_describe (const ClutterEvent *event)
|
|
{
|
|
g_autofree char *event_description = NULL;
|
|
g_autofree char *modifiers_description = NULL;
|
|
ClutterInputDevice *source_device;
|
|
|
|
source_device = clutter_event_get_source_device (event);
|
|
event_description = generate_event_description (event);
|
|
modifiers_description = generate_modifiers_description (event);
|
|
|
|
return g_strdup_printf ("'%s'%s%s, time=%" G_GINT64_FORMAT " us, modifiers=%s, %s",
|
|
clutter_event_get_name (event),
|
|
source_device ? " from " : "",
|
|
source_device ?
|
|
clutter_input_device_get_device_node (source_device) :
|
|
"",
|
|
event->any.time_us,
|
|
modifiers_description,
|
|
event_description);
|
|
}
|