mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 04:22:05 +00:00
Merge branch 'device-manager'
* device-manager: (37 commits) x11: Re-enable XI1 extension keyboards x11: Always handle core device events before XI events docs: Documentation fixes for DeviceManager device-manager: Fix the signals definition docs: Add sections for InputDevice and DeviceManager docs: Add clutter_input_device_get_device_name() tests: Print out the device details on motion Always register core devices device: Remove unused is_default member win32: Experimental implementation of device support tests: Print the device name, as well as its Id x11: Fill out the :name property of the InputDevices device: Add the :name property to InputDevice x11: Store core devices on the X11 Backend singleton device: Unset the cursor actor when leaving the stage device: Add pointer actor getter x11: Discard the LeaveNotify for off-stage ButtonRelease device: Do not overwrite the stage for an InputDevice event: Off-stage button releases have a click count of 1 event: Scroll events do not have click count ...
This commit is contained in:
commit
5f1c8a17e4
@ -84,6 +84,7 @@ source_h = \
|
|||||||
$(srcdir)/clutter-color.h \
|
$(srcdir)/clutter-color.h \
|
||||||
$(srcdir)/clutter-container.h \
|
$(srcdir)/clutter-container.h \
|
||||||
$(srcdir)/clutter-deprecated.h \
|
$(srcdir)/clutter-deprecated.h \
|
||||||
|
$(srcdir)/clutter-device-manager.h \
|
||||||
$(srcdir)/clutter-event.h \
|
$(srcdir)/clutter-event.h \
|
||||||
$(srcdir)/clutter-feature.h \
|
$(srcdir)/clutter-feature.h \
|
||||||
$(srcdir)/clutter-fixed.h \
|
$(srcdir)/clutter-fixed.h \
|
||||||
@ -91,6 +92,7 @@ source_h = \
|
|||||||
$(srcdir)/clutter-flow-layout.h \
|
$(srcdir)/clutter-flow-layout.h \
|
||||||
$(srcdir)/clutter-frame-source.h \
|
$(srcdir)/clutter-frame-source.h \
|
||||||
$(srcdir)/clutter-group.h \
|
$(srcdir)/clutter-group.h \
|
||||||
|
$(srcdir)/clutter-input-device.h \
|
||||||
$(srcdir)/clutter-interval.h \
|
$(srcdir)/clutter-interval.h \
|
||||||
$(srcdir)/clutter-keysyms.h \
|
$(srcdir)/clutter-keysyms.h \
|
||||||
$(srcdir)/clutter-layout-manager.h \
|
$(srcdir)/clutter-layout-manager.h \
|
||||||
@ -154,6 +156,7 @@ source_c = \
|
|||||||
$(srcdir)/clutter-clone.c \
|
$(srcdir)/clutter-clone.c \
|
||||||
$(srcdir)/clutter-color.c \
|
$(srcdir)/clutter-color.c \
|
||||||
$(srcdir)/clutter-container.c \
|
$(srcdir)/clutter-container.c \
|
||||||
|
$(srcdir)/clutter-device-manager.c \
|
||||||
clutter-enum-types.c \
|
clutter-enum-types.c \
|
||||||
$(srcdir)/clutter-event.c \
|
$(srcdir)/clutter-event.c \
|
||||||
$(srcdir)/clutter-feature.c \
|
$(srcdir)/clutter-feature.c \
|
||||||
@ -162,6 +165,7 @@ source_c = \
|
|||||||
$(srcdir)/clutter-flow-layout.c \
|
$(srcdir)/clutter-flow-layout.c \
|
||||||
$(srcdir)/clutter-frame-source.c \
|
$(srcdir)/clutter-frame-source.c \
|
||||||
$(srcdir)/clutter-group.c \
|
$(srcdir)/clutter-group.c \
|
||||||
|
$(srcdir)/clutter-input-device.c \
|
||||||
$(srcdir)/clutter-interval.c \
|
$(srcdir)/clutter-interval.c \
|
||||||
$(srcdir)/clutter-layout-manager.c \
|
$(srcdir)/clutter-layout-manager.c \
|
||||||
$(srcdir)/clutter-layout-meta.c \
|
$(srcdir)/clutter-layout-meta.c \
|
||||||
|
@ -308,6 +308,7 @@ struct _ClutterActorPrivate
|
|||||||
guint clip_to_allocation : 1;
|
guint clip_to_allocation : 1;
|
||||||
guint enable_model_view_transform : 1;
|
guint enable_model_view_transform : 1;
|
||||||
guint enable_paint_unmapped : 1;
|
guint enable_paint_unmapped : 1;
|
||||||
|
guint has_pointer : 1;
|
||||||
|
|
||||||
gfloat clip[4];
|
gfloat clip[4];
|
||||||
|
|
||||||
@ -429,7 +430,8 @@ enum
|
|||||||
|
|
||||||
PROP_SHOW_ON_SET_PARENT,
|
PROP_SHOW_ON_SET_PARENT,
|
||||||
|
|
||||||
PROP_TEXT_DIRECTION
|
PROP_TEXT_DIRECTION,
|
||||||
|
PROP_HAS_POINTER
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -3031,6 +3033,10 @@ clutter_actor_get_property (GObject *object,
|
|||||||
g_value_set_enum (value, priv->text_direction);
|
g_value_set_enum (value, priv->text_direction);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_HAS_POINTER:
|
||||||
|
g_value_set_boolean (value, priv->has_pointer);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -3858,6 +3864,24 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||||||
PROP_TEXT_DIRECTION,
|
PROP_TEXT_DIRECTION,
|
||||||
pspec);
|
pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterActor:has-pointer:
|
||||||
|
*
|
||||||
|
* Whether the actor contains the pointer of a #ClutterInputDevice
|
||||||
|
* or not.
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_boolean ("has-pointer",
|
||||||
|
"Has Pointer",
|
||||||
|
"Whether the actor contains the pointer "
|
||||||
|
"of an input device",
|
||||||
|
FALSE,
|
||||||
|
CLUTTER_PARAM_READABLE);
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_HAS_POINTER,
|
||||||
|
pspec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterActor::destroy:
|
* ClutterActor::destroy:
|
||||||
* @actor: the object which received the signal
|
* @actor: the object which received the signal
|
||||||
@ -9638,6 +9662,20 @@ clutter_actor_set_text_direction (ClutterActor *self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_actor_set_has_pointer (ClutterActor *self,
|
||||||
|
gboolean has_pointer)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->has_pointer != has_pointer)
|
||||||
|
{
|
||||||
|
priv->has_pointer = has_pointer;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (self), "has-pointer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_actor_get_text_direction:
|
* clutter_actor_get_text_direction:
|
||||||
* @self: a #ClutterActor
|
* @self: a #ClutterActor
|
||||||
@ -9748,3 +9786,23 @@ clutter_actor_pop_internal (void)
|
|||||||
|
|
||||||
ctx->internal_child -= 1;
|
ctx->internal_child -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_actor_has_pointer:
|
||||||
|
* @self: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Checks whether an actor contains the the pointer of a
|
||||||
|
* #ClutterInputDevice
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the actor contains the pointer, and
|
||||||
|
* %FALSE otherwise
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
clutter_actor_has_pointer (ClutterActor *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||||
|
|
||||||
|
return self->priv->has_pointer;
|
||||||
|
}
|
||||||
|
@ -532,6 +532,7 @@ void clutter_actor_get_transformation_matrix (ClutterActor *self
|
|||||||
CoglMatrix *matrix);
|
CoglMatrix *matrix);
|
||||||
|
|
||||||
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
|
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
|
||||||
|
gboolean clutter_actor_has_pointer (ClutterActor *self);
|
||||||
|
|
||||||
void clutter_actor_set_text_direction (ClutterActor *self,
|
void clutter_actor_set_text_direction (ClutterActor *self,
|
||||||
ClutterTextDirection text_dir);
|
ClutterTextDirection text_dir);
|
||||||
|
321
clutter/clutter-device-manager.c
Normal file
321
clutter/clutter-device-manager.c
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corp.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:clutter-device-manager
|
||||||
|
* @short_description: Maintains the list of input devices
|
||||||
|
*
|
||||||
|
* #ClutterDeviceManager is a singleton object, owned by Clutter, which
|
||||||
|
* maintains the list of #ClutterInputDevice<!-- -->s.
|
||||||
|
*
|
||||||
|
* Depending on the backend used by Clutter it is possible to use the
|
||||||
|
* #ClutterDeviceManager::device-added and
|
||||||
|
* #ClutterDeviceManager::device-removed to monitor addition and removal
|
||||||
|
* of devices.
|
||||||
|
*
|
||||||
|
* #ClutterDeviceManager is available since Clutter 1.2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-debug.h"
|
||||||
|
#include "clutter-device-manager.h"
|
||||||
|
#include "clutter-enum-types.h"
|
||||||
|
#include "clutter-marshal.h"
|
||||||
|
#include "clutter-private.h"
|
||||||
|
|
||||||
|
#define CLUTTER_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManagerClass))
|
||||||
|
#define CLUTTER_IS_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER))
|
||||||
|
#define CLUTTER_DEVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManagerClass))
|
||||||
|
|
||||||
|
typedef struct _ClutterDeviceManagerClass ClutterDeviceManagerClass;
|
||||||
|
|
||||||
|
struct _ClutterDeviceManagerClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEVICE_ADDED,
|
||||||
|
DEVICE_REMOVED,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static ClutterDeviceManager *default_manager = NULL;
|
||||||
|
|
||||||
|
static guint manager_signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterDeviceManager, clutter_device_manager, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_device_manager_class_init (ClutterDeviceManagerClass *klass)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ClutterDeviceManager::device-added:
|
||||||
|
* @manager: the #ClutterDeviceManager that emitted the signal
|
||||||
|
* @device: the newly added #ClutterInputDevice
|
||||||
|
*
|
||||||
|
* The ::device-added signal is emitted each time a device has been
|
||||||
|
* added to the #ClutterDeviceManager
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
manager_signals[DEVICE_ADDED] =
|
||||||
|
g_signal_new (I_("device-added"),
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
clutter_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
CLUTTER_TYPE_INPUT_DEVICE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterDeviceManager::device-removed:
|
||||||
|
* @manager: the #ClutterDeviceManager that emitted the signal
|
||||||
|
* @device: the removed #ClutterInputDevice
|
||||||
|
*
|
||||||
|
* The ::device-removed signal is emitted each time a device has been
|
||||||
|
* removed from the #ClutterDeviceManager
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
manager_signals[DEVICE_REMOVED] =
|
||||||
|
g_signal_new (I_("device-removed"),
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
clutter_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
CLUTTER_TYPE_INPUT_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_device_manager_init (ClutterDeviceManager *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_device_manager_get_default:
|
||||||
|
*
|
||||||
|
* Retrieves the device manager singleton
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): the #ClutterDeviceManager singleton.
|
||||||
|
* The returned instance is owned by Clutter and it should not be
|
||||||
|
* modified or freed
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
ClutterDeviceManager *
|
||||||
|
clutter_device_manager_get_default (void)
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (default_manager == NULL))
|
||||||
|
default_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER, NULL);
|
||||||
|
|
||||||
|
return default_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_device_manager_list_devices:
|
||||||
|
* @device_manager: a #ClutterDeviceManager
|
||||||
|
*
|
||||||
|
* Lists all currently registered input devices
|
||||||
|
*
|
||||||
|
* Return value: (transfer container) (element-type ClutterInputDevice):
|
||||||
|
* a newly allocated list of #ClutterInputDevice objects. Use
|
||||||
|
* g_slist_free() to deallocate it when done
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
GSList *
|
||||||
|
clutter_device_manager_list_devices (ClutterDeviceManager *device_manager)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
|
||||||
|
|
||||||
|
return g_slist_copy (device_manager->devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_device_manager_peek_devices:
|
||||||
|
* @device_manager: a #ClutterDeviceManager
|
||||||
|
*
|
||||||
|
* Lists all currently registered input devices
|
||||||
|
*
|
||||||
|
* Return value: (transfer none) (element-type ClutterInputDevice):
|
||||||
|
* a pointer to the internal list of #ClutterInputDevice objects. The
|
||||||
|
* returned list is owned by the #ClutterDeviceManager and should never
|
||||||
|
* be modified or freed
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
const GSList *
|
||||||
|
clutter_device_manager_peek_devices (ClutterDeviceManager *device_manager)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
|
||||||
|
|
||||||
|
return device_manager->devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_device_manager_get_device:
|
||||||
|
* @device_manager: a #ClutterDeviceManager
|
||||||
|
* @device_id: the integer id of a device
|
||||||
|
*
|
||||||
|
* Retrieves the #ClutterInputDevice with the given @device_id
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): a #ClutterInputDevice or %NULL. The
|
||||||
|
* returned device is owned by the #ClutterDeviceManager and should
|
||||||
|
* never be modified or freed
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
ClutterInputDevice *
|
||||||
|
clutter_device_manager_get_device (ClutterDeviceManager *device_manager,
|
||||||
|
gint device_id)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
|
||||||
|
|
||||||
|
for (l = device_manager->devices; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
ClutterInputDevice *device = l->data;
|
||||||
|
|
||||||
|
if (device->id == device_id)
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
input_device_cmp (gconstpointer a,
|
||||||
|
gconstpointer b)
|
||||||
|
{
|
||||||
|
const ClutterInputDevice *device_a = a;
|
||||||
|
const ClutterInputDevice *device_b = b;
|
||||||
|
|
||||||
|
if (device_a->id < device_b->id)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (device_a->id > device_b->id)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_device_manager_add_device:
|
||||||
|
* @device_manager: a #ClutterDeviceManager
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
*
|
||||||
|
* Adds @device to the list of #ClutterInputDevice<!-- -->s maintained
|
||||||
|
* by @device_manager
|
||||||
|
*
|
||||||
|
* The reference count of @device is not increased
|
||||||
|
*
|
||||||
|
* The #ClutterDeviceManager::device-added signal is emitted after
|
||||||
|
* adding @device to the list
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
|
||||||
|
ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
|
||||||
|
|
||||||
|
device_manager->devices = g_slist_insert_sorted (device_manager->devices,
|
||||||
|
device,
|
||||||
|
input_device_cmp);
|
||||||
|
|
||||||
|
g_signal_emit (device_manager, manager_signals[DEVICE_ADDED], 0, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_device_manager_remove_device:
|
||||||
|
* @device_manager: a #ClutterDeviceManager
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
*
|
||||||
|
* Removes @device from the list of #ClutterInputDevice<!-- -->s
|
||||||
|
* maintained by @device_manager
|
||||||
|
*
|
||||||
|
* The reference count of @device is not decreased
|
||||||
|
*
|
||||||
|
* The #ClutterDeviceManager::device-removed signal is emitted after
|
||||||
|
* removing @device from the list
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
|
||||||
|
ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
|
||||||
|
|
||||||
|
if (g_slist_find (device_manager->devices, device) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
device_manager->devices = g_slist_remove (device_manager->devices, device);
|
||||||
|
|
||||||
|
g_signal_emit (device_manager, manager_signals[DEVICE_REMOVED], 0, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_device_manager_update_devices:
|
||||||
|
* @device_manager: a #ClutterDeviceManager
|
||||||
|
*
|
||||||
|
* Updates every #ClutterInputDevice handled by @device_manager
|
||||||
|
* by performing a pick paint at the coordinates of each pointer
|
||||||
|
* device
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_device_manager_update_devices (ClutterDeviceManager *device_manager)
|
||||||
|
{
|
||||||
|
GSList *d;
|
||||||
|
|
||||||
|
/* the user disabled motion events delivery on actors; we
|
||||||
|
* don't perform any picking since the source of the events
|
||||||
|
* will always be set to be the stage
|
||||||
|
*/
|
||||||
|
if (!clutter_get_motion_events_enabled ())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (d = device_manager->devices; d != NULL; d = d->next)
|
||||||
|
{
|
||||||
|
ClutterInputDevice *device = d->data;
|
||||||
|
ClutterInputDeviceType device_type;
|
||||||
|
|
||||||
|
/* we only care about pointer devices */
|
||||||
|
device_type = clutter_input_device_get_device_type (device);
|
||||||
|
if (device_type != CLUTTER_POINTER_DEVICE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* out of stage */
|
||||||
|
if (device->stage == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_clutter_input_device_update (device);
|
||||||
|
}
|
||||||
|
}
|
59
clutter/clutter-device-manager.h
Normal file
59
clutter/clutter-device-manager.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corp.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||||
|
#error "Only <clutter/clutter.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_DEVICE_MANAGER_H__
|
||||||
|
#define __CLUTTER_DEVICE_MANAGER_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-event.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_DEVICE_MANAGER (clutter_device_manager_get_type ())
|
||||||
|
#define CLUTTER_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManager))
|
||||||
|
#define CLUTTER_IS_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterDeviceManager:
|
||||||
|
*
|
||||||
|
* The #ClutterDeviceManager structure contains only
|
||||||
|
* private data
|
||||||
|
*/
|
||||||
|
typedef struct _ClutterDeviceManager ClutterDeviceManager;
|
||||||
|
|
||||||
|
GType clutter_device_manager_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
ClutterDeviceManager *clutter_device_manager_get_default (void);
|
||||||
|
GSList * clutter_device_manager_list_devices (ClutterDeviceManager *device_manager);
|
||||||
|
const GSList * clutter_device_manager_peek_devices (ClutterDeviceManager *device_manager);
|
||||||
|
|
||||||
|
ClutterInputDevice * clutter_device_manager_get_device (ClutterDeviceManager *device_manager,
|
||||||
|
gint device_id);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_DEVICE_MANAGER_H__ */
|
@ -787,39 +787,3 @@ clutter_get_current_event (void)
|
|||||||
|
|
||||||
return context->current_event;
|
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;
|
|
||||||
}
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#define __CLUTTER_EVENT_H__
|
#define __CLUTTER_EVENT_H__
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-input-device.h>
|
||||||
#include <clutter/clutter-types.h>
|
#include <clutter/clutter-types.h>
|
||||||
|
|
||||||
#define CLUTTER_TYPE_EVENT (clutter_event_get_type ())
|
#define CLUTTER_TYPE_EVENT (clutter_event_get_type ())
|
||||||
@ -201,37 +202,6 @@ typedef struct _ClutterScrollEvent ClutterScrollEvent;
|
|||||||
typedef struct _ClutterStageStateEvent ClutterStageStateEvent;
|
typedef struct _ClutterStageStateEvent ClutterStageStateEvent;
|
||||||
typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
|
typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
|
||||||
|
|
||||||
/**
|
|
||||||
* ClutterInputDevice:
|
|
||||||
*
|
|
||||||
* Generic representation of an input device. The
|
|
||||||
* actual contents of this structure depend on the
|
|
||||||
* backend used.
|
|
||||||
*/
|
|
||||||
typedef struct _ClutterInputDevice ClutterInputDevice;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ClutterInputDeviceType:
|
|
||||||
* @CLUTTER_POINTER_DEVICE: A pointer device
|
|
||||||
* @CLUTTER_KEYBOARD_DEVICE: A keyboard device
|
|
||||||
* @CLUTTER_EXTENSION_DEVICE: A generic extension device
|
|
||||||
* @CLUTTER_N_DEVICE_TYPES: The number of device types
|
|
||||||
*
|
|
||||||
* The types of input devices available.
|
|
||||||
*
|
|
||||||
* The #ClutterInputDeviceType enumeration can be extended at later
|
|
||||||
* date; not every platform supports every input device type.
|
|
||||||
*
|
|
||||||
* Since: 1.0
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
CLUTTER_POINTER_DEVICE,
|
|
||||||
CLUTTER_KEYBOARD_DEVICE,
|
|
||||||
CLUTTER_EXTENSION_DEVICE,
|
|
||||||
|
|
||||||
CLUTTER_N_DEVICE_TYPES
|
|
||||||
} ClutterInputDeviceType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterAnyEvent:
|
* ClutterAnyEvent:
|
||||||
* @type: event type
|
* @type: event type
|
||||||
@ -509,9 +479,6 @@ guint32 clutter_keysym_to_unicode (guint k
|
|||||||
guint32 clutter_get_current_event_time (void);
|
guint32 clutter_get_current_event_time (void);
|
||||||
G_CONST_RETURN ClutterEvent *clutter_get_current_event (void);
|
G_CONST_RETURN ClutterEvent *clutter_get_current_event (void);
|
||||||
|
|
||||||
ClutterInputDeviceType clutter_input_device_get_device_type (ClutterInputDevice *device);
|
|
||||||
gint clutter_input_device_get_device_id (ClutterInputDevice *device);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_EVENT_H__ */
|
#endif /* __CLUTTER_EVENT_H__ */
|
||||||
|
524
clutter/clutter-input-device.c
Normal file
524
clutter/clutter-input-device.c
Normal file
@ -0,0 +1,524 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corp.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:clutter-input-device
|
||||||
|
* @short_description: An input device managed by Clutter
|
||||||
|
*
|
||||||
|
* #ClutterInputDevice represents an input device known to Clutter.
|
||||||
|
*
|
||||||
|
* The #ClutterInputDevice class holds the state of the device, but
|
||||||
|
* its contents are usually defined by the Clutter backend in use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-debug.h"
|
||||||
|
#include "clutter-enum-types.h"
|
||||||
|
#include "clutter-input-device.h"
|
||||||
|
#include "clutter-private.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_ID,
|
||||||
|
PROP_DEVICE_TYPE,
|
||||||
|
PROP_NAME
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterInputDevice, clutter_input_device, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterInputDevice *self = CLUTTER_INPUT_DEVICE (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_ID:
|
||||||
|
self->id = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DEVICE_TYPE:
|
||||||
|
self->device_type = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_NAME:
|
||||||
|
self->device_name = g_strdup (g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterInputDevice *self = CLUTTER_INPUT_DEVICE (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_ID:
|
||||||
|
g_value_set_int (value, self->id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DEVICE_TYPE:
|
||||||
|
g_value_set_enum (value, self->device_type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_NAME:
|
||||||
|
g_value_set_string (value, self->device_name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_class_init (ClutterInputDeviceClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
gobject_class->set_property = clutter_input_device_set_property;
|
||||||
|
gobject_class->get_property = clutter_input_device_get_property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterInputDevice:id:
|
||||||
|
*
|
||||||
|
* The unique identifier of the device
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_int ("id",
|
||||||
|
"Id",
|
||||||
|
"Unique identifier of the device",
|
||||||
|
-1, G_MAXINT,
|
||||||
|
0,
|
||||||
|
CLUTTER_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_ID, pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterInputDevice:name:
|
||||||
|
*
|
||||||
|
* The name of the device
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_string ("name",
|
||||||
|
"Name",
|
||||||
|
"The name of the device",
|
||||||
|
NULL,
|
||||||
|
CLUTTER_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_NAME, pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterInputDevice:device-type:
|
||||||
|
*
|
||||||
|
* The type of the device
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_enum ("device-type",
|
||||||
|
"Device Type",
|
||||||
|
"The type of the device",
|
||||||
|
CLUTTER_TYPE_INPUT_DEVICE_TYPE,
|
||||||
|
CLUTTER_POINTER_DEVICE,
|
||||||
|
CLUTTER_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_DEVICE_TYPE, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_init (ClutterInputDevice *self)
|
||||||
|
{
|
||||||
|
self->id = -1;
|
||||||
|
self->device_type = CLUTTER_POINTER_DEVICE;
|
||||||
|
|
||||||
|
self->click_count = 0;
|
||||||
|
|
||||||
|
self->current_time = self->previous_time = CLUTTER_CURRENT_TIME;
|
||||||
|
self->current_x = self->previous_x = -1;
|
||||||
|
self->current_y = self->previous_y = -1;
|
||||||
|
self->current_button_number = self->previous_button_number = -1;
|
||||||
|
self->current_state = self->previous_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_input_device_set_coords:
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
* @x: X coordinate of the device
|
||||||
|
* @y: Y coordinate of the device
|
||||||
|
*
|
||||||
|
* Stores the last known coordinates of the device
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_input_device_set_coords (ClutterInputDevice *device,
|
||||||
|
gint x,
|
||||||
|
gint y)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||||
|
|
||||||
|
if (device->current_x != x)
|
||||||
|
device->current_x = x;
|
||||||
|
|
||||||
|
if (device->current_y != y)
|
||||||
|
device->current_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_input_device_set_state:
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
* @state: a bitmask of modifiers
|
||||||
|
*
|
||||||
|
* Stores the last known modifiers state of the device
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_input_device_set_state (ClutterInputDevice *device,
|
||||||
|
ClutterModifierType state)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||||
|
|
||||||
|
device->current_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_input_device_set_time:
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
* @time_: the time
|
||||||
|
*
|
||||||
|
* Stores the last known event time of the device
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_input_device_set_time (ClutterInputDevice *device,
|
||||||
|
guint32 time_)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||||
|
|
||||||
|
if (device->current_time != time_)
|
||||||
|
device->current_time = time_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cursor_weak_unref:
|
||||||
|
*
|
||||||
|
* #ClutterInputDevice keeps a weak reference on the actor
|
||||||
|
* under its pointer; this function unsets the reference on
|
||||||
|
* the actor to avoid keeping around stale pointers
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cursor_weak_unref (gpointer user_data,
|
||||||
|
GObject *object_pointer)
|
||||||
|
{
|
||||||
|
ClutterInputDevice *device = user_data;
|
||||||
|
|
||||||
|
device->cursor_actor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_input_device_set_stage:
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
* @stage: a #ClutterStage or %NULL
|
||||||
|
*
|
||||||
|
* Stores the stage under the device
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||||
|
ClutterStage *stage)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||||
|
|
||||||
|
device->stage = stage;
|
||||||
|
|
||||||
|
/* if we left the stage then we also need to unset the
|
||||||
|
* cursor actor (and update its :has-pointer property)
|
||||||
|
*/
|
||||||
|
if (device->stage == NULL && 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 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_input_device_set_actor:
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
* @actor: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Sets the actor under the pointer coordinates of @device
|
||||||
|
*
|
||||||
|
* This function is called by _clutter_input_device_update()
|
||||||
|
* and it will:
|
||||||
|
*
|
||||||
|
* - queue a %CLUTTER_LEAVE event on the previous pointer actor
|
||||||
|
* of @device, if any
|
||||||
|
* - set to %FALSE the :has-pointer property of the previous
|
||||||
|
* pointer actor of @device, if any
|
||||||
|
* - queue a %CLUTTER_ENTER event on the new pointer actor
|
||||||
|
* - set to %TRUE the :has-pointer property of the new pointer
|
||||||
|
* actor
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterActor *old_actor;
|
||||||
|
ClutterEvent cev;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||||
|
|
||||||
|
if (actor == device->cursor_actor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
old_actor = device->cursor_actor;
|
||||||
|
if (old_actor != NULL)
|
||||||
|
{
|
||||||
|
cev.crossing.type = CLUTTER_LEAVE;
|
||||||
|
cev.crossing.time = device->current_time;
|
||||||
|
cev.crossing.flags = 0;
|
||||||
|
cev.crossing.stage = device->stage;
|
||||||
|
cev.crossing.source = device->cursor_actor;
|
||||||
|
cev.crossing.x = device->current_x;
|
||||||
|
cev.crossing.y = device->current_y;
|
||||||
|
cev.crossing.device = device;
|
||||||
|
cev.crossing.related = actor;
|
||||||
|
|
||||||
|
/* we need to make sure that this event is processed before
|
||||||
|
* any other event we might have queued up until now, so we
|
||||||
|
* go on and synthesize the event emission
|
||||||
|
*/
|
||||||
|
_clutter_process_event (&cev);
|
||||||
|
|
||||||
|
_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 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor != NULL)
|
||||||
|
{
|
||||||
|
cev.crossing.type = CLUTTER_ENTER;
|
||||||
|
cev.crossing.time = device->current_time;
|
||||||
|
cev.crossing.flags = 0;
|
||||||
|
cev.crossing.stage = device->stage;
|
||||||
|
cev.crossing.source = actor;
|
||||||
|
cev.crossing.x = device->current_x;
|
||||||
|
cev.crossing.y = device->current_y;
|
||||||
|
cev.crossing.device = device;
|
||||||
|
cev.crossing.related = old_actor;
|
||||||
|
|
||||||
|
/* as above: we need to make sure that this event is processed
|
||||||
|
* before any other event we might have queued up until now, so
|
||||||
|
* we go on and synthesize the event emission
|
||||||
|
*/
|
||||||
|
_clutter_process_event (&cev);
|
||||||
|
}
|
||||||
|
|
||||||
|
device->cursor_actor = actor;
|
||||||
|
|
||||||
|
if (device->cursor_actor != NULL)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* 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 (CLUTTER_IS_INPUT_DEVICE (device),
|
||||||
|
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 (CLUTTER_IS_INPUT_DEVICE (device), -1);
|
||||||
|
|
||||||
|
return device->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_input_device_get_device_coords:
|
||||||
|
* @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
|
||||||
|
* @x: (out): return location for the X coordinate
|
||||||
|
* @y: (out): return location for the Y coordinate
|
||||||
|
*
|
||||||
|
* Retrieves the latest coordinates of the pointer of @device
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_input_device_get_device_coords (ClutterInputDevice *device,
|
||||||
|
gint *x,
|
||||||
|
gint *y)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||||
|
g_return_if_fail (device->device_type == CLUTTER_POINTER_DEVICE);
|
||||||
|
|
||||||
|
if (x)
|
||||||
|
*x = device->current_x;
|
||||||
|
|
||||||
|
if (y)
|
||||||
|
*y = device->current_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_input_device_update:
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
*
|
||||||
|
* Updates the input @device by determining the #ClutterActor underneath the
|
||||||
|
* pointer's cursor
|
||||||
|
*
|
||||||
|
* This function calls _clutter_input_device_set_actor() if needed.
|
||||||
|
*
|
||||||
|
* This function only works for #ClutterInputDevice of type
|
||||||
|
* %CLUTTER_POINTER_DEVICE.
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
ClutterActor *
|
||||||
|
_clutter_input_device_update (ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
ClutterStage *stage;
|
||||||
|
ClutterActor *new_cursor_actor;
|
||||||
|
ClutterActor *old_cursor_actor;
|
||||||
|
gint x, y;
|
||||||
|
|
||||||
|
g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL);
|
||||||
|
|
||||||
|
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 the pick could not find an actor then we do not update the
|
||||||
|
* input device, to avoid ghost enter/leave events; the pick should
|
||||||
|
* never fail, except for bugs in the glReadPixels() implementation
|
||||||
|
* in which case this is the safest course of action anyway
|
||||||
|
*/
|
||||||
|
if (new_cursor_actor == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
/* short-circuit here */
|
||||||
|
if (new_cursor_actor == old_cursor_actor)
|
||||||
|
return old_cursor_actor;
|
||||||
|
|
||||||
|
_clutter_input_device_set_actor (device, new_cursor_actor);
|
||||||
|
|
||||||
|
return device->cursor_actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_input_device_get_pointer_actor:
|
||||||
|
* @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
|
||||||
|
*
|
||||||
|
* Retrieves the #ClutterActor underneath the pointer of @device
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): a pointer to the #ClutterActor or %NULL
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
ClutterActor *
|
||||||
|
clutter_input_device_get_pointer_actor (ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||||
|
g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL);
|
||||||
|
|
||||||
|
return device->cursor_actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_input_device_get_device_name:
|
||||||
|
* @device: a #ClutterInputDevice
|
||||||
|
*
|
||||||
|
* Retrieves the name of the @device
|
||||||
|
*
|
||||||
|
* Return value: the name of the device, or %NULL. The returned string
|
||||||
|
* is owned by the #ClutterInputDevice and should never be modified
|
||||||
|
* or freed
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
G_CONST_RETURN gchar *
|
||||||
|
clutter_input_device_get_device_name (ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||||
|
|
||||||
|
return device->device_name;
|
||||||
|
}
|
99
clutter/clutter-input-device.h
Normal file
99
clutter/clutter-input-device.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corp.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||||
|
#error "Only <clutter/clutter.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_INPUT_DEVICE_H__
|
||||||
|
#define __CLUTTER_INPUT_DEVICE_H__
|
||||||
|
|
||||||
|
#include <clutter/clutter-types.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_INPUT_DEVICE (clutter_input_device_get_type ())
|
||||||
|
#define CLUTTER_INPUT_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE, ClutterInputDevice))
|
||||||
|
#define CLUTTER_IS_INPUT_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE))
|
||||||
|
#define CLUTTER_INPUT_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_INPUT_DEVICE, ClutterInputDeviceClass))
|
||||||
|
#define CLUTTER_IS_INPUT_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_INPUT_DEVICE))
|
||||||
|
#define CLUTTER_INPUT_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_INPUT_DEVICE, ClutterInputDeviceClass))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterInputDevice:
|
||||||
|
*
|
||||||
|
* Generic representation of an input device. The actual contents of this
|
||||||
|
* structure depend on the backend used.
|
||||||
|
*/
|
||||||
|
typedef struct _ClutterInputDevice ClutterInputDevice;
|
||||||
|
typedef struct _ClutterInputDeviceClass ClutterInputDeviceClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterInputDeviceType:
|
||||||
|
* @CLUTTER_POINTER_DEVICE: A pointer device
|
||||||
|
* @CLUTTER_KEYBOARD_DEVICE: A keyboard device
|
||||||
|
* @CLUTTER_EXTENSION_DEVICE: A generic extension device
|
||||||
|
* @CLUTTER_N_DEVICE_TYPES: The number of device types
|
||||||
|
*
|
||||||
|
* The types of input devices available.
|
||||||
|
*
|
||||||
|
* The #ClutterInputDeviceType enumeration can be extended at later
|
||||||
|
* date; not every platform supports every input device type.
|
||||||
|
*
|
||||||
|
* Since: 1.0
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
CLUTTER_POINTER_DEVICE,
|
||||||
|
CLUTTER_KEYBOARD_DEVICE,
|
||||||
|
CLUTTER_EXTENSION_DEVICE,
|
||||||
|
|
||||||
|
CLUTTER_N_DEVICE_TYPES
|
||||||
|
} ClutterInputDeviceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterInputDeviceClass:
|
||||||
|
*
|
||||||
|
* The #ClutterInputDeviceClass structure contains only private
|
||||||
|
* data and should not be accessed directly
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
struct _ClutterInputDeviceClass
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
void clutter_input_device_get_device_coords (ClutterInputDevice *device,
|
||||||
|
gint *x,
|
||||||
|
gint *y);
|
||||||
|
ClutterActor * clutter_input_device_get_pointer_actor (ClutterInputDevice *device);
|
||||||
|
G_CONST_RETURN gchar * clutter_input_device_get_device_name (ClutterInputDevice *device);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_INPUT_DEVICE_H__ */
|
@ -2045,69 +2045,93 @@ event_click_count_generate (ClutterEvent *event)
|
|||||||
static guint32 previous_time = 0;
|
static guint32 previous_time = 0;
|
||||||
static gint previous_button_number = -1;
|
static gint previous_button_number = -1;
|
||||||
|
|
||||||
|
ClutterInputDevice *device = NULL;
|
||||||
ClutterBackend *backend;
|
ClutterBackend *backend;
|
||||||
guint double_click_time;
|
guint double_click_time;
|
||||||
guint double_click_distance;
|
guint double_click_distance;
|
||||||
|
|
||||||
backend = _clutter_context_get_default ()->backend;
|
backend = clutter_get_default_backend ();
|
||||||
double_click_distance = clutter_backend_get_double_click_distance (backend);
|
double_click_distance = clutter_backend_get_double_click_distance (backend);
|
||||||
double_click_time = clutter_backend_get_double_click_time (backend);
|
double_click_time = clutter_backend_get_double_click_time (backend);
|
||||||
|
|
||||||
if (event->button.device != NULL)
|
device = clutter_event_get_device (event);
|
||||||
|
if (device != NULL)
|
||||||
{
|
{
|
||||||
click_count = event->button.device->click_count;
|
click_count = device->click_count;
|
||||||
previous_x = event->button.device->previous_x;
|
previous_x = device->previous_x;
|
||||||
previous_y = event->button.device->previous_y;
|
previous_y = device->previous_y;
|
||||||
previous_time = event->button.device->previous_time;
|
previous_time = device->previous_time;
|
||||||
previous_button_number = event->button.device->previous_button_number;
|
previous_button_number = device->previous_button_number;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"Restoring previous click count:%d (device:%d, time:%u)",
|
||||||
|
click_count,
|
||||||
|
clutter_input_device_get_device_id (device),
|
||||||
|
previous_time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"Restoring previous click count:%d (time:%u)",
|
||||||
|
click_count,
|
||||||
|
previous_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event->type)
|
switch (clutter_event_type (event))
|
||||||
{
|
{
|
||||||
case CLUTTER_BUTTON_PRESS:
|
case CLUTTER_BUTTON_PRESS:
|
||||||
case CLUTTER_SCROLL:
|
|
||||||
/* check if we are in time and within distance to increment an
|
/* check if we are in time and within distance to increment an
|
||||||
* existing click count
|
* existing click count
|
||||||
*/
|
*/
|
||||||
if (event->button.time < previous_time + double_click_time &&
|
if (event->button.button == previous_button_number &&
|
||||||
|
event->button.time < (previous_time + double_click_time) &&
|
||||||
(ABS (event->button.x - previous_x) <= double_click_distance) &&
|
(ABS (event->button.x - previous_x) <= double_click_distance) &&
|
||||||
(ABS (event->button.y - previous_y) <= double_click_distance)
|
(ABS (event->button.y - previous_y) <= double_click_distance))
|
||||||
&& event->button.button == previous_button_number)
|
|
||||||
{
|
{
|
||||||
click_count ++;
|
CLUTTER_NOTE (EVENT, "Increase click count (button: %d, time: %u)",
|
||||||
|
event->button.button,
|
||||||
|
event->button.time);
|
||||||
|
|
||||||
|
click_count += 1;
|
||||||
}
|
}
|
||||||
else /* start a new click count*/
|
else /* start a new click count*/
|
||||||
{
|
{
|
||||||
click_count=1;
|
CLUTTER_NOTE (EVENT, "Reset click count (button: %d, time: %u)",
|
||||||
|
event->button.button,
|
||||||
|
event->button.time);
|
||||||
|
|
||||||
|
click_count = 1;
|
||||||
previous_button_number = event->button.button;
|
previous_button_number = event->button.button;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store time and position for this click for comparison with
|
|
||||||
* next event
|
|
||||||
*/
|
|
||||||
previous_time = event->button.time;
|
|
||||||
previous_x = event->button.x;
|
previous_x = event->button.x;
|
||||||
previous_y = event->button.y;
|
previous_y = event->button.y;
|
||||||
|
previous_time = event->button.time;
|
||||||
|
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case CLUTTER_BUTTON_RELEASE:
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
event->button.click_count=click_count;
|
event->button.click_count = click_count;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert (NULL);
|
g_assert (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->button.device != NULL)
|
if (event->type == CLUTTER_BUTTON_PRESS && device != NULL)
|
||||||
{
|
{
|
||||||
event->button.device->click_count = click_count;
|
CLUTTER_NOTE (EVENT, "Storing click count: %d (device:%d, time:%u)",
|
||||||
event->button.device->previous_x = previous_x;
|
click_count,
|
||||||
event->button.device->previous_y = previous_y;
|
clutter_input_device_get_device_id (device),
|
||||||
event->button.device->previous_time = previous_time;
|
previous_time);
|
||||||
event->button.device->previous_button_number = previous_button_number;
|
|
||||||
|
device->click_count = click_count;
|
||||||
|
device->previous_x = previous_x;
|
||||||
|
device->previous_y = previous_y;
|
||||||
|
device->previous_time = previous_time;
|
||||||
|
device->previous_button_number = previous_button_number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
emit_event (ClutterEvent *event,
|
emit_event (ClutterEvent *event,
|
||||||
gboolean is_key_event)
|
gboolean is_key_event)
|
||||||
@ -2118,7 +2142,7 @@ emit_event (ClutterEvent *event,
|
|||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
gint i = 0;
|
gint i = 0;
|
||||||
|
|
||||||
if (!event->any.source)
|
if (event->any.source == NULL)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (EVENT, "No source set, discarding event");
|
CLUTTER_NOTE (EVENT, "No source set, discarding event");
|
||||||
return;
|
return;
|
||||||
@ -2182,136 +2206,38 @@ static inline void
|
|||||||
emit_pointer_event (ClutterEvent *event,
|
emit_pointer_event (ClutterEvent *event,
|
||||||
ClutterInputDevice *device)
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
/* Using the global variable directly, since it has to be initialized
|
ClutterMainContext *context = _clutter_context_get_default ();
|
||||||
* at this point
|
|
||||||
*/
|
|
||||||
ClutterMainContext *context = ClutterCntx;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (context->pointer_grab_actor != NULL &&
|
if (context->pointer_grab_actor == NULL &&
|
||||||
device == NULL))
|
(device == NULL || device->pointer_grab_actor == NULL))
|
||||||
|
{
|
||||||
|
/* no grab, time to capture and bubble */
|
||||||
|
emit_event (event, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (context->pointer_grab_actor != NULL)
|
||||||
{
|
{
|
||||||
/* global grab */
|
/* global grab */
|
||||||
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
|
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
|
||||||
}
|
}
|
||||||
else if (G_UNLIKELY (device != NULL &&
|
else if (device != NULL && device->pointer_grab_actor != NULL)
|
||||||
device->pointer_grab_actor != NULL))
|
|
||||||
{
|
{
|
||||||
/* per device grab */
|
/* per device grab */
|
||||||
clutter_actor_event (device->pointer_grab_actor, event, FALSE);
|
clutter_actor_event (device->pointer_grab_actor, event, FALSE);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* no grab, time to capture and bubble */
|
|
||||||
emit_event (event, FALSE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
emit_keyboard_event (ClutterEvent *event)
|
emit_keyboard_event (ClutterEvent *event)
|
||||||
{
|
{
|
||||||
ClutterMainContext *context = ClutterCntx;
|
ClutterMainContext *context = _clutter_context_get_default ();
|
||||||
|
|
||||||
if (G_UNLIKELY (context->keyboard_grab_actor != NULL))
|
if (context->keyboard_grab_actor == NULL)
|
||||||
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
|
||||||
else
|
|
||||||
emit_event (event, TRUE);
|
emit_event (event, TRUE);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
unset_motion_last_actor (ClutterActor *actor, ClutterInputDevice *dev)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = ClutterCntx;
|
|
||||||
|
|
||||||
if (dev == NULL)
|
|
||||||
context->motion_last_actor = NULL;
|
|
||||||
else
|
else
|
||||||
dev->motion_last_actor = NULL;
|
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_motion_last_actor (ClutterActor *motion_current_actor,
|
|
||||||
ClutterInputDevice *device)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = ClutterCntx;
|
|
||||||
ClutterActor *last_actor = context->motion_last_actor;
|
|
||||||
|
|
||||||
if (device != NULL)
|
|
||||||
last_actor = device->motion_last_actor;
|
|
||||||
|
|
||||||
if (last_actor && last_actor != motion_current_actor)
|
|
||||||
{
|
|
||||||
g_signal_handlers_disconnect_by_func
|
|
||||||
(last_actor,
|
|
||||||
G_CALLBACK (unset_motion_last_actor),
|
|
||||||
device);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (motion_current_actor && last_actor != motion_current_actor)
|
|
||||||
{
|
|
||||||
g_signal_connect (motion_current_actor, "destroy",
|
|
||||||
G_CALLBACK (unset_motion_last_actor),
|
|
||||||
device);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device != NULL)
|
|
||||||
device->motion_last_actor = motion_current_actor;
|
|
||||||
else
|
|
||||||
context->motion_last_actor = motion_current_actor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
generate_enter_leave_events (ClutterEvent *event)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = ClutterCntx;
|
|
||||||
ClutterActor *motion_current_actor = event->motion.source;
|
|
||||||
ClutterActor *last_actor = context->motion_last_actor;
|
|
||||||
ClutterInputDevice *device = clutter_event_get_device (event);
|
|
||||||
|
|
||||||
if (device != NULL)
|
|
||||||
last_actor = device->motion_last_actor;
|
|
||||||
|
|
||||||
if (last_actor != motion_current_actor)
|
|
||||||
{
|
|
||||||
if (motion_current_actor)
|
|
||||||
{
|
|
||||||
ClutterEvent cev;
|
|
||||||
gfloat x, y;
|
|
||||||
|
|
||||||
cev.crossing.device = device;
|
|
||||||
clutter_event_get_coords (event, &x, &y);
|
|
||||||
|
|
||||||
if (context->motion_last_actor)
|
|
||||||
{
|
|
||||||
cev.crossing.type = CLUTTER_LEAVE;
|
|
||||||
cev.crossing.time = event->any.time;
|
|
||||||
cev.crossing.flags = 0;
|
|
||||||
cev.crossing.x = x;
|
|
||||||
cev.crossing.y = y;
|
|
||||||
cev.crossing.source = last_actor;
|
|
||||||
cev.crossing.stage = event->any.stage;
|
|
||||||
cev.crossing.related = motion_current_actor;
|
|
||||||
|
|
||||||
emit_pointer_event (&cev, device);
|
|
||||||
}
|
|
||||||
|
|
||||||
cev.crossing.type = CLUTTER_ENTER;
|
|
||||||
cev.crossing.time = event->any.time;
|
|
||||||
cev.crossing.flags = 0;
|
|
||||||
cev.crossing.x = x;
|
|
||||||
cev.crossing.y = y;
|
|
||||||
cev.crossing.source = motion_current_actor;
|
|
||||||
cev.crossing.stage = event->any.stage;
|
|
||||||
|
|
||||||
if (context->motion_last_actor)
|
|
||||||
cev.crossing.related = last_actor;
|
|
||||||
else
|
|
||||||
cev.crossing.related = NULL;
|
|
||||||
|
|
||||||
emit_pointer_event (&cev, device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_motion_last_actor (motion_current_actor, device);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2345,6 +2271,8 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
{
|
{
|
||||||
ClutterInputDevice *device = NULL;
|
ClutterInputDevice *device = NULL;
|
||||||
|
|
||||||
|
device = clutter_event_get_device (event);
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case CLUTTER_NOTHING:
|
case CLUTTER_NOTHING:
|
||||||
@ -2352,23 +2280,8 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_LEAVE:
|
case CLUTTER_LEAVE:
|
||||||
/* The source is set for generated events, not for events
|
|
||||||
* resulting from the cursor leaving the stage
|
|
||||||
*/
|
|
||||||
if (event->any.source == NULL)
|
|
||||||
{
|
|
||||||
ClutterActor *last_actor = context->motion_last_actor;
|
|
||||||
|
|
||||||
if (event->crossing.device != NULL)
|
|
||||||
last_actor = event->crossing.device->motion_last_actor;
|
|
||||||
|
|
||||||
event->any.source = last_actor;
|
|
||||||
|
|
||||||
set_motion_last_actor (NULL, event->crossing.device);
|
|
||||||
}
|
|
||||||
/* flow through */
|
|
||||||
case CLUTTER_ENTER:
|
case CLUTTER_ENTER:
|
||||||
emit_pointer_event (event, event->crossing.device);
|
emit_pointer_event (event, device);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_DESTROY_NOTIFY:
|
case CLUTTER_DESTROY_NOTIFY:
|
||||||
@ -2400,8 +2313,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_MOTION:
|
case CLUTTER_MOTION:
|
||||||
device = event->motion.device;
|
|
||||||
|
|
||||||
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
||||||
* and the event is not a synthetic event with source set.
|
* and the event is not a synthetic event with source set.
|
||||||
*/
|
*/
|
||||||
@ -2434,8 +2345,7 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fallthrough */
|
/* fallthrough from motion */
|
||||||
|
|
||||||
case CLUTTER_BUTTON_PRESS:
|
case CLUTTER_BUTTON_PRESS:
|
||||||
case CLUTTER_BUTTON_RELEASE:
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
case CLUTTER_SCROLL:
|
case CLUTTER_SCROLL:
|
||||||
@ -2462,18 +2372,29 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
x, y);
|
x, y);
|
||||||
|
|
||||||
event->button.source = stage;
|
event->button.source = stage;
|
||||||
emit_pointer_event (event, event->button.device);
|
event->button.click_count = 1;
|
||||||
|
emit_pointer_event (event, device);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map the event to a reactive actor */
|
/* 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)
|
||||||
|
actor = _clutter_input_device_update (device);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (EVENT, "No device found: picking");
|
||||||
|
|
||||||
actor = _clutter_do_pick (CLUTTER_STAGE (stage),
|
actor = _clutter_do_pick (CLUTTER_STAGE (stage),
|
||||||
x, y,
|
x, y,
|
||||||
CLUTTER_PICK_REACTIVE);
|
CLUTTER_PICK_REACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
event->any.source = actor;
|
event->any.source = actor;
|
||||||
if (!actor)
|
if (event->any.source == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2482,7 +2403,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
actor = event->any.source;
|
actor = event->any.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: for an optimisation should check if there are
|
/* FIXME: for an optimisation should check if there are
|
||||||
* actually any reactive actors and avoid the pick all together
|
* actually any reactive actors and avoid the pick all together
|
||||||
* (signalling just the stage). Should be big help for gles.
|
* (signalling just the stage). Should be big help for gles.
|
||||||
@ -2493,33 +2413,12 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
x, y,
|
x, y,
|
||||||
actor);
|
actor);
|
||||||
|
|
||||||
/* Create, enter/leave events if needed */
|
|
||||||
generate_enter_leave_events (event);
|
|
||||||
|
|
||||||
if (event->type != CLUTTER_MOTION)
|
if (event->type != CLUTTER_MOTION)
|
||||||
{
|
{
|
||||||
/* Generate click count */
|
/* Generate click count */
|
||||||
event_click_count_generate (event);
|
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);
|
emit_pointer_event (event, device);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3023,9 +2922,19 @@ clutter_get_font_flags (void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_get_input_device_for_id:
|
* clutter_get_input_device_for_id:
|
||||||
* @id: a device id
|
* @id: the unique id for a device
|
||||||
*
|
*
|
||||||
* Retrieves the #ClutterInputDevice from its id.
|
* Retrieves the #ClutterInputDevice from its @id. This is a convenience
|
||||||
|
* wrapper for clutter_device_manager_get_device() and it is functionally
|
||||||
|
* equivalent to:
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* ClutterDeviceManager *manager;
|
||||||
|
* ClutterInputDevice *device;
|
||||||
|
*
|
||||||
|
* manager = clutter_device_manager_get_default ();
|
||||||
|
* device = clutter_device_manager_get_device (manager, id);
|
||||||
|
* ]|
|
||||||
*
|
*
|
||||||
* Return value: (transfer none): a #ClutterInputDevice, or %NULL
|
* Return value: (transfer none): a #ClutterInputDevice, or %NULL
|
||||||
*
|
*
|
||||||
@ -3034,23 +2943,11 @@ clutter_get_font_flags (void)
|
|||||||
ClutterInputDevice *
|
ClutterInputDevice *
|
||||||
clutter_get_input_device_for_id (gint id)
|
clutter_get_input_device_for_id (gint id)
|
||||||
{
|
{
|
||||||
GSList *item;
|
ClutterDeviceManager *manager;
|
||||||
ClutterInputDevice *device = NULL;
|
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
for (item = context->input_devices;
|
return clutter_device_manager_get_device (manager, id);
|
||||||
item != NULL;
|
|
||||||
item = item->next)
|
|
||||||
{
|
|
||||||
device = item->data;
|
|
||||||
|
|
||||||
if (device->id == id)
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,6 +12,7 @@ VOID:INT,INT,INT,INT
|
|||||||
VOID:OBJECT
|
VOID:OBJECT
|
||||||
VOID:OBJECT,OBJECT,PARAM
|
VOID:OBJECT,OBJECT,PARAM
|
||||||
VOID:OBJECT,POINTER
|
VOID:OBJECT,POINTER
|
||||||
|
VOID:POINTER
|
||||||
VOID:STRING,BOOLEAN,BOOLEAN
|
VOID:STRING,BOOLEAN,BOOLEAN
|
||||||
VOID:STRING,INT
|
VOID:STRING,INT
|
||||||
VOID:UINT
|
VOID:UINT
|
||||||
|
@ -288,14 +288,13 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
* event handling
|
* event handling
|
||||||
*/
|
*/
|
||||||
stages = clutter_stage_manager_list_stages (stage_manager);
|
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);
|
CLUTTER_TIMER_START (_clutter_uprof_context, master_event_process);
|
||||||
|
|
||||||
master_clock->updated_stages = FALSE;
|
master_clock->updated_stages = FALSE;
|
||||||
|
|
||||||
/* Process queued events
|
/* Process queued events */
|
||||||
*/
|
|
||||||
for (l = stages; l != NULL; l = l->next)
|
for (l = stages; l != NULL; l = l->next)
|
||||||
_clutter_stage_process_queued_events (l->data);
|
_clutter_stage_process_queued_events (l->data);
|
||||||
|
|
||||||
@ -311,7 +310,7 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
for (l = stages; l != NULL; l = l->next)
|
for (l = stages; l != NULL; l = l->next)
|
||||||
master_clock->updated_stages |= _clutter_stage_do_update (l->data);
|
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);
|
g_slist_free (stages);
|
||||||
|
|
||||||
master_clock->prev_tick = master_clock->cur_tick;
|
master_clock->prev_tick = master_clock->cur_tick;
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "pango/cogl-pango.h"
|
#include "pango/cogl-pango.h"
|
||||||
|
|
||||||
#include "clutter-backend.h"
|
#include "clutter-backend.h"
|
||||||
|
#include "clutter-device-manager.h"
|
||||||
#include "clutter-event.h"
|
#include "clutter-event.h"
|
||||||
#include "clutter-feature.h"
|
#include "clutter-feature.h"
|
||||||
#include "clutter-id-pool.h"
|
#include "clutter-id-pool.h"
|
||||||
@ -52,6 +53,8 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _ClutterMainContext ClutterMainContext;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CLUTTER_ACTOR_UNUSED_FLAG = 0,
|
CLUTTER_ACTOR_UNUSED_FLAG = 0,
|
||||||
|
|
||||||
@ -82,21 +85,54 @@ typedef enum {
|
|||||||
|
|
||||||
struct _ClutterInputDevice
|
struct _ClutterInputDevice
|
||||||
{
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
gint id;
|
gint id;
|
||||||
|
|
||||||
ClutterInputDeviceType device_type;
|
ClutterInputDeviceType device_type;
|
||||||
|
|
||||||
ClutterActor *pointer_grab_actor;
|
gchar *device_name;
|
||||||
ClutterActor *motion_last_actor;
|
|
||||||
|
|
||||||
|
/* the actor underneath the pointer */
|
||||||
|
ClutterActor *cursor_actor;
|
||||||
|
|
||||||
|
/* the actor that has a grab in place for the device */
|
||||||
|
ClutterActor *pointer_grab_actor;
|
||||||
|
|
||||||
|
/* the current click count */
|
||||||
gint click_count;
|
gint click_count;
|
||||||
|
|
||||||
|
/* the stage the device is on */
|
||||||
|
ClutterStage *stage;
|
||||||
|
|
||||||
|
/* the current state */
|
||||||
|
gint current_x;
|
||||||
|
gint current_y;
|
||||||
|
guint32 current_time;
|
||||||
|
gint current_button_number;
|
||||||
|
ClutterModifierType current_state;
|
||||||
|
|
||||||
|
/* the previous state, used for click count generation */
|
||||||
gint previous_x;
|
gint previous_x;
|
||||||
gint previous_y;
|
gint previous_y;
|
||||||
guint32 previous_time;
|
guint32 previous_time;
|
||||||
gint previous_button_number;
|
gint previous_button_number;
|
||||||
|
ClutterModifierType previous_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _ClutterMainContext ClutterMainContext;
|
struct _ClutterStageManager
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GSList *stages;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterDeviceManager
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GSList *devices;
|
||||||
|
};
|
||||||
|
|
||||||
struct _ClutterMainContext
|
struct _ClutterMainContext
|
||||||
{
|
{
|
||||||
@ -138,9 +174,6 @@ struct _ClutterMainContext
|
|||||||
PangoContext *pango_context; /* Global Pango context */
|
PangoContext *pango_context; /* Global Pango context */
|
||||||
CoglPangoFontMap *font_map; /* Global font map */
|
CoglPangoFontMap *font_map; /* Global font map */
|
||||||
|
|
||||||
GSList *input_devices; /* For extra input devices, i.e
|
|
||||||
MultiTouch */
|
|
||||||
|
|
||||||
ClutterEvent *current_event;
|
ClutterEvent *current_event;
|
||||||
guint32 last_event_time;
|
guint32 last_event_time;
|
||||||
|
|
||||||
@ -170,21 +203,34 @@ PangoContext *_clutter_context_get_pango_context (ClutterMainContext *self);
|
|||||||
|
|
||||||
#define I_(str) (g_intern_static_string ((str)))
|
#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_update_devices (ClutterDeviceManager *device_manager);
|
||||||
|
|
||||||
|
/* input device */
|
||||||
|
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 */
|
/* stage manager */
|
||||||
struct _ClutterStageManager
|
|
||||||
{
|
|
||||||
GObject parent_instance;
|
|
||||||
|
|
||||||
GSList *stages;
|
|
||||||
};
|
|
||||||
|
|
||||||
void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
||||||
ClutterStage *stage);
|
ClutterStage *stage);
|
||||||
void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
||||||
ClutterStage *stage);
|
ClutterStage *stage);
|
||||||
|
|
||||||
/* stage */
|
/* stage */
|
||||||
|
|
||||||
void _clutter_stage_set_window (ClutterStage *stage,
|
void _clutter_stage_set_window (ClutterStage *stage,
|
||||||
ClutterStageWindow *stage_window);
|
ClutterStageWindow *stage_window);
|
||||||
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
||||||
@ -198,6 +244,7 @@ void _clutter_stage_queue_event (ClutterStage *stage,
|
|||||||
ClutterEvent *event);
|
ClutterEvent *event);
|
||||||
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
|
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
|
||||||
void _clutter_stage_process_queued_events (ClutterStage *stage);
|
void _clutter_stage_process_queued_events (ClutterStage *stage);
|
||||||
|
void _clutter_stage_update_input_devices (ClutterStage *stage);
|
||||||
|
|
||||||
/* vfuncs implemented by backend */
|
/* vfuncs implemented by backend */
|
||||||
GType _clutter_backend_impl_get_type (void);
|
GType _clutter_backend_impl_get_type (void);
|
||||||
@ -271,6 +318,9 @@ void _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
|
|||||||
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
||||||
gboolean enable);
|
gboolean enable);
|
||||||
|
|
||||||
|
void _clutter_actor_set_has_pointer (ClutterActor *self,
|
||||||
|
gboolean has_pointer);
|
||||||
|
|
||||||
void _clutter_run_repaint_functions (void);
|
void _clutter_run_repaint_functions (void);
|
||||||
|
|
||||||
gint32 _clutter_backend_get_units_serial (ClutterBackend *backend);
|
gint32 _clutter_backend_get_units_serial (ClutterBackend *backend);
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
#include "clutter-id-pool.h"
|
#include "clutter-id-pool.h"
|
||||||
#include "clutter-container.h"
|
#include "clutter-container.h"
|
||||||
#include "clutter-profile.h"
|
#include "clutter-profile.h"
|
||||||
|
#include "clutter-input-device.h"
|
||||||
|
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
|
|
||||||
@ -455,6 +456,7 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
|||||||
{
|
{
|
||||||
ClutterStagePrivate *priv;
|
ClutterStagePrivate *priv;
|
||||||
gboolean first_event;
|
gboolean first_event;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||||
|
|
||||||
@ -462,14 +464,31 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
|||||||
|
|
||||||
first_event = priv->event_queue->length == 0;
|
first_event = priv->event_queue->length == 0;
|
||||||
|
|
||||||
g_queue_push_tail (priv->event_queue,
|
g_queue_push_tail (priv->event_queue, clutter_event_copy (event));
|
||||||
clutter_event_copy (event));
|
|
||||||
|
|
||||||
if (first_event)
|
if (first_event)
|
||||||
{
|
{
|
||||||
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
|
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
|
||||||
_clutter_master_clock_start_running (master_clock);
|
_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -488,7 +507,7 @@ void
|
|||||||
_clutter_stage_process_queued_events (ClutterStage *stage)
|
_clutter_stage_process_queued_events (ClutterStage *stage)
|
||||||
{
|
{
|
||||||
ClutterStagePrivate *priv;
|
ClutterStagePrivate *priv;
|
||||||
GList *events, *l;;
|
GList *events, *l;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||||
|
|
||||||
@ -507,7 +526,7 @@ _clutter_stage_process_queued_events (ClutterStage *stage)
|
|||||||
priv->event_queue->tail = NULL;
|
priv->event_queue->tail = NULL;
|
||||||
priv->event_queue->length = 0;
|
priv->event_queue->length = 0;
|
||||||
|
|
||||||
for (l = events; l; l = l->next)
|
for (l = events; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
ClutterEvent *event;
|
ClutterEvent *event;
|
||||||
ClutterEvent *next_event;
|
ClutterEvent *next_event;
|
||||||
|
@ -51,12 +51,14 @@
|
|||||||
#include "clutter-clone.h"
|
#include "clutter-clone.h"
|
||||||
#include "clutter-color.h"
|
#include "clutter-color.h"
|
||||||
#include "clutter-container.h"
|
#include "clutter-container.h"
|
||||||
|
#include "clutter-device-manager.h"
|
||||||
#include "clutter-event.h"
|
#include "clutter-event.h"
|
||||||
#include "clutter-feature.h"
|
#include "clutter-feature.h"
|
||||||
#include "clutter-fixed-layout.h"
|
#include "clutter-fixed-layout.h"
|
||||||
#include "clutter-flow-layout.h"
|
#include "clutter-flow-layout.h"
|
||||||
#include "clutter-frame-source.h"
|
#include "clutter-frame-source.h"
|
||||||
#include "clutter-group.h"
|
#include "clutter-group.h"
|
||||||
|
#include "clutter-input-device.h"
|
||||||
#include "clutter-interval.h"
|
#include "clutter-interval.h"
|
||||||
#include "clutter-keysyms.h"
|
#include "clutter-keysyms.h"
|
||||||
#include "clutter-layout-manager.h"
|
#include "clutter-layout-manager.h"
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "../clutter-event.h"
|
#include "../clutter-event.h"
|
||||||
#include "../clutter-main.h"
|
#include "../clutter-main.h"
|
||||||
|
#include "../clutter-input-device.h"
|
||||||
#include "../clutter-debug.h"
|
#include "../clutter-debug.h"
|
||||||
#include "../clutter-private.h"
|
#include "../clutter-private.h"
|
||||||
#include "../clutter-version.h"
|
#include "../clutter-version.h"
|
||||||
@ -64,8 +65,30 @@ clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
|||||||
static void
|
static void
|
||||||
clutter_backend_win32_init_events (ClutterBackend *backend)
|
clutter_backend_win32_init_events (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
|
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "initialising the event loop");
|
CLUTTER_NOTE (EVENT, "initialising the event loop");
|
||||||
|
|
||||||
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
|
||||||
|
"id", 0,
|
||||||
|
"name", "Core Pointer",
|
||||||
|
"device-type", CLUTTER_POINTER_DEVICE,
|
||||||
|
NULL);
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
backend_win32->core_pointer = device;
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
|
||||||
|
"id", 1,
|
||||||
|
"name", "Core Keyboard",
|
||||||
|
"device-type", CLUTTER_KEYBOARD_DEVICE,
|
||||||
|
NULL);
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
backend_win32->core_keyboard = device;
|
||||||
|
|
||||||
_clutter_backend_win32_events_init (backend);
|
_clutter_backend_win32_events_init (backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,9 @@ struct _ClutterBackendWin32
|
|||||||
HCURSOR invisible_cursor;
|
HCURSOR invisible_cursor;
|
||||||
|
|
||||||
GSource *event_source;
|
GSource *event_source;
|
||||||
|
|
||||||
|
ClutterInputDevice *core_pointer;
|
||||||
|
ClutterInputDevice *core_keyboard;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendWin32Class
|
struct _ClutterBackendWin32Class
|
||||||
|
@ -201,9 +201,13 @@ get_modifier_state (WPARAM wparam)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static inline void
|
||||||
make_button_event (const MSG *msg, ClutterEvent *event,
|
make_button_event (const MSG *msg,
|
||||||
int button, int click_count, gboolean release)
|
ClutterEvent *event,
|
||||||
|
int button,
|
||||||
|
int click_count,
|
||||||
|
gboolean release,
|
||||||
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
event->type = release ? CLUTTER_BUTTON_RELEASE : CLUTTER_BUTTON_PRESS;
|
event->type = release ? CLUTTER_BUTTON_RELEASE : CLUTTER_BUTTON_PRESS;
|
||||||
event->button.time = msg->time;
|
event->button.time = msg->time;
|
||||||
@ -212,6 +216,7 @@ make_button_event (const MSG *msg, ClutterEvent *event,
|
|||||||
event->button.modifier_state = get_modifier_state (msg->wParam);
|
event->button.modifier_state = get_modifier_state (msg->wParam);
|
||||||
event->button.button = button;
|
event->button.button = button;
|
||||||
event->button.click_count = click_count;
|
event->button.click_count = click_count;
|
||||||
|
event->button.device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -429,39 +434,39 @@ message_translate (ClutterBackend *backend,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDOWN:
|
case WM_LBUTTONDOWN:
|
||||||
make_button_event (msg, event, 1, 1, FALSE);
|
make_button_event (msg, event, 1, 1, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_MBUTTONDOWN:
|
case WM_MBUTTONDOWN:
|
||||||
make_button_event (msg, event, 2, 1, FALSE);
|
make_button_event (msg, event, 2, 1, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDOWN:
|
case WM_RBUTTONDOWN:
|
||||||
make_button_event (msg, event, 3, 1, FALSE);
|
make_button_event (msg, event, 3, 1, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
make_button_event (msg, event, 1, 1, TRUE);
|
make_button_event (msg, event, 1, 1, TRUE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_MBUTTONUP:
|
case WM_MBUTTONUP:
|
||||||
make_button_event (msg, event, 2, 1, TRUE);
|
make_button_event (msg, event, 2, 1, TRUE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONUP:
|
case WM_RBUTTONUP:
|
||||||
make_button_event (msg, event, 3, 1, TRUE);
|
make_button_event (msg, event, 3, 1, TRUE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDBLCLK:
|
case WM_LBUTTONDBLCLK:
|
||||||
make_button_event (msg, event, 1, 2, FALSE);
|
make_button_event (msg, event, 1, 2, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_MBUTTONDBLCLK:
|
case WM_MBUTTONDBLCLK:
|
||||||
make_button_event (msg, event, 2, 2, FALSE);
|
make_button_event (msg, event, 2, 2, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDBLCLK:
|
case WM_RBUTTONDBLCLK:
|
||||||
make_button_event (msg, event, 3, 2, FALSE);
|
make_button_event (msg, event, 3, 2, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_MOUSEWHEEL:
|
case WM_MOUSEWHEEL:
|
||||||
@ -469,8 +474,8 @@ message_translate (ClutterBackend *backend,
|
|||||||
|
|
||||||
event->type = CLUTTER_SCROLL;
|
event->type = CLUTTER_SCROLL;
|
||||||
event->scroll.time = msg->time;
|
event->scroll.time = msg->time;
|
||||||
event->scroll.modifier_state
|
event->scroll.modifier_state = get_modifier_state (LOWORD (msg->wParam));
|
||||||
= get_modifier_state (LOWORD (msg->wParam));
|
event->scroll.device = backend_win32->core_pointer;
|
||||||
|
|
||||||
/* conversion to window coordinates is required */
|
/* conversion to window coordinates is required */
|
||||||
{
|
{
|
||||||
@ -500,7 +505,9 @@ message_translate (ClutterBackend *backend,
|
|||||||
event->motion.x = GET_X_LPARAM (msg->lParam);
|
event->motion.x = GET_X_LPARAM (msg->lParam);
|
||||||
event->motion.y = GET_Y_LPARAM (msg->lParam);
|
event->motion.y = GET_Y_LPARAM (msg->lParam);
|
||||||
event->motion.modifier_state = get_modifier_state (msg->wParam);
|
event->motion.modifier_state = get_modifier_state (msg->wParam);
|
||||||
/* We need to start tracking when the mouse leaves the stage if
|
event->motion.device = backend_win32->core_pointer;
|
||||||
|
|
||||||
|
/* We need to start tracking when the mouse enters the stage if
|
||||||
we're not already */
|
we're not already */
|
||||||
if (!stage_win32->tracking_mouse)
|
if (!stage_win32->tracking_mouse)
|
||||||
{
|
{
|
||||||
@ -511,6 +518,9 @@ message_translate (ClutterBackend *backend,
|
|||||||
tmevent.hwndTrack = stage_win32->hwnd;
|
tmevent.hwndTrack = stage_win32->hwnd;
|
||||||
TrackMouseEvent (&tmevent);
|
TrackMouseEvent (&tmevent);
|
||||||
|
|
||||||
|
/* we entered the stage */
|
||||||
|
_clutter_input_device_set_stage (event->motion.device, stage);
|
||||||
|
|
||||||
stage_win32->tracking_mouse = TRUE;
|
stage_win32->tracking_mouse = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -520,6 +530,10 @@ message_translate (ClutterBackend *backend,
|
|||||||
event->crossing.time = msg->time;
|
event->crossing.time = msg->time;
|
||||||
event->crossing.x = msg->pt.x;
|
event->crossing.x = msg->pt.x;
|
||||||
event->crossing.y = msg->pt.y;
|
event->crossing.y = msg->pt.y;
|
||||||
|
event->crossing.device = backend_win32->core_pointer;
|
||||||
|
|
||||||
|
/* we left the stage */
|
||||||
|
_clutter_input_device_set_stage (event->crossing.device, NULL);
|
||||||
|
|
||||||
/* When we get a leave message the mouse tracking is
|
/* When we get a leave message the mouse tracking is
|
||||||
automatically cancelled so we'll need to start it again when
|
automatically cancelled so we'll need to start it again when
|
||||||
@ -604,6 +618,7 @@ message_translate (ClutterBackend *backend,
|
|||||||
event->key.time = msg->time;
|
event->key.time = msg->time;
|
||||||
event->key.modifier_state = get_key_modifier_state (key_states);
|
event->key.modifier_state = get_key_modifier_state (key_states);
|
||||||
event->key.hardware_keycode = scan_code;
|
event->key.hardware_keycode = scan_code;
|
||||||
|
event->key.device = backend_win32->core_keyboard;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ libclutter_x11_la_SOURCES = \
|
|||||||
clutter-backend-x11.h \
|
clutter-backend-x11.h \
|
||||||
clutter-backend-x11.c \
|
clutter-backend-x11.c \
|
||||||
clutter-event-x11.c \
|
clutter-event-x11.c \
|
||||||
|
clutter-input-device-x11.h \
|
||||||
|
clutter-input-device-x11.c \
|
||||||
clutter-stage-x11.h \
|
clutter-stage-x11.h \
|
||||||
clutter-stage-x11.c \
|
clutter-stage-x11.c \
|
||||||
clutter-x11-enum-types.h \
|
clutter-x11-enum-types.h \
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "clutter-backend-x11.h"
|
#include "clutter-backend-x11.h"
|
||||||
|
#include "clutter-input-device-x11.h"
|
||||||
#include "clutter-stage-x11.h"
|
#include "clutter-stage-x11.h"
|
||||||
#include "clutter-x11.h"
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
@ -46,31 +47,16 @@
|
|||||||
#include <X11/extensions/XInput.h>
|
#include <X11/extensions/XInput.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../clutter-event.h"
|
|
||||||
#include "../clutter-main.h"
|
|
||||||
#include "../clutter-debug.h"
|
|
||||||
#include "../clutter-private.h"
|
|
||||||
|
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
|
|
||||||
|
#include "../clutter-debug.h"
|
||||||
|
#include "../clutter-device-manager.h"
|
||||||
|
#include "../clutter-event.h"
|
||||||
|
#include "../clutter-main.h"
|
||||||
|
#include "../clutter-private.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
|
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
|
||||||
|
|
||||||
struct _ClutterX11XInputDevice
|
|
||||||
{
|
|
||||||
ClutterInputDevice device;
|
|
||||||
|
|
||||||
#ifdef HAVE_XINPUT
|
|
||||||
XDevice *xdevice;
|
|
||||||
XEventClass xevent_list[5]; /* MAX 5 event types */
|
|
||||||
int num_events;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef HAVE_XINPUT
|
|
||||||
void _clutter_x11_register_xinput ();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* atoms; remember to add the code that assigns the atom value to
|
/* atoms; remember to add the code that assigns the atom value to
|
||||||
* the member of the ClutterBackendX11 structure if you add an
|
* the member of the ClutterBackendX11 structure if you add an
|
||||||
* atom name here. do not change the order!
|
* atom name here. do not change the order!
|
||||||
@ -109,6 +95,129 @@ static gboolean clutter_synchronise = FALSE;
|
|||||||
static int TrappedErrorCode = 0;
|
static int TrappedErrorCode = 0;
|
||||||
static int (* old_error_handler) (Display *, XErrorEvent *);
|
static int (* old_error_handler) (Display *, XErrorEvent *);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_x11_register_input_devices (ClutterBackendX11 *backend)
|
||||||
|
{
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
XDeviceInfo *x_devices = NULL;
|
||||||
|
int res, opcode, event, error;
|
||||||
|
int i, n_devices;
|
||||||
|
#endif /* HAVE_XINPUT */
|
||||||
|
|
||||||
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
|
if (!clutter_enable_xinput)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "XInput support not enabled");
|
||||||
|
goto default_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
res = XQueryExtension (backend->xdpy, "XInputExtension",
|
||||||
|
&opcode,
|
||||||
|
&event,
|
||||||
|
&error);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "No XInput extension available");
|
||||||
|
goto default_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->xi_event_base = event;
|
||||||
|
|
||||||
|
x_devices = XListInputDevices (backend->xdpy, &n_devices);
|
||||||
|
if (n_devices == 0)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "No XInput devices found");
|
||||||
|
goto default_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n_devices; i++)
|
||||||
|
{
|
||||||
|
XDeviceInfo *info = x_devices + i;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND,
|
||||||
|
"Considering device %li with type %d, %d of %d",
|
||||||
|
info->id,
|
||||||
|
info->use,
|
||||||
|
i, n_devices);
|
||||||
|
|
||||||
|
/* we only want 'raw' devices, not virtual ones */
|
||||||
|
if (info->use == IsXExtensionPointer ||
|
||||||
|
/* info->use == IsXExtensionKeyboard || XInput1 is broken */
|
||||||
|
info->use == IsXExtensionDevice)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceType device_type;
|
||||||
|
gint n_events = 0;
|
||||||
|
|
||||||
|
switch (info->use)
|
||||||
|
{
|
||||||
|
case IsXExtensionPointer:
|
||||||
|
device_type = CLUTTER_POINTER_DEVICE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* XInput1 is broken for keyboards */
|
||||||
|
case IsXExtensionKeyboard:
|
||||||
|
device_type = CLUTTER_KEYBOARD_DEVICE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IsXExtensionDevice:
|
||||||
|
device_type = CLUTTER_EXTENSION_DEVICE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
|
||||||
|
"id", info->id,
|
||||||
|
"device-type", device_type,
|
||||||
|
"name", info->name,
|
||||||
|
NULL);
|
||||||
|
n_events = _clutter_input_device_x11_construct (device, backend);
|
||||||
|
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
|
||||||
|
if (info->use == IsXExtensionPointer && n_events > 0)
|
||||||
|
backend->have_xinput = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree (x_devices);
|
||||||
|
#endif /* HAVE_XINPUT */
|
||||||
|
|
||||||
|
default_device:
|
||||||
|
/* fallback code in case:
|
||||||
|
*
|
||||||
|
* - we do not have XInput support compiled in
|
||||||
|
* - we do not have XInput support enabled
|
||||||
|
* - we do not have the XInput extension
|
||||||
|
*
|
||||||
|
* we register two default devices, one for the pointer
|
||||||
|
* and one for the keyboard. this block must also be
|
||||||
|
* executed for the XInput support because XI does not
|
||||||
|
* cover core devices
|
||||||
|
*/
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
|
||||||
|
"id", 0,
|
||||||
|
"name", "Core Pointer",
|
||||||
|
"device-type", CLUTTER_POINTER_DEVICE,
|
||||||
|
"is-core", TRUE,
|
||||||
|
NULL);
|
||||||
|
CLUTTER_NOTE (BACKEND, "Added core pointer device");
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
backend->core_pointer = device;
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
|
||||||
|
"id", 1,
|
||||||
|
"name", "Core Keyboard",
|
||||||
|
"device-type", CLUTTER_KEYBOARD_DEVICE,
|
||||||
|
"is-core", TRUE,
|
||||||
|
NULL);
|
||||||
|
CLUTTER_NOTE (BACKEND, "Added core keyboard device");
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
backend->core_keyboard = device;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
clutter_backend_x11_pre_parse (ClutterBackend *backend,
|
clutter_backend_x11_pre_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -199,9 +308,8 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
|
|||||||
|
|
||||||
clutter_backend_set_resolution (backend, dpi);
|
clutter_backend_set_resolution (backend, dpi);
|
||||||
|
|
||||||
#ifdef HAVE_XINPUT
|
/* register input devices */
|
||||||
_clutter_x11_register_xinput ();
|
clutter_x11_register_input_devices (backend_x11);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (clutter_synchronise)
|
if (clutter_synchronise)
|
||||||
XSynchronize (backend_x11->xdpy, True);
|
XSynchronize (backend_x11->xdpy, True);
|
||||||
@ -644,239 +752,29 @@ clutter_x11_remove_filter (ClutterX11FilterFunc func,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_x11_register_xinput ()
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XINPUT
|
|
||||||
XDeviceInfo *xdevices = NULL;
|
|
||||||
XDeviceInfo *info = NULL;
|
|
||||||
|
|
||||||
XDevice *xdevice = NULL;
|
|
||||||
|
|
||||||
XInputClassInfo *xclass_info = NULL;
|
|
||||||
|
|
||||||
gint opcode, event, error;
|
|
||||||
gint res;
|
|
||||||
gint num_devices = 0;
|
|
||||||
gint num_events = 0;
|
|
||||||
gint i = 0, j = 0;
|
|
||||||
gboolean have_an_xpointer = FALSE;
|
|
||||||
|
|
||||||
ClutterBackendX11 *x11b;
|
|
||||||
ClutterX11XInputDevice *device = NULL;
|
|
||||||
|
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
GSList *input_devices = NULL;
|
|
||||||
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
|
||||||
g_critical ("X11 backend has not been initialised");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!clutter_enable_xinput)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (BACKEND, "Not enabling XInput");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
|
|
||||||
backend_singleton->have_xinput = FALSE;
|
|
||||||
|
|
||||||
/* is the XInput extension available? */
|
|
||||||
res = XQueryExtension (backend_singleton->xdpy, "XInputExtension",
|
|
||||||
&opcode, &event,
|
|
||||||
&error);
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (BACKEND, "X Input extension not available");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
x11b = backend_singleton;
|
|
||||||
|
|
||||||
xdevices = XListInputDevices (x11b->xdpy, &num_devices);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "%d XINPUT devices found", num_devices);
|
|
||||||
|
|
||||||
if (num_devices == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < num_devices; i++)
|
|
||||||
{
|
|
||||||
info = xdevices + i;
|
|
||||||
num_events = 0;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Considering %li with type %d",
|
|
||||||
info->id,
|
|
||||||
info->use);
|
|
||||||
|
|
||||||
/* Only want 'raw' devices themselves not virtual ones */
|
|
||||||
if (info->use == IsXExtensionPointer ||
|
|
||||||
/*info->use == IsXExtensionKeyboard || XInput 1.x is broken */
|
|
||||||
info->use == IsXExtensionDevice)
|
|
||||||
{
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
xdevice = XOpenDevice (backend_singleton->xdpy, info->id);
|
|
||||||
if (clutter_x11_untrap_x_errors () || xdevice == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Create the appropriate Clutter device */
|
|
||||||
device = g_slice_new0 (ClutterX11XInputDevice);
|
|
||||||
|
|
||||||
device->device.id = info->id;
|
|
||||||
|
|
||||||
switch (info->use)
|
|
||||||
{
|
|
||||||
case IsXExtensionPointer:
|
|
||||||
device->device.device_type = CLUTTER_POINTER_DEVICE;
|
|
||||||
have_an_xpointer = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* XInput 1.x is broken for keyboards: */
|
|
||||||
case IsXExtensionKeyboard:
|
|
||||||
device->device.type = CLUTTER_KEYBOARD_DEVICE;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case IsXExtensionDevice:
|
|
||||||
device->device.device_type = CLUTTER_EXTENSION_DEVICE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: some kind of general device_init() call should do below */
|
|
||||||
device->device.click_count = 0;
|
|
||||||
device->device.previous_time = 0;
|
|
||||||
device->device.previous_x = -1;
|
|
||||||
device->device.previous_y = -1;
|
|
||||||
device->device.previous_button_number = -1;
|
|
||||||
|
|
||||||
device->num_events = 0;
|
|
||||||
device->xdevice = xdevice;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Registering XINPUT device with XID: %li",
|
|
||||||
xdevice->device_id);
|
|
||||||
|
|
||||||
/* We must go through all the classes supported by this device and
|
|
||||||
* register the appropriate events we want. Each class only appears
|
|
||||||
* once. We need to store the types with the stage since they are
|
|
||||||
* created dynamically by the server. They are not device specific.
|
|
||||||
*/
|
|
||||||
for (j = 0; j < xdevice->num_classes; j++)
|
|
||||||
{
|
|
||||||
xclass_info = xdevice->classes + j;
|
|
||||||
|
|
||||||
switch (xclass_info->input_class)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
/* XInput 1.x is broken for keyboards: */
|
|
||||||
case KeyClass:
|
|
||||||
DeviceKeyPress (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
|
|
||||||
DeviceKeyRelease (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case ButtonClass:
|
|
||||||
DeviceButtonPress (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
|
|
||||||
DeviceButtonRelease (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ValuatorClass:
|
|
||||||
DeviceMotionNotify (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->use == IsXExtensionPointer && num_events > 0)
|
|
||||||
have_an_xpointer = TRUE;
|
|
||||||
|
|
||||||
device->num_events = num_events;
|
|
||||||
|
|
||||||
input_devices = g_slist_prepend (input_devices, device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree (xdevices);
|
|
||||||
|
|
||||||
if (!have_an_xpointer)
|
|
||||||
{
|
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
/* Something is likely wrong with Xinput setup so we basically
|
|
||||||
* abort here and fall back to lofi regular xinput.
|
|
||||||
*/
|
|
||||||
g_warning ("No usuable XInput pointing devices found");
|
|
||||||
|
|
||||||
for (l = input_devices; l != NULL; l = l->next)
|
|
||||||
g_slice_free (ClutterX11XInputDevice, l->data);
|
|
||||||
|
|
||||||
g_slist_free (input_devices);
|
|
||||||
context->input_devices = NULL;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store the list of input devices */
|
|
||||||
context->input_devices = g_slist_reverse (input_devices);
|
|
||||||
|
|
||||||
/* why yes, we are awesome */
|
|
||||||
backend_singleton->have_xinput = TRUE;
|
|
||||||
#endif /* HAVE_XINPUT */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_x11_unregister_xinput ()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_clutter_x11_select_events (Window xwin)
|
_clutter_x11_select_events (Window xwin)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XINPUT
|
#ifdef HAVE_XINPUT
|
||||||
GSList *list_it;
|
ClutterDeviceManager *manager;
|
||||||
ClutterX11XInputDevice *device = NULL;
|
const GSList *l;
|
||||||
|
|
||||||
ClutterMainContext *context;
|
if (G_UNLIKELY (backend_singleton == NULL))
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
{
|
||||||
g_critical ("X11 backend has not been initialised");
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (list_it = context->input_devices;
|
manager = clutter_device_manager_get_default ();
|
||||||
list_it != NULL;
|
|
||||||
list_it = list_it->next)
|
|
||||||
{
|
|
||||||
device = (ClutterX11XInputDevice *)list_it->data;
|
|
||||||
|
|
||||||
XSelectExtensionEvent (backend_singleton->xdpy,
|
for (l = clutter_device_manager_peek_devices (manager);
|
||||||
xwin,
|
l != NULL;
|
||||||
device->xevent_list,
|
l = l->next)
|
||||||
device->num_events);
|
{
|
||||||
|
ClutterInputDevice *device = l->data;
|
||||||
|
|
||||||
|
_clutter_input_device_x11_select_events (device, backend_singleton, xwin);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_XINPUT */
|
#endif /* HAVE_XINPUT */
|
||||||
}
|
}
|
||||||
@ -884,49 +782,34 @@ _clutter_x11_select_events (Window xwin)
|
|||||||
ClutterInputDevice *
|
ClutterInputDevice *
|
||||||
_clutter_x11_get_device_for_xid (XID id)
|
_clutter_x11_get_device_for_xid (XID id)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XINPUT
|
ClutterDeviceManager *manager;
|
||||||
ClutterMainContext *context;
|
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
if (!backend_singleton)
|
return clutter_device_manager_get_device (manager, (gint) id);
|
||||||
{
|
|
||||||
g_critical ("X11 backend has not been initialised");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (l = context->input_devices; l != NULL; l = l->next)
|
|
||||||
{
|
|
||||||
ClutterX11XInputDevice *device = l->data;
|
|
||||||
|
|
||||||
if (device->xdevice->device_id == id)
|
|
||||||
return (ClutterInputDevice *) device;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_XINPUT */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: This nasty little func needs moving elsewhere.. */
|
/**
|
||||||
|
* clutter_x11_get_input_devices:
|
||||||
|
*
|
||||||
|
* Retrieves a pointer to the list of input devices
|
||||||
|
*
|
||||||
|
* Deprecated: 1.2: Use clutter_device_manager_peek_devices() instead
|
||||||
|
*
|
||||||
|
* Since: 0.8
|
||||||
|
*
|
||||||
|
* Return value: a pointer to the internal list of input devices; the
|
||||||
|
* returned list is owned by Clutter and should not be modified or
|
||||||
|
* freed
|
||||||
|
*/
|
||||||
G_CONST_RETURN GSList *
|
G_CONST_RETURN GSList *
|
||||||
clutter_x11_get_input_devices (void)
|
clutter_x11_get_input_devices (void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XINPUT
|
ClutterDeviceManager *manager;
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
if (!backend_singleton)
|
manager = clutter_device_manager_get_default ();
|
||||||
{
|
|
||||||
g_critical ("X11 backend has not been initialised");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
return clutter_device_manager_peek_devices (manager);
|
||||||
|
|
||||||
return context->input_devices;
|
|
||||||
#else /* !HAVE_XINPUT */
|
|
||||||
return NULL;
|
|
||||||
#endif /* HAVE_XINPUT */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -943,7 +826,7 @@ gboolean
|
|||||||
clutter_x11_has_xinput (void)
|
clutter_x11_has_xinput (void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XINPUT
|
#ifdef HAVE_XINPUT
|
||||||
if (!backend_singleton)
|
if (backend_singleton == NULL)
|
||||||
{
|
{
|
||||||
g_critical ("X11 backend has not been initialised");
|
g_critical ("X11 backend has not been initialised");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -76,10 +76,14 @@ struct _ClutterBackendX11
|
|||||||
Atom atom_NET_WM_NAME;
|
Atom atom_NET_WM_NAME;
|
||||||
Atom atom_UTF8_STRING;
|
Atom atom_UTF8_STRING;
|
||||||
|
|
||||||
|
int xi_event_base;
|
||||||
int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
|
int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
|
||||||
gboolean have_xinput;
|
gboolean have_xinput;
|
||||||
|
|
||||||
Time last_event_time;
|
Time last_event_time;
|
||||||
|
|
||||||
|
ClutterInputDevice *core_pointer;
|
||||||
|
ClutterInputDevice *core_keyboard;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendX11Class
|
struct _ClutterBackendX11Class
|
||||||
@ -125,12 +129,6 @@ clutter_backend_x11_get_features (ClutterBackend *backend);
|
|||||||
XVisualInfo *
|
XVisualInfo *
|
||||||
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11);
|
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11);
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_x11_register_xinput (void);
|
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_x11_unregister_xinput (void);
|
|
||||||
|
|
||||||
ClutterInputDevice *
|
ClutterInputDevice *
|
||||||
_clutter_x11_get_device_for_xid (XID id);
|
_clutter_x11_get_device_for_xid (XID id);
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
/* Clutter.
|
/* Clutter.
|
||||||
* An OpenGL based 'interactive canvas' library.
|
* An OpenGL based 'interactive canvas' library.
|
||||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
*
|
||||||
* Copyright (C) 2006-2007 OpenedHand
|
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd
|
||||||
|
* Copyright (C) 2009, 2010 Intel Corp.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -17,6 +18,10 @@
|
|||||||
* License along with this library; if not, write to the
|
* License along with this library; if not, write to the
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authored by:
|
||||||
|
* Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -183,7 +188,6 @@ _clutter_backend_x11_events_init (ClutterBackend *backend)
|
|||||||
g_source_add_poll (source, &event_source->event_poll_fd);
|
g_source_add_poll (source, &event_source->event_poll_fd);
|
||||||
g_source_set_can_recurse (source, TRUE);
|
g_source_set_can_recurse (source, TRUE);
|
||||||
g_source_attach (source, NULL);
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -263,9 +267,10 @@ set_user_time (ClutterBackendX11 *backend_x11,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* See XInput keyboard comment below HAVE_XINPUT */
|
#ifdef HAVE_XINPUT
|
||||||
static void
|
static void
|
||||||
convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev, XEvent *xevent)
|
convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev,
|
||||||
|
XEvent *xevent)
|
||||||
{
|
{
|
||||||
xevent->xany.type = xevent->xkey.type = xkev->type;
|
xevent->xany.type = xevent->xkey.type = xkev->type;
|
||||||
xevent->xkey.serial = xkev->serial;
|
xevent->xkey.serial = xkev->serial;
|
||||||
@ -416,6 +421,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
ClutterStageWindow *impl;
|
ClutterStageWindow *impl;
|
||||||
gboolean res, not_yet_handled = FALSE;
|
gboolean res, not_yet_handled = FALSE;
|
||||||
Window xwindow, stage_xwindow;
|
Window xwindow, stage_xwindow;
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
@ -424,13 +431,12 @@ event_translate (ClutterBackend *backend,
|
|||||||
if (backend_x11->event_filters)
|
if (backend_x11->event_filters)
|
||||||
{
|
{
|
||||||
GSList *node;
|
GSList *node;
|
||||||
ClutterX11EventFilter *filter;
|
|
||||||
|
|
||||||
node = backend_x11->event_filters;
|
node = backend_x11->event_filters;
|
||||||
|
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
filter = node->data;
|
ClutterX11EventFilter *filter = node->data;
|
||||||
|
|
||||||
switch (filter->func (xevent, event, filter->data))
|
switch (filter->func (xevent, event, filter->data))
|
||||||
{
|
{
|
||||||
@ -448,16 +454,16 @@ event_translate (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Do further processing only on events for the stage window (the x11
|
||||||
* Do further processing only on events for the stage window
|
* filters might be getting events for other windows, so do not mess
|
||||||
* (the x11 filters might be getting events for other windows, so do not
|
* them about.
|
||||||
* mess them about.
|
|
||||||
*/
|
*/
|
||||||
stage = clutter_x11_get_stage_from_window (xwindow);
|
stage = clutter_x11_get_stage_from_window (xwindow);
|
||||||
|
|
||||||
if (stage == NULL)
|
if (stage == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
impl = _clutter_stage_get_window (stage);
|
impl = _clutter_stage_get_window (stage);
|
||||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||||
stage_xwindow = xwindow; /* clutter_x11_get_stage_window (stage); */
|
stage_xwindow = xwindow; /* clutter_x11_get_stage_window (stage); */
|
||||||
@ -621,6 +627,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
|
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
event->key.type = event->type = CLUTTER_KEY_PRESS;
|
event->key.type = event->type = CLUTTER_KEY_PRESS;
|
||||||
|
event->key.device = backend_x11->core_keyboard;
|
||||||
|
|
||||||
translate_key_event (backend, event, xevent);
|
translate_key_event (backend, event, xevent);
|
||||||
|
|
||||||
set_user_time (backend_x11, &xwindow, xevent->xkey.time);
|
set_user_time (backend_x11, &xwindow, xevent->xkey.time);
|
||||||
@ -654,6 +662,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
event->key.type = event->type = CLUTTER_KEY_RELEASE;
|
event->key.type = event->type = CLUTTER_KEY_RELEASE;
|
||||||
|
event->key.device = backend_x11->core_keyboard;
|
||||||
|
|
||||||
translate_key_event (backend, event, xevent);
|
translate_key_event (backend, event, xevent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -666,14 +676,11 @@ event_translate (ClutterBackend *backend,
|
|||||||
/* Input device event handling.. */
|
/* Input device event handling.. */
|
||||||
if (not_yet_handled)
|
if (not_yet_handled)
|
||||||
{
|
{
|
||||||
if (!clutter_x11_has_xinput ())
|
device = backend_x11->core_pointer;
|
||||||
{
|
|
||||||
/* Regular X event */
|
/* Regular X event */
|
||||||
switch (xevent->type)
|
switch (xevent->type)
|
||||||
{
|
{
|
||||||
/* KeyPress / KeyRelease should reside here if XInput
|
|
||||||
* worked properly
|
|
||||||
*/
|
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
switch (xevent->xbutton.button)
|
switch (xevent->xbutton.button)
|
||||||
{
|
{
|
||||||
@ -696,8 +703,9 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->scroll.x = xevent->xbutton.x;
|
event->scroll.x = xevent->xbutton.x;
|
||||||
event->scroll.y = xevent->xbutton.y;
|
event->scroll.y = xevent->xbutton.y;
|
||||||
event->scroll.modifier_state = xevent->xbutton.state;
|
event->scroll.modifier_state = xevent->xbutton.state;
|
||||||
|
event->scroll.device = device;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
event->button.type = event->type = CLUTTER_BUTTON_PRESS;
|
event->button.type = event->type = CLUTTER_BUTTON_PRESS;
|
||||||
event->button.time = xevent->xbutton.time;
|
event->button.time = xevent->xbutton.time;
|
||||||
@ -705,11 +713,13 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->button.y = xevent->xbutton.y;
|
event->button.y = xevent->xbutton.y;
|
||||||
event->button.modifier_state = xevent->xbutton.state;
|
event->button.modifier_state = xevent->xbutton.state;
|
||||||
event->button.button = xevent->xbutton.button;
|
event->button.button = xevent->xbutton.button;
|
||||||
|
event->button.device = device;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_user_time (backend_x11, &xwindow, event->button.time);
|
set_user_time (backend_x11, &xwindow, event->button.time);
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
@ -720,7 +730,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
xevent->xbutton.button == 7)
|
xevent->xbutton.button == 7)
|
||||||
{
|
{
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
||||||
@ -729,6 +739,9 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->button.y = xevent->xbutton.y;
|
event->button.y = xevent->xbutton.y;
|
||||||
event->button.modifier_state = xevent->xbutton.state;
|
event->button.modifier_state = xevent->xbutton.state;
|
||||||
event->button.button = xevent->xbutton.button;
|
event->button.button = xevent->xbutton.button;
|
||||||
|
event->button.device = device;
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MotionNotify:
|
case MotionNotify:
|
||||||
@ -737,9 +750,16 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->motion.x = xevent->xmotion.x;
|
event->motion.x = xevent->xmotion.x;
|
||||||
event->motion.y = xevent->xmotion.y;
|
event->motion.y = xevent->xmotion.y;
|
||||||
event->motion.modifier_state = xevent->xmotion.state;
|
event->motion.modifier_state = xevent->xmotion.state;
|
||||||
|
event->motion.device = device;
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EnterNotify:
|
case EnterNotify:
|
||||||
|
/* we know that we are entering the stage here */
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
CLUTTER_NOTE (EVENT, "Entering the stage");
|
||||||
|
|
||||||
/* Convert enter notifies to motion events because X
|
/* Convert enter notifies to motion events because X
|
||||||
doesn't emit the corresponding motion notify */
|
doesn't emit the corresponding motion notify */
|
||||||
event->motion.type = event->type = CLUTTER_MOTION;
|
event->motion.type = event->type = CLUTTER_MOTION;
|
||||||
@ -747,34 +767,70 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->motion.x = xevent->xcrossing.x;
|
event->motion.x = xevent->xcrossing.x;
|
||||||
event->motion.y = xevent->xcrossing.y;
|
event->motion.y = xevent->xcrossing.y;
|
||||||
event->motion.modifier_state = xevent->xcrossing.state;
|
event->motion.modifier_state = xevent->xcrossing.state;
|
||||||
|
event->motion.source = CLUTTER_ACTOR (stage);
|
||||||
|
event->motion.device = device;
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LeaveNotify:
|
case LeaveNotify:
|
||||||
|
if (device->stage == NULL)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"Discarding LeaveNotify for ButtonRelease "
|
||||||
|
"event off-stage");
|
||||||
|
res = FALSE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we know that we are leaving the stage here */
|
||||||
|
_clutter_input_device_set_stage (device, NULL);
|
||||||
|
CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)",
|
||||||
|
event->crossing.time);
|
||||||
|
|
||||||
event->crossing.type = event->type = CLUTTER_LEAVE;
|
event->crossing.type = event->type = CLUTTER_LEAVE;
|
||||||
event->crossing.time = xevent->xcrossing.time;
|
event->crossing.time = xevent->xcrossing.time;
|
||||||
event->crossing.x = xevent->xcrossing.x;
|
event->crossing.x = xevent->xcrossing.x;
|
||||||
event->crossing.y = xevent->xcrossing.y;
|
event->crossing.y = xevent->xcrossing.y;
|
||||||
|
event->crossing.source = CLUTTER_ACTOR (stage);
|
||||||
|
event->crossing.device = device;
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* ignore every other event */
|
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{ /* XInput fun.. Needs clean up. */
|
/* XInput fun...*/
|
||||||
|
if (!res && clutter_x11_has_xinput ())
|
||||||
|
{
|
||||||
#ifdef HAVE_XINPUT
|
#ifdef HAVE_XINPUT
|
||||||
int *ev_types = backend_x11->event_types;
|
int *ev_types = backend_x11->event_types;
|
||||||
|
int button_press, button_release;
|
||||||
|
int key_press, key_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];
|
||||||
|
key_press = ev_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT];
|
||||||
|
key_release = ev_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT];
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type);
|
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;
|
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent;
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "XINPUT Button press event for %li at %d, %d",
|
device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"XI ButtonPress for %li ('%s') at %d, %d",
|
||||||
xbev->deviceid,
|
xbev->deviceid,
|
||||||
|
device->device_name,
|
||||||
xbev->x,
|
xbev->x,
|
||||||
xbev->y);
|
xbev->y);
|
||||||
|
|
||||||
@ -799,7 +855,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->scroll.x = xbev->x;
|
event->scroll.x = xbev->x;
|
||||||
event->scroll.y = xbev->y;
|
event->scroll.y = xbev->y;
|
||||||
event->scroll.modifier_state = xbev->state;
|
event->scroll.modifier_state = xbev->state;
|
||||||
event->scroll.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
event->scroll.device = device;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -809,19 +865,24 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->button.y = xbev->y;
|
event->button.y = xbev->y;
|
||||||
event->button.modifier_state = xbev->state;
|
event->button.modifier_state = xbev->state;
|
||||||
event->button.button = xbev->button;
|
event->button.button = xbev->button;
|
||||||
event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
event->button.device = device;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_user_time (backend_x11, &xwindow, xbev->time);
|
set_user_time (backend_x11, &xwindow, xbev->time);
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
}
|
}
|
||||||
else if (xevent->type
|
else if (xevent->type == button_release)
|
||||||
== ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT])
|
|
||||||
{
|
{
|
||||||
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
|
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "XINPUT Button release event for %li at %d, %d",
|
device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT, "XI ButtonRelease for %li ('%s') at %d, %d",
|
||||||
xbev->deviceid,
|
xbev->deviceid,
|
||||||
|
device->device_name,
|
||||||
xbev->x,
|
xbev->x,
|
||||||
xbev->y);
|
xbev->y);
|
||||||
|
|
||||||
@ -831,7 +892,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
xbev->button == 6 ||
|
xbev->button == 6 ||
|
||||||
xbev->button == 7)
|
xbev->button == 7)
|
||||||
{
|
{
|
||||||
return FALSE;
|
res = FALSE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
||||||
@ -840,15 +902,20 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->button.y = xbev->y;
|
event->button.y = xbev->y;
|
||||||
event->button.modifier_state = xbev->state;
|
event->button.modifier_state = xbev->state;
|
||||||
event->button.button = xbev->button;
|
event->button.button = xbev->button;
|
||||||
event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
event->button.device = device;
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
}
|
}
|
||||||
else if (xevent->type
|
else if (xevent->type == motion_notify)
|
||||||
== ev_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT])
|
|
||||||
{
|
{
|
||||||
XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
|
XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
|
||||||
|
|
||||||
CLUTTER_NOTE(EVENT, "XINPUT Motion event for %li at %d, %d",
|
device = _clutter_x11_get_device_for_xid (xmev->deviceid);
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT, "XI Motion for %li ('%s') at %d, %d",
|
||||||
xmev->deviceid,
|
xmev->deviceid,
|
||||||
|
device->device_name,
|
||||||
xmev->x,
|
xmev->x,
|
||||||
xmev->y);
|
xmev->y);
|
||||||
|
|
||||||
@ -857,39 +924,30 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->motion.x = xmev->x;
|
event->motion.x = xmev->x;
|
||||||
event->motion.y = xmev->y;
|
event->motion.y = xmev->y;
|
||||||
event->motion.modifier_state = xmev->state;
|
event->motion.modifier_state = xmev->state;
|
||||||
event->motion.device = _clutter_x11_get_device_for_xid (xmev->deviceid);
|
event->motion.device = device;
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
/* the Xinput handling of key presses/releases disabled for now since
|
|
||||||
* it makes keyrepeat, and key presses and releases outside the window
|
|
||||||
* not generate events even when the window has focus
|
|
||||||
*/
|
|
||||||
|
|
||||||
else if (xevent->type
|
res = TRUE;
|
||||||
== ev_types [CLUTTER_X11_XINPUT_KEY_PRESS_EVENT])
|
}
|
||||||
|
else if (xevent->type == key_press || xevent->type == key_release)
|
||||||
{
|
{
|
||||||
|
/* the XInput 1.x handling of key presses/releases is broken:
|
||||||
|
* it makes key repeat, key presses and releases outside the
|
||||||
|
* window not generate events even when the window has focus
|
||||||
|
*/
|
||||||
|
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *) xevent;
|
||||||
XEvent xevent_converted;
|
XEvent xevent_converted;
|
||||||
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *)xevent;
|
|
||||||
|
|
||||||
convert_xdevicekey_to_xkey (xkev, &xevent_converted);
|
convert_xdevicekey_to_xkey (xkev, &xevent_converted);
|
||||||
|
|
||||||
event->key.type = event->type = CLUTTER_KEY_PRESS;
|
event->key.type = event->type = (xevent->type == key_press)
|
||||||
|
? CLUTTER_KEY_PRESS
|
||||||
|
: CLUTTER_KEY_RELEASE;
|
||||||
|
|
||||||
translate_key_event (backend, event, &xevent_converted);
|
translate_key_event (backend, event, &xevent_converted);
|
||||||
|
|
||||||
|
if (xevent->type == key_press)
|
||||||
set_user_time (backend_x11, &xwindow, xkev->time);
|
set_user_time (backend_x11, &xwindow, xkev->time);
|
||||||
}
|
}
|
||||||
else if (xevent->type
|
|
||||||
== ev_types [CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT])
|
|
||||||
{
|
|
||||||
XEvent xevent_converted;
|
|
||||||
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *)xevent;
|
|
||||||
|
|
||||||
convert_xdevicekey_to_xkey (xkev, &xevent_converted);
|
|
||||||
|
|
||||||
event->key.type = event->type = CLUTTER_KEY_RELEASE;
|
|
||||||
translate_key_event (backend, event, &xevent_converted);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
#endif /* HAVE_XINPUT */
|
#endif /* HAVE_XINPUT */
|
||||||
{
|
{
|
||||||
@ -897,8 +955,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
res = FALSE;
|
res = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
out:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
221
clutter/x11/clutter-input-device-x11.c
Normal file
221
clutter/x11/clutter-input-device-x11.c
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-input-device-x11.h"
|
||||||
|
#include "../clutter-debug.h"
|
||||||
|
#include "../clutter-private.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
#include <X11/extensions/XInput.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _ClutterInputDeviceClass ClutterInputDeviceX11Class;
|
||||||
|
|
||||||
|
/* a specific X11 input device */
|
||||||
|
struct _ClutterInputDeviceX11
|
||||||
|
{
|
||||||
|
ClutterInputDevice device;
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
XDevice *xdevice;
|
||||||
|
XEventClass xevent_list[5]; /* MAX 5 event types */
|
||||||
|
int num_events;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
guint is_core : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_IS_CORE
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterInputDeviceX11,
|
||||||
|
clutter_input_device_x11,
|
||||||
|
CLUTTER_TYPE_INPUT_DEVICE);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_x11_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceX11 *self = CLUTTER_INPUT_DEVICE_X11 (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_IS_CORE:
|
||||||
|
self->is_core = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_x11_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceX11 *self = CLUTTER_INPUT_DEVICE_X11 (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_IS_CORE:
|
||||||
|
g_value_set_boolean (value, self->is_core);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_x11_class_init (ClutterInputDeviceX11Class *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
gobject_class->set_property = clutter_input_device_x11_set_property;
|
||||||
|
gobject_class->get_property = clutter_input_device_x11_get_property;
|
||||||
|
|
||||||
|
pspec = g_param_spec_boolean ("is-core",
|
||||||
|
"Is Core",
|
||||||
|
"Whether the device is a core one",
|
||||||
|
FALSE,
|
||||||
|
CLUTTER_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_IS_CORE, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_x11_init (ClutterInputDeviceX11 *self)
|
||||||
|
{
|
||||||
|
self->is_core = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
_clutter_input_device_x11_construct (ClutterInputDevice *device,
|
||||||
|
ClutterBackendX11 *backend)
|
||||||
|
{
|
||||||
|
int n_events = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
ClutterInputDeviceX11 *device_x11;
|
||||||
|
XDevice *x_device = NULL;
|
||||||
|
gint device_id;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
|
||||||
|
device_id = clutter_input_device_get_device_id (device);
|
||||||
|
|
||||||
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
|
/* retrieve the X11 device */
|
||||||
|
x_device = XOpenDevice (backend->xdpy, device_id);
|
||||||
|
|
||||||
|
if (clutter_x11_untrap_x_errors () || x_device == NULL)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "Unable to open device %i", device_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_x11->xdevice = x_device;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND,
|
||||||
|
"Registering XINPUT device with XID: %li",
|
||||||
|
x_device->device_id);
|
||||||
|
|
||||||
|
/* We must go through all the classes supported by this device and
|
||||||
|
* register the appropriate events we want. Each class only appears
|
||||||
|
* once. We need to store the types with the stage since they are
|
||||||
|
* created dynamically by the server. They are not device specific.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < x_device->num_classes; i++)
|
||||||
|
{
|
||||||
|
XInputClassInfo *xclass_info = x_device->classes + i;
|
||||||
|
int *button_press, *button_release, *motion_notify;
|
||||||
|
int *key_press, *key_release;
|
||||||
|
|
||||||
|
button_press =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
|
||||||
|
button_release =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
|
||||||
|
motion_notify =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT];
|
||||||
|
|
||||||
|
key_press =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT];
|
||||||
|
key_release =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT];
|
||||||
|
|
||||||
|
switch (xclass_info->input_class)
|
||||||
|
{
|
||||||
|
/* event though XInput 1.x is broken for keyboard-like devices
|
||||||
|
* it might still be useful to track them down; the core keyboard
|
||||||
|
* will handle the right events anyway
|
||||||
|
*/
|
||||||
|
case KeyClass:
|
||||||
|
DeviceKeyPress (x_device,
|
||||||
|
*key_press,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
|
||||||
|
DeviceKeyRelease (x_device,
|
||||||
|
*key_release,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ButtonClass:
|
||||||
|
DeviceButtonPress (x_device,
|
||||||
|
*button_press,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
|
||||||
|
DeviceButtonRelease (x_device,
|
||||||
|
*button_release,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ValuatorClass:
|
||||||
|
DeviceMotionNotify (x_device,
|
||||||
|
*motion_notify,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device_x11->num_events = n_events;
|
||||||
|
#endif /* HAVE_XINPUT */
|
||||||
|
|
||||||
|
return n_events;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_input_device_x11_select_events (ClutterInputDevice *device,
|
||||||
|
ClutterBackendX11 *backend_x11,
|
||||||
|
Window xwin)
|
||||||
|
{
|
||||||
|
#if HAVE_XINPUT
|
||||||
|
ClutterInputDeviceX11 *device_x11;
|
||||||
|
|
||||||
|
device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
|
||||||
|
|
||||||
|
if (device_x11->xdevice == None || device_x11->num_events == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XSelectExtensionEvent (backend_x11->xdpy, xwin,
|
||||||
|
device_x11->xevent_list,
|
||||||
|
device_x11->num_events);
|
||||||
|
#endif /* HAVE_XINPUT */
|
||||||
|
}
|
25
clutter/x11/clutter-input-device-x11.h
Normal file
25
clutter/x11/clutter-input-device-x11.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef __CLUTTER_INPUT_DEVICE_X11_H__
|
||||||
|
#define __CLUTTER_INPUT_DEVICE_X11_H__
|
||||||
|
|
||||||
|
#include <clutter/clutter-input-device.h>
|
||||||
|
#include "clutter-backend-x11.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_INPUT_DEVICE_X11 (clutter_input_device_x11_get_type ())
|
||||||
|
#define CLUTTER_INPUT_DEVICE_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_X11, ClutterInputDeviceX11))
|
||||||
|
#define CLUTTER_IS_INPUT_DEVICE_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_X11))
|
||||||
|
|
||||||
|
typedef struct _ClutterInputDeviceX11 ClutterInputDeviceX11;
|
||||||
|
|
||||||
|
GType clutter_input_device_x11_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
gint _clutter_input_device_x11_construct (ClutterInputDevice *device,
|
||||||
|
ClutterBackendX11 *backend);
|
||||||
|
void _clutter_input_device_x11_select_events (ClutterInputDevice *device,
|
||||||
|
ClutterBackendX11 *backend,
|
||||||
|
Window xwin);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_INPUT_DEVICE_X11_H__ */
|
@ -121,7 +121,9 @@ gboolean clutter_x11_has_event_retrieval (void);
|
|||||||
|
|
||||||
ClutterStage *clutter_x11_get_stage_from_window (Window win);
|
ClutterStage *clutter_x11_get_stage_from_window (Window win);
|
||||||
|
|
||||||
|
#ifndef CLUTTER_DISABLE_DEPRECATED
|
||||||
G_CONST_RETURN GSList* clutter_x11_get_input_devices (void);
|
G_CONST_RETURN GSList* clutter_x11_get_input_devices (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
void clutter_x11_enable_xinput (void);
|
void clutter_x11_enable_xinput (void);
|
||||||
gboolean clutter_x11_has_xinput (void);
|
gboolean clutter_x11_has_xinput (void);
|
||||||
|
@ -139,6 +139,8 @@
|
|||||||
<xi:include href="xml/clutter-main.xml"/>
|
<xi:include href="xml/clutter-main.xml"/>
|
||||||
<xi:include href="xml/clutter-shader.xml"/>
|
<xi:include href="xml/clutter-shader.xml"/>
|
||||||
<xi:include href="xml/clutter-stage-manager.xml"/>
|
<xi:include href="xml/clutter-stage-manager.xml"/>
|
||||||
|
<xi:include href="xml/clutter-input-device.xml"/>
|
||||||
|
<xi:include href="xml/clutter-device-manager.xml"/>
|
||||||
<xi:include href="xml/clutter-units.xml"/>
|
<xi:include href="xml/clutter-units.xml"/>
|
||||||
<xi:include href="xml/clutter-util.xml"/>
|
<xi:include href="xml/clutter-util.xml"/>
|
||||||
<xi:include href="xml/clutter-feature.xml"/>
|
<xi:include href="xml/clutter-feature.xml"/>
|
||||||
|
@ -404,6 +404,7 @@ clutter_actor_create_pango_layout
|
|||||||
clutter_actor_is_in_clone_paint
|
clutter_actor_is_in_clone_paint
|
||||||
clutter_actor_set_text_direction
|
clutter_actor_set_text_direction
|
||||||
clutter_actor_get_text_direction
|
clutter_actor_get_text_direction
|
||||||
|
clutter_actor_has_pointer
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
ClutterActorBox
|
ClutterActorBox
|
||||||
@ -940,7 +941,6 @@ ClutterMotionEvent
|
|||||||
ClutterScrollEvent
|
ClutterScrollEvent
|
||||||
ClutterStageStateEvent
|
ClutterStageStateEvent
|
||||||
ClutterCrossingEvent
|
ClutterCrossingEvent
|
||||||
ClutterInputDevice
|
|
||||||
clutter_event_new
|
clutter_event_new
|
||||||
clutter_event_copy
|
clutter_event_copy
|
||||||
clutter_event_free
|
clutter_event_free
|
||||||
@ -977,13 +977,9 @@ clutter_event_get_related
|
|||||||
clutter_event_get_scroll_direction
|
clutter_event_get_scroll_direction
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
ClutterInputDeviceType
|
|
||||||
clutter_event_get_device
|
clutter_event_get_device
|
||||||
clutter_event_get_device_id
|
clutter_event_get_device_id
|
||||||
clutter_event_get_device_type
|
clutter_event_get_device_type
|
||||||
clutter_get_input_device_for_id
|
|
||||||
clutter_input_device_get_device_id
|
|
||||||
clutter_input_device_get_device_type
|
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
clutter_get_current_event_time
|
clutter_get_current_event_time
|
||||||
@ -996,6 +992,51 @@ ClutterAnyEvent
|
|||||||
clutter_event_get_type
|
clutter_event_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>clutter-input-device</FILE>
|
||||||
|
<TITLE>ClutterInputDevice</TITLE>
|
||||||
|
ClutterInputDeviceType
|
||||||
|
ClutterInputDevice
|
||||||
|
ClutterInputDeviceClass
|
||||||
|
clutter_input_device_get_device_id
|
||||||
|
clutter_input_device_get_device_type
|
||||||
|
clutter_input_device_get_device_name
|
||||||
|
clutter_input_device_get_device_coords
|
||||||
|
clutter_input_device_get_pointer_actor
|
||||||
|
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
CLUTTER_TYPE_INPUT_DEVICE
|
||||||
|
CLUTTER_INPUT_DEVICE
|
||||||
|
CLUTTER_INPUT_DEVICE_CLASS
|
||||||
|
CLUTTER_IS_INPUT_DEVICE
|
||||||
|
CLUTTER_IS_INPUT_DEVICE_CLASS
|
||||||
|
CLUTTER_INPUT_DEVICE_GET_CLASS
|
||||||
|
|
||||||
|
<SUBSECTION Private>
|
||||||
|
clutter_input_device_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>clutter-device-manager</FILE>
|
||||||
|
<TITLE>ClutterDeviceManager</TITLE>
|
||||||
|
ClutterDeviceManager
|
||||||
|
clutter_device_manager_get_default
|
||||||
|
clutter_device_manager_list_devices
|
||||||
|
clutter_device_manager_peek_devices
|
||||||
|
clutter_device_manager_get_device
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
|
clutter_get_input_device_for_id
|
||||||
|
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
CLUTTER_TYPE_DEVICE_MANAGER
|
||||||
|
CLUTTER_DEVICE_MANAGER
|
||||||
|
CLUTTER_IS_DEVICE_MANAGER
|
||||||
|
|
||||||
|
<SUBSECTION Private>
|
||||||
|
clutter_device_manager_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>clutter-main</FILE>
|
<FILE>clutter-main</FILE>
|
||||||
<TITLE>General</TITLE>
|
<TITLE>General</TITLE>
|
||||||
|
@ -40,3 +40,5 @@ clutter_fixed_layout_get_type
|
|||||||
clutter_bin_layout_get_type
|
clutter_bin_layout_get_type
|
||||||
clutter_flow_layout_get_type
|
clutter_flow_layout_get_type
|
||||||
clutter_box_layout_get_type
|
clutter_box_layout_get_type
|
||||||
|
clutter_input_device_get_type
|
||||||
|
clutter_device_manager_get_type
|
||||||
|
@ -9,7 +9,31 @@ typedef struct {
|
|||||||
|
|
||||||
} TestDevicesApp;
|
} TestDevicesApp;
|
||||||
|
|
||||||
|
static const gchar *
|
||||||
|
device_type_name (ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceType d_type;
|
||||||
|
|
||||||
|
d_type = clutter_input_device_get_device_type (device);
|
||||||
|
switch (d_type)
|
||||||
|
{
|
||||||
|
case CLUTTER_POINTER_DEVICE:
|
||||||
|
return "Pointer";
|
||||||
|
|
||||||
|
case CLUTTER_KEYBOARD_DEVICE:
|
||||||
|
return "Keyboard";
|
||||||
|
|
||||||
|
case CLUTTER_EXTENSION_DEVICE:
|
||||||
|
return "Extension";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
g_warn_if_reached ();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
stage_motion_event_cb (ClutterActor *actor,
|
stage_motion_event_cb (ClutterActor *actor,
|
||||||
@ -24,6 +48,11 @@ stage_motion_event_cb (ClutterActor *actor,
|
|||||||
|
|
||||||
hand = g_hash_table_lookup (app->devices, device);
|
hand = g_hash_table_lookup (app->devices, device);
|
||||||
|
|
||||||
|
g_print ("Device: '%s' (id:%d, type:%s)\n",
|
||||||
|
clutter_input_device_get_device_name (device),
|
||||||
|
clutter_input_device_get_device_id (device),
|
||||||
|
device_type_name (device));
|
||||||
|
|
||||||
if (hand != NULL)
|
if (hand != NULL)
|
||||||
{
|
{
|
||||||
gfloat event_x, event_y;
|
gfloat event_x, event_y;
|
||||||
@ -43,6 +72,7 @@ test_devices_main (int argc, char **argv)
|
|||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
TestDevicesApp *app;
|
TestDevicesApp *app;
|
||||||
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
const GSList *stage_devices, *l;
|
const GSList *stage_devices, *l;
|
||||||
|
|
||||||
/* force enabling X11 support */
|
/* force enabling X11 support */
|
||||||
@ -63,10 +93,11 @@ test_devices_main (int argc, char **argv)
|
|||||||
|
|
||||||
clutter_actor_show_all (stage);
|
clutter_actor_show_all (stage);
|
||||||
|
|
||||||
stage_devices = clutter_x11_get_input_devices ();
|
manager = clutter_device_manager_get_default ();
|
||||||
|
stage_devices = clutter_device_manager_peek_devices (manager);
|
||||||
|
|
||||||
if (stage_devices == NULL)
|
if (stage_devices == NULL)
|
||||||
g_error ("No extended input devices found.");
|
g_error ("No input devices found.");
|
||||||
|
|
||||||
for (l = stage_devices; l != NULL; l = l->next)
|
for (l = stage_devices; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
@ -74,12 +105,15 @@ test_devices_main (int argc, char **argv)
|
|||||||
ClutterInputDeviceType device_type;
|
ClutterInputDeviceType device_type;
|
||||||
ClutterActor *hand = NULL;
|
ClutterActor *hand = NULL;
|
||||||
|
|
||||||
device_type = clutter_input_device_get_device_type (device);
|
g_print ("got a %s device '%s' with id %d...\n",
|
||||||
if (device_type == CLUTTER_POINTER_DEVICE)
|
device_type_name (device),
|
||||||
{
|
clutter_input_device_get_device_name (device),
|
||||||
g_print ("got a pointer device with id %d...\n",
|
|
||||||
clutter_input_device_get_device_id (device));
|
clutter_input_device_get_device_id (device));
|
||||||
|
|
||||||
|
device_type = clutter_input_device_get_device_type (device);
|
||||||
|
if (device_type == CLUTTER_POINTER_DEVICE ||
|
||||||
|
device_type == CLUTTER_EXTENSION_DEVICE)
|
||||||
|
{
|
||||||
hand = clutter_texture_new_from_file (TESTS_DATADIR
|
hand = clutter_texture_new_from_file (TESTS_DATADIR
|
||||||
G_DIR_SEPARATOR_S
|
G_DIR_SEPARATOR_S
|
||||||
"redhand.png",
|
"redhand.png",
|
||||||
|
@ -27,6 +27,12 @@ get_event_type_name (const ClutterEvent *event)
|
|||||||
case CLUTTER_LEAVE:
|
case CLUTTER_LEAVE:
|
||||||
return "LEAVE";
|
return "LEAVE";
|
||||||
|
|
||||||
|
case CLUTTER_MOTION:
|
||||||
|
return "MOTION";
|
||||||
|
|
||||||
|
case CLUTTER_DELETE:
|
||||||
|
return "DELETE";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "EVENT";
|
return "EVENT";
|
||||||
}
|
}
|
||||||
@ -124,29 +130,36 @@ fill_keybuf (char *keybuf, ClutterKeyEvent *event)
|
|||||||
/* printable character, if any (ß, ∑) */
|
/* printable character, if any (ß, ∑) */
|
||||||
len = g_unichar_to_utf8 (event->unicode_value, utf8);
|
len = g_unichar_to_utf8 (event->unicode_value, utf8);
|
||||||
utf8[len] = '\0';
|
utf8[len] = '\0';
|
||||||
sprintf(keybuf, "'%s' ", utf8);
|
sprintf (keybuf, "'%s' ", utf8);
|
||||||
|
|
||||||
/* key combination (<Mod1>s, <Shift><Mod1>S, <Ctrl><Mod1>Delete) */
|
/* key combination (<Mod1>s, <Shift><Mod1>S, <Ctrl><Mod1>Delete) */
|
||||||
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval),
|
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval), utf8);
|
||||||
utf8);
|
|
||||||
utf8[len] = '\0';
|
utf8[len] = '\0';
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_SHIFT_MASK)
|
if (event->modifier_state & CLUTTER_SHIFT_MASK)
|
||||||
strcat (keybuf, "<Shift>");
|
strcat (keybuf, "<Shift>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_LOCK_MASK)
|
if (event->modifier_state & CLUTTER_LOCK_MASK)
|
||||||
strcat (keybuf, "<Lock>");
|
strcat (keybuf, "<Lock>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_CONTROL_MASK)
|
if (event->modifier_state & CLUTTER_CONTROL_MASK)
|
||||||
strcat (keybuf, "<Control>");
|
strcat (keybuf, "<Control>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD1_MASK)
|
if (event->modifier_state & CLUTTER_MOD1_MASK)
|
||||||
strcat (keybuf, "<Mod1>");
|
strcat (keybuf, "<Mod1>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD2_MASK)
|
if (event->modifier_state & CLUTTER_MOD2_MASK)
|
||||||
strcat (keybuf, "<Mod2>");
|
strcat (keybuf, "<Mod2>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD3_MASK)
|
if (event->modifier_state & CLUTTER_MOD3_MASK)
|
||||||
strcat (keybuf, "<Mod3>");
|
strcat (keybuf, "<Mod3>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD4_MASK)
|
if (event->modifier_state & CLUTTER_MOD4_MASK)
|
||||||
strcat (keybuf, "<Mod4>");
|
strcat (keybuf, "<Mod4>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD5_MASK)
|
if (event->modifier_state & CLUTTER_MOD5_MASK)
|
||||||
strcat (keybuf, "<Mod5>");
|
strcat (keybuf, "<Mod5>");
|
||||||
|
|
||||||
strcat (keybuf, utf8);
|
strcat (keybuf, utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,62 +169,83 @@ input_cb (ClutterActor *actor,
|
|||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
ClutterStage *stage = CLUTTER_STAGE (clutter_stage_get_default ());
|
ClutterStage *stage = CLUTTER_STAGE (clutter_stage_get_default ());
|
||||||
gchar keybuf[128], *source = (gchar*)data;
|
ClutterActor *source_actor = clutter_event_get_source (event);
|
||||||
|
gchar keybuf[128];
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case CLUTTER_KEY_PRESS:
|
case CLUTTER_KEY_PRESS:
|
||||||
fill_keybuf (keybuf, &event->key);
|
fill_keybuf (keybuf, &event->key);
|
||||||
printf ("[%s] KEY PRESS %s", source, keybuf);
|
printf ("[%s] KEY PRESS %s",
|
||||||
|
clutter_actor_get_name (source_actor),
|
||||||
|
keybuf);
|
||||||
break;
|
break;
|
||||||
case CLUTTER_KEY_RELEASE:
|
case CLUTTER_KEY_RELEASE:
|
||||||
fill_keybuf (keybuf, &event->key);
|
fill_keybuf (keybuf, &event->key);
|
||||||
printf ("[%s] KEY RELEASE %s", source, keybuf);
|
printf ("[%s] KEY RELEASE %s",
|
||||||
|
clutter_actor_get_name (source_actor),
|
||||||
|
keybuf);
|
||||||
break;
|
break;
|
||||||
case CLUTTER_MOTION:
|
case CLUTTER_MOTION:
|
||||||
g_print ("[%s] MOTION", source);
|
g_print ("[%s] MOTION",
|
||||||
|
clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_ENTER:
|
case CLUTTER_ENTER:
|
||||||
g_print ("[%s] ENTER", source);
|
g_print ("[%s] ENTER (from:%s)",
|
||||||
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_related (event) != NULL
|
||||||
|
? clutter_actor_get_name (clutter_event_get_related (event))
|
||||||
|
: "<out of stage>");
|
||||||
break;
|
break;
|
||||||
case CLUTTER_LEAVE:
|
case CLUTTER_LEAVE:
|
||||||
g_print ("[%s] LEAVE", source);
|
g_print ("[%s] LEAVE (to:%s)",
|
||||||
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_related (event) != NULL
|
||||||
|
? clutter_actor_get_name (clutter_event_get_related (event))
|
||||||
|
: "<out of stage>");
|
||||||
break;
|
break;
|
||||||
case CLUTTER_BUTTON_PRESS:
|
case CLUTTER_BUTTON_PRESS:
|
||||||
g_print ("[%s] BUTTON PRESS (click count:%i)",
|
g_print ("[%s] BUTTON PRESS (button:%i, click count:%i)",
|
||||||
source, event->button.click_count);
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_button (event),
|
||||||
|
clutter_event_get_click_count (event));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_BUTTON_RELEASE:
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
g_print ("[%s] BUTTON RELEASE (click count:%i)",
|
g_print ("[%s] BUTTON RELEASE (button:%i, click count:%i)",
|
||||||
source, event->button.click_count);
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_button (event),
|
||||||
|
clutter_event_get_click_count (event));
|
||||||
|
|
||||||
if (clutter_event_get_source (event) == CLUTTER_ACTOR (stage))
|
if (source_actor == CLUTTER_ACTOR (stage))
|
||||||
clutter_stage_set_key_focus (stage, NULL);
|
clutter_stage_set_key_focus (stage, NULL);
|
||||||
else if (clutter_event_get_source (event) == actor
|
else if (source_actor == actor &&
|
||||||
&& clutter_actor_get_parent (actor) == CLUTTER_ACTOR (stage))
|
clutter_actor_get_parent (actor) == CLUTTER_ACTOR (stage))
|
||||||
clutter_stage_set_key_focus (stage, actor);
|
clutter_stage_set_key_focus (stage, actor);
|
||||||
break;
|
break;
|
||||||
case CLUTTER_SCROLL:
|
case CLUTTER_SCROLL:
|
||||||
g_print ("[%s] BUTTON SCROLL (click count:%i)",
|
g_print ("[%s] BUTTON SCROLL (direction:%s)",
|
||||||
source, event->button.click_count);
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_scroll_direction (event) == CLUTTER_SCROLL_UP
|
||||||
|
? "up"
|
||||||
|
: "down");
|
||||||
break;
|
break;
|
||||||
case CLUTTER_STAGE_STATE:
|
case CLUTTER_STAGE_STATE:
|
||||||
g_print ("[%s] STAGE STATE", source);
|
g_print ("[%s] STAGE STATE", clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_DESTROY_NOTIFY:
|
case CLUTTER_DESTROY_NOTIFY:
|
||||||
g_print ("[%s] DESTROY NOTIFY", source);
|
g_print ("[%s] DESTROY NOTIFY", clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_CLIENT_MESSAGE:
|
case CLUTTER_CLIENT_MESSAGE:
|
||||||
g_print ("[%s] CLIENT MESSAGE", source);
|
g_print ("[%s] CLIENT MESSAGE", clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_DELETE:
|
case CLUTTER_DELETE:
|
||||||
g_print ("[%s] DELETE", source);
|
g_print ("[%s] DELETE", clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_NOTHING:
|
case CLUTTER_NOTHING:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clutter_event_get_source (event) == actor)
|
if (source_actor == actor)
|
||||||
g_print (" *source*");
|
g_print (" *source*");
|
||||||
|
|
||||||
g_print ("\n");
|
g_print ("\n");
|
||||||
@ -234,8 +268,8 @@ test_events_main (int argc, char *argv[])
|
|||||||
|
|
||||||
|
|
||||||
stage = clutter_stage_get_default ();
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_actor_set_name (stage, "Stage");
|
||||||
g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage");
|
g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage");
|
||||||
|
|
||||||
g_signal_connect (stage, "fullscreen",
|
g_signal_connect (stage, "fullscreen",
|
||||||
G_CALLBACK (stage_state_cb), "fullscreen");
|
G_CALLBACK (stage_state_cb), "fullscreen");
|
||||||
g_signal_connect (stage, "unfullscreen",
|
g_signal_connect (stage, "unfullscreen",
|
||||||
@ -244,24 +278,21 @@ test_events_main (int argc, char *argv[])
|
|||||||
G_CALLBACK (stage_state_cb), "activate");
|
G_CALLBACK (stage_state_cb), "activate");
|
||||||
g_signal_connect (stage, "deactivate",
|
g_signal_connect (stage, "deactivate",
|
||||||
G_CALLBACK (stage_state_cb), "deactivate");
|
G_CALLBACK (stage_state_cb), "deactivate");
|
||||||
|
/*g_signal_connect (stage, "captured-event", G_CALLBACK (capture_cb), NULL);*/
|
||||||
g_signal_connect (stage, "captured-event", G_CALLBACK (capture_cb), NULL);
|
|
||||||
|
|
||||||
focus_box = clutter_rectangle_new_with_color (&ncol);
|
focus_box = clutter_rectangle_new_with_color (&ncol);
|
||||||
|
clutter_actor_set_name (focus_box, "Focus Box");
|
||||||
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
||||||
|
|
||||||
actor = clutter_rectangle_new_with_color (&rcol);
|
actor = clutter_rectangle_new_with_color (&rcol);
|
||||||
|
clutter_actor_set_name (actor, "Red Box");
|
||||||
clutter_actor_set_size (actor, 100, 100);
|
clutter_actor_set_size (actor, 100, 100);
|
||||||
clutter_actor_set_position (actor, 100, 100);
|
clutter_actor_set_position (actor, 100, 100);
|
||||||
|
|
||||||
clutter_actor_set_reactive (actor, TRUE);
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||||
|
|
||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "red box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "red box");
|
||||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
|
||||||
/* Toggle motion - enter/leave capture */
|
/* Toggle motion - enter/leave capture */
|
||||||
g_signal_connect (actor, "button-press-event",
|
g_signal_connect (actor, "button-press-event",
|
||||||
G_CALLBACK (red_button_cb), NULL);
|
G_CALLBACK (red_button_cb), NULL);
|
||||||
@ -269,27 +300,22 @@ test_events_main (int argc, char *argv[])
|
|||||||
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor);
|
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor);
|
||||||
|
|
||||||
actor = clutter_rectangle_new_with_color (&gcol);
|
actor = clutter_rectangle_new_with_color (&gcol);
|
||||||
|
clutter_actor_set_name (actor, "Green Box");
|
||||||
clutter_actor_set_size (actor, 100, 100);
|
clutter_actor_set_size (actor, 100, 100);
|
||||||
clutter_actor_set_position (actor, 250, 100);
|
clutter_actor_set_position (actor, 250, 100);
|
||||||
|
|
||||||
clutter_actor_set_reactive (actor, TRUE);
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||||
|
|
||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "green box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "green box");
|
||||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
|
||||||
g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL);
|
g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL);
|
||||||
|
|
||||||
actor = clutter_rectangle_new_with_color (&bcol);
|
actor = clutter_rectangle_new_with_color (&bcol);
|
||||||
|
clutter_actor_set_name (actor, "Blue Box");
|
||||||
clutter_actor_set_size (actor, 100, 100);
|
clutter_actor_set_size (actor, 100, 100);
|
||||||
clutter_actor_set_position (actor, 400, 100);
|
clutter_actor_set_position (actor, 400, 100);
|
||||||
|
|
||||||
clutter_actor_set_reactive (actor, TRUE);
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
||||||
|
|
||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
||||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
@ -299,20 +325,19 @@ test_events_main (int argc, char *argv[])
|
|||||||
|
|
||||||
/* non reactive */
|
/* non reactive */
|
||||||
actor = clutter_rectangle_new_with_color (&ncol);
|
actor = clutter_rectangle_new_with_color (&ncol);
|
||||||
|
clutter_actor_set_name (actor, "Black Box");
|
||||||
clutter_actor_set_size (actor, 400, 50);
|
clutter_actor_set_size (actor, 400, 50);
|
||||||
clutter_actor_set_position (actor, 100, 250);
|
clutter_actor_set_position (actor, 100, 250);
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
||||||
|
|
||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
||||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
|
||||||
g_signal_connect (stage, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (stage, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
|
||||||
/* non reactive group, with reactive child */
|
/* non reactive group, with reactive child */
|
||||||
actor = clutter_rectangle_new_with_color (&ycol);
|
actor = clutter_rectangle_new_with_color (&ycol);
|
||||||
|
clutter_actor_set_name (actor, "Yellow Box");
|
||||||
clutter_actor_set_size (actor, 100, 100);
|
clutter_actor_set_size (actor, 100, 100);
|
||||||
clutter_actor_set_reactive (actor, TRUE);
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user