mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
Merge remote branch 'master' into texture-debugging
Conflicts: clutter/cogl/cogl/cogl-context.h
This commit is contained in:
commit
145cc9d3df
1
.gitignore
vendored
1
.gitignore
vendored
@ -240,6 +240,7 @@ TAGS
|
||||
/tests/conform/test-script-named-object
|
||||
/tests/conform/test-actor-destruction
|
||||
/tests/conform/test-color-operators
|
||||
/tests/conform/test-cogl-texture-mipmaps
|
||||
/tests/micro-bench/test-text-perf
|
||||
/tests/micro-bench/test-text
|
||||
/tests/micro-bench/test-picking
|
||||
|
49
NEWS
49
NEWS
@ -1,3 +1,52 @@
|
||||
Clutter 1.1.6 (18/01/2010)
|
||||
===============================================================================
|
||||
|
||||
* List of changes since Clutter 1.1.4
|
||||
|
||||
o Some fixes for the Win32 backend (bug #1905).
|
||||
|
||||
o Profiling support via the UProf library. Configure with
|
||||
--enable-profile to get a report after each Clutter application is
|
||||
run.
|
||||
|
||||
o Improved conformance tests with coverage reports via gcov.
|
||||
|
||||
o ClutterTexture no longer tries to read back texture data into
|
||||
g_malloc'd memory on unrealize (bug #1842).
|
||||
|
||||
o The CGL_* defines from cogl-defines.h have been removed. These
|
||||
should not have been used by any applications, but if they were
|
||||
being used then please replace them either with the Cogl enums or
|
||||
with the appropriate GL_* enum if you are using GL directly.
|
||||
|
||||
o Added a delete-event signal to the stage.
|
||||
|
||||
o Fix for using cogl_rectangle with different texture coordinates
|
||||
for multiple layers (bug #1937).
|
||||
|
||||
o Fix for using stencil and depth buffers in FBOs on Intel drivers
|
||||
in Mesa (bug #1873).
|
||||
|
||||
o Support for subtitles in ClutterMedia.
|
||||
|
||||
o ClutterGLX will now use an RGB visual by default. For
|
||||
applications (and toolkit integration libraries) that want to
|
||||
enable the ClutterStage:use-alpha property there is a new
|
||||
function: clutter_x11_set_use_argb_visual().
|
||||
|
||||
o Fix ClutterText to allow using Pango markup and attributes in
|
||||
the same actor (bug #1940).
|
||||
|
||||
Many thanks to:
|
||||
|
||||
Alejandro Piñeiro
|
||||
Damien Lespiau
|
||||
Emmanuele Bassi
|
||||
Gord Allot
|
||||
Halton Huo
|
||||
Robert Bragg
|
||||
Samuel Degrande
|
||||
|
||||
Clutter 1.1.4 (03/01/2010)
|
||||
===============================================================================
|
||||
|
||||
|
101
README
101
README
@ -1,19 +1,25 @@
|
||||
Clutter - README
|
||||
===============================================================================
|
||||
|
||||
Clutter is an open source software library for creating fast, visually
|
||||
rich and animated graphical user interfaces.
|
||||
Clutter is an open source software library for creating portable, fast,
|
||||
visually rich and animated graphical user interfaces.
|
||||
|
||||
Clutter currently requires:
|
||||
|
||||
• GLib >= 2.16.0
|
||||
• Cairo >= 1.6
|
||||
• PangoCairo >= 1.20
|
||||
• OpenGL >= 1.2, OpenGL ES 1.1 or OpenGL ES 2.0
|
||||
• OpenGL >= 1.3 or 1.2+multitexturing, OpenGL ES 1.1 or OpenGL ES 2.0
|
||||
• GLX, SDL, WGL or an EGL Implementation
|
||||
• JSON-GLib >= 0.8 (optional)
|
||||
• GDK-Pixbuf >= 2.0 (optional)
|
||||
|
||||
When running the OpenGL flavor, Clutter requires at least version 1.3
|
||||
or 1.2 with the multitexturing extension. However to build Clutter
|
||||
you will need the latest GL headers which can be obtained from:
|
||||
|
||||
http://www.khronos.org
|
||||
|
||||
If you are building the API reference you will also need:
|
||||
|
||||
• GTK-Doc >= 1.11
|
||||
@ -24,30 +30,53 @@ If you are building the Introspection data you will also need:
|
||||
|
||||
If you want built in support for profiling Clutter you will also need:
|
||||
|
||||
• UProf 0.2 available from git://git.moblin.org/uprof.git
|
||||
• UProf >= 0.2
|
||||
|
||||
The official website is:
|
||||
http://www.clutter-project.org
|
||||
UProf is available from:
|
||||
|
||||
The Clutter blog is at
|
||||
http://www.clutter-project.org/blog
|
||||
git://git.moblin.org/uprof.git
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The official Clutter website is:
|
||||
|
||||
http://www.clutter-project.org/
|
||||
|
||||
The API reference for the latest stable release and unstable developers
|
||||
snapshot are available at:
|
||||
|
||||
http://www.clutter-project.org/docs/clutter/stable/
|
||||
http://www.clutter-project.org/docs/clutter/unstable/
|
||||
|
||||
New releases of Clutter are available at:
|
||||
|
||||
http://www.clutter-project.org/sources/clutter/
|
||||
|
||||
The Clutter blog is at:
|
||||
|
||||
http://www.clutter-project.org/blog/
|
||||
|
||||
To subscribe to the Clutter mailing list, send an email to:
|
||||
|
||||
To subscribe to the Clutter mailing list, send mail to:
|
||||
clutter+subscribe@o-hand.com
|
||||
|
||||
The official mailing list archive is:
|
||||
|
||||
http://lists.o-hand.com/clutter/
|
||||
|
||||
New bug page on Bugzilla:
|
||||
|
||||
http://bugzilla.o-hand.com/enter_bug.cgi?product=Clutter
|
||||
|
||||
Clutter is licensed under the terms of the GNU Lesser General Public
|
||||
License, version 2.1 or (at your option) later.
|
||||
|
||||
INSTALLATION
|
||||
BUILDING AND INSTALLATION
|
||||
===============================================================================
|
||||
|
||||
See the INSTALL file. Info on specific Clutter options;
|
||||
See the INSTALL file.
|
||||
|
||||
Clutter has additional command line options for the configure script:
|
||||
|
||||
--enable-debug=[no/minimum/yes]
|
||||
Controls Clutter debugging level:
|
||||
@ -55,7 +84,7 @@ See the INSTALL file. Info on specific Clutter options;
|
||||
yes:
|
||||
All GLib asserts, checks and support for runtime Clutter
|
||||
debugging notes through CLUTTER_DEBUG. This is the default
|
||||
value for snapshots.
|
||||
value for developers snapshots.
|
||||
|
||||
minimum:
|
||||
Just GType cast checks and support for runtime Clutter
|
||||
@ -65,26 +94,27 @@ See the INSTALL file. Info on specific Clutter options;
|
||||
no:
|
||||
No GLib asserts or checks and no support for runtime Clutter
|
||||
debugging notes. Only use in extreme performance and/or size
|
||||
optimization cases.
|
||||
optimization cases, though it is strongly discouraged.
|
||||
|
||||
--enable-cogl-debug=[no/minimum/yes]
|
||||
Controls COGL debugging level (default=minimum):
|
||||
|
||||
yes:
|
||||
Support for COGL debugging notes through COGL_DEBUG and
|
||||
error checking for each GL primitive.
|
||||
error checking for each GL primitive. This is useful mostly
|
||||
to debug COGL itself.
|
||||
|
||||
minimum:
|
||||
Support for COGL debugging notes through COGL_DEBUG. This is
|
||||
the default for snapshots.
|
||||
the default for developers snapshots.
|
||||
|
||||
no:
|
||||
Disable support for COGL runtime debugging notes. This is
|
||||
the default for stable releases.
|
||||
|
||||
--enable-maintainer-flags=[no/yes]
|
||||
Use strict compiler flags. This defaults to 'yes' for snapshots and
|
||||
to 'no' for stable releases.
|
||||
Use strict compiler flags. This defaults to 'yes' for developers
|
||||
snapshots and to 'no' for stable releases.
|
||||
|
||||
--enable-gtk-doc
|
||||
use gtk-doc to build API documentation (default=no). Requires gtk-doc
|
||||
@ -94,6 +124,17 @@ See the INSTALL file. Info on specific Clutter options;
|
||||
Build additional documentation. Requires xsltproc for DocBook
|
||||
conversion, and optionally jw for PDF generation.
|
||||
|
||||
--enable-gcov=[no/yes]
|
||||
Build Clutter with coverage report support, provided by gcov. This
|
||||
feature only works with the GNU Compiler Suite and gcov installed.
|
||||
|
||||
--enable-profile=[no/yes]
|
||||
Build Clutter with profiling instrumentation. Requires the GNU
|
||||
C Compiler and the UProf library.
|
||||
|
||||
--enable-conform=[yes/no]
|
||||
Build the Clutter conformance test suite.
|
||||
|
||||
--with-flavour=[glx/eglx/eglnative/sdl/osx/win32/fruity]
|
||||
Select the Clutter backend: (default=glx)
|
||||
|
||||
@ -150,7 +191,7 @@ See the INSTALL file. Info on specific Clutter options;
|
||||
and if it is available, make Clutter depend on it
|
||||
|
||||
system:
|
||||
Only use the system copy of JSON-GLib
|
||||
Only use the system copy of JSON-GLib and warn if not found
|
||||
|
||||
VERSIONING
|
||||
===============================================================================
|
||||
@ -167,22 +208,23 @@ the newly added API might still change.
|
||||
|
||||
The micro version indicates the origin of the release: even micro
|
||||
numbers are only used for released archives; odd micro numbers are
|
||||
only used on the SVN repository.
|
||||
only used on the Git repository.
|
||||
|
||||
HACKING
|
||||
===============================================================================
|
||||
|
||||
If you want to hack on and improve Clutter, check the contained TODO
|
||||
file for pending tasks, the HACKING file for general implementation guidelines,
|
||||
HACKING.backends for backend-specific implementation issues. The CODING_STYLE
|
||||
file contains the rules for writing code conformant to the style guidelines
|
||||
used throughout Clutter. Remember: the coding style is mandatory; patches
|
||||
not conforming to it will be rejected.
|
||||
If you want to hack on and improve Clutter, check the contained TODO file for
|
||||
pending tasks, the HACKING file for general implementation guidelines, and the
|
||||
HACKING.backends for backend-specific implementation issues.
|
||||
|
||||
The CODING_STYLE file contains the rules for writing code conformant to the
|
||||
style guidelines used throughout Clutter. Remember: the coding style is
|
||||
mandatory; patches not conforming to it will be rejected.
|
||||
|
||||
BUGS
|
||||
===============================================================================
|
||||
|
||||
Bugs should be reported to the OpenedHand Bugzilla at:
|
||||
Bugs should be reported to the Clutter Bugzilla at:
|
||||
|
||||
http://bugzilla.o-hand.com/enter_bug.cgi?product=Clutter
|
||||
|
||||
@ -192,7 +234,7 @@ In the report you should include:
|
||||
|
||||
• what system you're running Clutter on;
|
||||
• which version of Clutter you are using;
|
||||
• which version of GLib and OpenGL you are using;
|
||||
• which version of GLib and OpenGL (or OpenGL ES) you are using;
|
||||
• which video card and which drivers you are using, including output of
|
||||
glxinfo and xdpyinfo (if applicable);
|
||||
• how to reproduce the bug.
|
||||
@ -235,7 +277,8 @@ RELEASE NOTES
|
||||
===============================================================================
|
||||
|
||||
Relevant information for developers with existing Clutter applications
|
||||
wanting to port to newer releases (See NEWS for general new feature info).
|
||||
wanting to port to newer releases (see NEWS for general information on new
|
||||
features).
|
||||
|
||||
Release Notes for Clutter 1.2
|
||||
-------------------------------------------------------------------------------
|
||||
@ -852,5 +895,3 @@ Release Notes for Clutter 0.3
|
||||
ClutterGroup::remove signals have been deprecated:
|
||||
ClutterContainer::actor-added and ClutterContainer::actor-removed should
|
||||
be used instead.
|
||||
|
||||
$LastChangedDate$
|
||||
|
@ -1,3 +1,3 @@
|
||||
SUBDIRS = autotools
|
||||
SUBDIRS = autotools mingw
|
||||
|
||||
EXTRA_DIST = gen-gcov.pl
|
||||
|
1
build/mingw/Makefile.am
Normal file
1
build/mingw/Makefile.am
Normal file
@ -0,0 +1 @@
|
||||
EXTRA_DIST = README mingw-cross-compile.sh
|
@ -20,6 +20,23 @@ DISTCLEANFILES =
|
||||
EXTRA_DIST =
|
||||
BUILT_SOURCES =
|
||||
|
||||
if WINSYS_WIN32
|
||||
|
||||
# Ideally this resources stuff would go in win32/ but libtool doesn't
|
||||
# seem to pass on the -Wl argument when linking a convenience library
|
||||
# so we need to do it here as part of linking the dll. libtool also
|
||||
# won't let you link against the .o directly because it wants you to
|
||||
# link against libtool objects for dynamic libraries.
|
||||
.rc.o :
|
||||
$(WINDRES) -I$(srcdir)/win32 $< $@
|
||||
|
||||
win32/resources.o : $(srcdir)/win32/invisible-cursor.cur
|
||||
|
||||
win32_resources = win32/resources.o
|
||||
win32_resources_ldflag = -Wl,win32/resources.o
|
||||
|
||||
endif # WINSYS_WIN32
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/clutter/cogl \
|
||||
@ -67,6 +84,7 @@ source_h = \
|
||||
$(srcdir)/clutter-color.h \
|
||||
$(srcdir)/clutter-container.h \
|
||||
$(srcdir)/clutter-deprecated.h \
|
||||
$(srcdir)/clutter-device-manager.h \
|
||||
$(srcdir)/clutter-event.h \
|
||||
$(srcdir)/clutter-feature.h \
|
||||
$(srcdir)/clutter-fixed.h \
|
||||
@ -74,6 +92,7 @@ source_h = \
|
||||
$(srcdir)/clutter-flow-layout.h \
|
||||
$(srcdir)/clutter-frame-source.h \
|
||||
$(srcdir)/clutter-group.h \
|
||||
$(srcdir)/clutter-input-device.h \
|
||||
$(srcdir)/clutter-interval.h \
|
||||
$(srcdir)/clutter-keysyms.h \
|
||||
$(srcdir)/clutter-layout-manager.h \
|
||||
@ -137,6 +156,7 @@ source_c = \
|
||||
$(srcdir)/clutter-clone.c \
|
||||
$(srcdir)/clutter-color.c \
|
||||
$(srcdir)/clutter-container.c \
|
||||
$(srcdir)/clutter-device-manager.c \
|
||||
clutter-enum-types.c \
|
||||
$(srcdir)/clutter-event.c \
|
||||
$(srcdir)/clutter-feature.c \
|
||||
@ -145,6 +165,7 @@ source_c = \
|
||||
$(srcdir)/clutter-flow-layout.c \
|
||||
$(srcdir)/clutter-frame-source.c \
|
||||
$(srcdir)/clutter-group.c \
|
||||
$(srcdir)/clutter-input-device.c \
|
||||
$(srcdir)/clutter-interval.c \
|
||||
$(srcdir)/clutter-layout-manager.c \
|
||||
$(srcdir)/clutter-layout-meta.c \
|
||||
@ -205,7 +226,8 @@ libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_DEPENDENCIES = \
|
||||
$(top_builddir)/clutter/cogl/pango/libcoglpango.la \
|
||||
$(top_builddir)/clutter/$(CLUTTER_WINSYS)/libclutter-$(CLUTTER_WINSYS).la \
|
||||
$(clutter_json_dep) \
|
||||
$(CLUTTER_WINSYS_BASE_LIB)
|
||||
$(CLUTTER_WINSYS_BASE_LIB) \
|
||||
$(win32_resources)
|
||||
|
||||
libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_SOURCES = \
|
||||
$(source_c) \
|
||||
@ -219,6 +241,7 @@ libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_LDFLAGS = \
|
||||
-export-dynamic \
|
||||
-export-symbols-regex "^(clutter|cogl|json).*" \
|
||||
-rpath $(libdir) \
|
||||
$(win32_resources_ldflag) \
|
||||
$(NULL)
|
||||
|
||||
lib_LTLIBRARIES = $(CLUTTER_WINSYS_LIB)
|
||||
|
@ -308,6 +308,7 @@ struct _ClutterActorPrivate
|
||||
guint clip_to_allocation : 1;
|
||||
guint enable_model_view_transform : 1;
|
||||
guint enable_paint_unmapped : 1;
|
||||
guint has_pointer : 1;
|
||||
|
||||
gfloat clip[4];
|
||||
|
||||
@ -429,7 +430,8 @@ enum
|
||||
|
||||
PROP_SHOW_ON_SET_PARENT,
|
||||
|
||||
PROP_TEXT_DIRECTION
|
||||
PROP_TEXT_DIRECTION,
|
||||
PROP_HAS_POINTER
|
||||
};
|
||||
|
||||
enum
|
||||
@ -2581,7 +2583,7 @@ clutter_actor_set_property (GObject *object,
|
||||
break;
|
||||
|
||||
case PROP_OPACITY:
|
||||
clutter_actor_set_opacity (actor, g_value_get_uchar (value));
|
||||
clutter_actor_set_opacity (actor, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
@ -2864,7 +2866,7 @@ clutter_actor_get_property (GObject *object,
|
||||
break;
|
||||
|
||||
case PROP_OPACITY:
|
||||
g_value_set_uchar (value, priv->opacity);
|
||||
g_value_set_uint (value, priv->opacity);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
@ -3031,6 +3033,10 @@ clutter_actor_get_property (GObject *object,
|
||||
g_value_set_enum (value, priv->text_direction);
|
||||
break;
|
||||
|
||||
case PROP_HAS_POINTER:
|
||||
g_value_set_boolean (value, priv->has_pointer);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -3462,12 +3468,12 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
||||
/**
|
||||
* ClutterActor:opacity:
|
||||
*
|
||||
* Opacity of the actor, between 0 (fully transparent) and
|
||||
* Opacity of an actor, between 0 (fully transparent) and
|
||||
* 255 (fully opaque)
|
||||
*/
|
||||
pspec = g_param_spec_uchar ("opacity",
|
||||
pspec = g_param_spec_uint ("opacity",
|
||||
"Opacity",
|
||||
"Opacity of actor",
|
||||
"Opacity of an actor",
|
||||
0, 255,
|
||||
255,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
@ -3858,6 +3864,24 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
||||
PROP_TEXT_DIRECTION,
|
||||
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:
|
||||
* @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:
|
||||
* @self: a #ClutterActor
|
||||
@ -9748,3 +9786,23 @@ clutter_actor_pop_internal (void)
|
||||
|
||||
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);
|
||||
|
||||
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
|
||||
gboolean clutter_actor_has_pointer (ClutterActor *self);
|
||||
|
||||
void clutter_actor_set_text_direction (ClutterActor *self,
|
||||
ClutterTextDirection text_dir);
|
||||
|
@ -201,8 +201,11 @@ on_actor_dispose (gpointer user_data,
|
||||
ClutterAnimation *self = user_data;
|
||||
|
||||
if (self->priv->object == actor_pointer)
|
||||
{
|
||||
CLUTTER_NOTE (ANIMATION, "Object [%p] was unref'd", actor_pointer);
|
||||
g_object_unref (self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
@ -219,6 +222,7 @@ clutter_animation_real_completed (ClutterAnimation *self)
|
||||
direction = clutter_timeline_get_direction (timeline);
|
||||
|
||||
/* explicitly set the final state of the animation */
|
||||
CLUTTER_NOTE (ANIMATION, "Set final state on object [%p]", priv->object);
|
||||
g_hash_table_iter_init (&iter, priv->properties);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
@ -245,8 +249,14 @@ clutter_animation_real_completed (ClutterAnimation *self)
|
||||
animation = g_object_get_qdata (priv->object, quark_object_animation);
|
||||
if (animation == self)
|
||||
{
|
||||
CLUTTER_NOTE (ANIMATION, "Unsetting animation for actor [%p]",
|
||||
priv->object);
|
||||
|
||||
g_object_set_qdata (priv->object, quark_object_animation, NULL);
|
||||
g_object_weak_unref (priv->object, on_actor_dispose, self);
|
||||
|
||||
CLUTTER_NOTE (ANIMATION, "Releasing the reference Animation [%p]",
|
||||
animation);
|
||||
g_object_unref (animation);
|
||||
}
|
||||
}
|
||||
@ -256,7 +266,9 @@ clutter_animation_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
|
||||
|
||||
CLUTTER_NOTE (ANIMATION, "Destroying properties hash table");
|
||||
CLUTTER_NOTE (ANIMATION,
|
||||
"Destroying properties table for Animation [%p]",
|
||||
gobject);
|
||||
g_hash_table_destroy (priv->properties);
|
||||
|
||||
G_OBJECT_CLASS (clutter_animation_parent_class)->finalize (gobject);
|
||||
@ -444,7 +456,7 @@ clutter_animation_class_init (ClutterAnimationClass *klass)
|
||||
gobject_class->finalize = clutter_animation_finalize;
|
||||
|
||||
/**
|
||||
* ClutterAnimation:objct:
|
||||
* ClutterAnimation:object:
|
||||
*
|
||||
* The #GObject to which the animation applies.
|
||||
*
|
||||
@ -629,6 +641,7 @@ clutter_animation_validate_bind (ClutterAnimation *animation,
|
||||
ClutterAnimationPrivate *priv;
|
||||
GObjectClass *klass;
|
||||
GParamSpec *pspec;
|
||||
GType pspec_type;
|
||||
|
||||
priv = animation->priv;
|
||||
|
||||
@ -667,14 +680,17 @@ clutter_animation_validate_bind (ClutterAnimation *animation,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_value_type_compatible (G_PARAM_SPEC_VALUE_TYPE (pspec), argtype))
|
||||
pspec_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
||||
|
||||
if (!g_value_type_compatible (argtype, pspec_type) ||
|
||||
!g_value_type_transformable (argtype, pspec_type))
|
||||
{
|
||||
g_warning ("Cannot bind property '%s': the interval value of "
|
||||
"type '%s' is not compatible with the property value "
|
||||
"of type '%s'",
|
||||
property_name,
|
||||
g_type_name (argtype),
|
||||
g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
||||
g_type_name (pspec_type));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -846,6 +862,7 @@ clutter_animation_update_interval (ClutterAnimation *animation,
|
||||
ClutterAnimationPrivate *priv;
|
||||
GObjectClass *klass;
|
||||
GParamSpec *pspec;
|
||||
GType pspec_type, int_type;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||
g_return_if_fail (property_name != NULL);
|
||||
@ -872,15 +889,18 @@ clutter_animation_update_interval (ClutterAnimation *animation,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_value_type_compatible (G_PARAM_SPEC_VALUE_TYPE (pspec),
|
||||
clutter_interval_get_value_type (interval)))
|
||||
pspec_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
||||
int_type = clutter_interval_get_value_type (interval);
|
||||
|
||||
if (!g_value_type_compatible (int_type, pspec_type) ||
|
||||
!g_value_type_transformable (int_type, pspec_type))
|
||||
{
|
||||
g_warning ("Cannot update property '%s': the interval value of "
|
||||
"type '%s' is not compatible with the property value "
|
||||
"of type '%s'",
|
||||
property_name,
|
||||
g_type_name (clutter_interval_get_value_type (interval)),
|
||||
g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
||||
g_type_name (int_type),
|
||||
g_type_name (pspec_type));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -906,6 +926,7 @@ clutter_animation_update (ClutterAnimation *animation,
|
||||
{
|
||||
ClutterAnimationPrivate *priv;
|
||||
ClutterInterval *interval;
|
||||
GType int_type;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
|
||||
g_return_val_if_fail (property_name != NULL, NULL);
|
||||
@ -923,14 +944,16 @@ clutter_animation_update (ClutterAnimation *animation,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_value_type_compatible (G_VALUE_TYPE (final),
|
||||
clutter_interval_get_value_type (interval)))
|
||||
int_type = clutter_interval_get_value_type (interval);
|
||||
|
||||
if (!g_value_type_compatible (G_VALUE_TYPE (final), int_type) ||
|
||||
!g_value_type_transformable (G_VALUE_TYPE (final), int_type))
|
||||
{
|
||||
g_warning ("Cannot update property '%s': the interval value of "
|
||||
"type '%s' is not compatible with the property value "
|
||||
"of type '%s'",
|
||||
property_name,
|
||||
g_type_name (clutter_interval_get_value_type (interval)),
|
||||
g_type_name (int_type),
|
||||
g_type_name (G_VALUE_TYPE (final)));
|
||||
return NULL;
|
||||
}
|
||||
@ -1221,6 +1244,8 @@ clutter_animation_set_mode (ClutterAnimation *animation,
|
||||
g_object_freeze_notify (G_OBJECT (animation));
|
||||
|
||||
alpha = clutter_animation_get_alpha_internal (animation);
|
||||
g_assert (CLUTTER_IS_ALPHA (alpha));
|
||||
|
||||
clutter_alpha_set_mode (alpha, mode);
|
||||
|
||||
g_object_notify (G_OBJECT (animation), "mode");
|
||||
@ -1274,6 +1299,8 @@ clutter_animation_set_duration (ClutterAnimation *animation,
|
||||
g_object_freeze_notify (G_OBJECT (animation));
|
||||
|
||||
timeline = clutter_animation_get_timeline_internal (animation);
|
||||
g_assert (CLUTTER_IS_TIMELINE (timeline));
|
||||
|
||||
clutter_timeline_set_duration (timeline, msecs);
|
||||
clutter_timeline_rewind (timeline);
|
||||
|
||||
@ -1634,11 +1661,23 @@ clutter_animation_setup_property (ClutterAnimation *animation,
|
||||
*/
|
||||
if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (&real_value)))
|
||||
{
|
||||
if (!g_value_type_compatible (G_VALUE_TYPE (value),
|
||||
G_VALUE_TYPE (&real_value)) &&
|
||||
!g_value_type_compatible (G_VALUE_TYPE (&real_value),
|
||||
G_VALUE_TYPE (value)))
|
||||
/* are these two types compatible (can be directly copied)? */
|
||||
if (g_value_type_compatible (G_VALUE_TYPE (value),
|
||||
G_VALUE_TYPE (&real_value)))
|
||||
{
|
||||
g_value_copy (value, &real_value);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* are these two type transformable? */
|
||||
if (g_value_type_transformable (G_VALUE_TYPE (value),
|
||||
G_VALUE_TYPE (&real_value)))
|
||||
{
|
||||
if (g_value_transform (value, &real_value))
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* if not compatible and not transformable then we can't do much */
|
||||
g_warning ("%s: Unable to convert from %s to %s for "
|
||||
"the property '%s' of object %s",
|
||||
G_STRLOC,
|
||||
@ -1649,20 +1688,10 @@ clutter_animation_setup_property (ClutterAnimation *animation,
|
||||
g_value_unset (&real_value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_value_transform (value, &real_value))
|
||||
{
|
||||
g_warning ("%s: Unable to transform from %s to %s",
|
||||
G_STRLOC,
|
||||
g_type_name (G_VALUE_TYPE (value)),
|
||||
g_type_name (G_VALUE_TYPE (&real_value)));
|
||||
g_value_unset (&real_value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
g_value_copy (value, &real_value);
|
||||
|
||||
done:
|
||||
/* create an interval and bind it to the property, in case
|
||||
* it's not a fixed property, otherwise just set it
|
||||
*/
|
||||
|
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-input-device.h>
|
||||
#include <clutter/clutter-types.h>
|
||||
|
||||
#define CLUTTER_TYPE_EVENT (clutter_event_get_type ())
|
||||
@ -201,37 +202,6 @@ typedef struct _ClutterScrollEvent ClutterScrollEvent;
|
||||
typedef struct _ClutterStageStateEvent ClutterStageStateEvent;
|
||||
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:
|
||||
* @type: event type
|
||||
@ -509,9 +479,6 @@ guint32 clutter_keysym_to_unicode (guint k
|
||||
guint32 clutter_get_current_event_time (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
|
||||
|
||||
#endif /* __CLUTTER_EVENT_H__ */
|
||||
|
@ -25,9 +25,16 @@
|
||||
|
||||
/**
|
||||
* SECTION:clutter-feature
|
||||
* @short_description: Query GL features at runtime
|
||||
* @short_description: Run-time detection of Clutter features
|
||||
*
|
||||
* Functions to query available GL features ay runtime
|
||||
* Parts of Clutter depend on the underlying platform, including the
|
||||
* capabilities of the backend used and the OpenGL features exposed through the
|
||||
* Clutter and COGL API.
|
||||
*
|
||||
* It is possible to ask whether Clutter has support for specific features at
|
||||
* run-time.
|
||||
*
|
||||
* See also cogl_get_features() and #CoglFeatureFlags
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -25,14 +25,6 @@
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:clutter-main
|
||||
* @short_description: Various 'global' clutter functions.
|
||||
*
|
||||
* Functions to retrieve various global Clutter resources and other utility
|
||||
* functions for mainloops, events and threads
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_FEATURE_H__
|
||||
#define __CLUTTER_FEATURE_H__
|
||||
|
||||
|
@ -39,7 +39,8 @@ struct _ClutterFrameSource
|
||||
ClutterTimeoutInterval timeout;
|
||||
};
|
||||
|
||||
static gboolean clutter_frame_source_prepare (GSource *source, gint *timeout);
|
||||
static gboolean clutter_frame_source_prepare (GSource *source,
|
||||
gint *timeout);
|
||||
static gboolean clutter_frame_source_check (GSource *source);
|
||||
static gboolean clutter_frame_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
@ -56,7 +57,7 @@ static GSourceFuncs clutter_frame_source_funcs =
|
||||
/**
|
||||
* clutter_frame_source_add_full:
|
||||
* @priority: the priority of the frame source. Typically this will be in the
|
||||
* range between #G_PRIORITY_DEFAULT and #G_PRIORITY_HIGH.
|
||||
* range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH.
|
||||
* @fps: the number of times per second to call the function
|
||||
* @func: function to call
|
||||
* @data: data to pass to the function
|
||||
@ -131,7 +132,8 @@ clutter_frame_source_add (guint fps,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_frame_source_prepare (GSource *source, gint *delay)
|
||||
clutter_frame_source_prepare (GSource *source,
|
||||
gint *delay)
|
||||
{
|
||||
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
|
||||
GTimeVal current_time;
|
||||
|
@ -277,10 +277,12 @@ clutter_group_real_foreach (ClutterContainer *container,
|
||||
{
|
||||
ClutterGroup *group = CLUTTER_GROUP (container);
|
||||
ClutterGroupPrivate *priv = group->priv;
|
||||
GList *l;
|
||||
|
||||
for (l = priv->children; l; l = l->next)
|
||||
(* callback) (CLUTTER_ACTOR (l->data), user_data);
|
||||
/* Using g_list_foreach instead of iterating the list manually
|
||||
because it has better protection against the current node being
|
||||
removed. This will happen for example if someone calls
|
||||
clutter_container_foreach(container, clutter_actor_destroy) */
|
||||
g_list_foreach (priv->children, (GFunc) callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
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,68 +2045,92 @@ event_click_count_generate (ClutterEvent *event)
|
||||
static guint32 previous_time = 0;
|
||||
static gint previous_button_number = -1;
|
||||
|
||||
ClutterInputDevice *device = NULL;
|
||||
ClutterBackend *backend;
|
||||
guint double_click_time;
|
||||
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_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;
|
||||
previous_x = event->button.device->previous_x;
|
||||
previous_y = event->button.device->previous_y;
|
||||
previous_time = event->button.device->previous_time;
|
||||
previous_button_number = event->button.device->previous_button_number;
|
||||
click_count = device->click_count;
|
||||
previous_x = device->previous_x;
|
||||
previous_y = device->previous_y;
|
||||
previous_time = device->previous_time;
|
||||
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_SCROLL:
|
||||
/* check if we are in time and within distance to increment an
|
||||
* 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.y - previous_y) <= double_click_distance)
|
||||
&& event->button.button == previous_button_number)
|
||||
(ABS (event->button.y - previous_y) <= double_click_distance))
|
||||
{
|
||||
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*/
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* store time and position for this click for comparison with
|
||||
* next event
|
||||
*/
|
||||
previous_time = event->button.time;
|
||||
previous_x = event->button.x;
|
||||
previous_y = event->button.y;
|
||||
previous_time = event->button.time;
|
||||
|
||||
/* fallthrough */
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
event->button.click_count = click_count;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert (NULL);
|
||||
}
|
||||
|
||||
if (event->button.device != NULL)
|
||||
if (event->type == CLUTTER_BUTTON_PRESS && device != NULL)
|
||||
{
|
||||
event->button.device->click_count = click_count;
|
||||
event->button.device->previous_x = previous_x;
|
||||
event->button.device->previous_y = previous_y;
|
||||
event->button.device->previous_time = previous_time;
|
||||
event->button.device->previous_button_number = previous_button_number;
|
||||
}
|
||||
}
|
||||
CLUTTER_NOTE (EVENT, "Storing click count: %d (device:%d, time:%u)",
|
||||
click_count,
|
||||
clutter_input_device_get_device_id (device),
|
||||
previous_time);
|
||||
|
||||
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
|
||||
emit_event (ClutterEvent *event,
|
||||
@ -2118,7 +2142,7 @@ emit_event (ClutterEvent *event,
|
||||
ClutterActor *actor;
|
||||
gint i = 0;
|
||||
|
||||
if (!event->any.source)
|
||||
if (event->any.source == NULL)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "No source set, discarding event");
|
||||
return;
|
||||
@ -2182,136 +2206,38 @@ static inline void
|
||||
emit_pointer_event (ClutterEvent *event,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
/* Using the global variable directly, since it has to be initialized
|
||||
* at this point
|
||||
*/
|
||||
ClutterMainContext *context = ClutterCntx;
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
|
||||
if (G_UNLIKELY (context->pointer_grab_actor != NULL &&
|
||||
device == NULL))
|
||||
if (context->pointer_grab_actor == 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 */
|
||||
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
|
||||
}
|
||||
else if (G_UNLIKELY (device != NULL &&
|
||||
device->pointer_grab_actor != NULL))
|
||||
else if (device != NULL && device->pointer_grab_actor != NULL)
|
||||
{
|
||||
/* per device grab */
|
||||
clutter_actor_event (device->pointer_grab_actor, event, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no grab, time to capture and bubble */
|
||||
emit_event (event, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emit_keyboard_event (ClutterEvent *event)
|
||||
{
|
||||
ClutterMainContext *context = ClutterCntx;
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
|
||||
if (G_UNLIKELY (context->keyboard_grab_actor != NULL))
|
||||
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
||||
else
|
||||
if (context->keyboard_grab_actor == NULL)
|
||||
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
|
||||
dev->motion_last_actor = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2345,6 +2271,8 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
{
|
||||
ClutterInputDevice *device = NULL;
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_NOTHING:
|
||||
@ -2352,23 +2280,8 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
|
||||
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:
|
||||
emit_pointer_event (event, event->crossing.device);
|
||||
emit_pointer_event (event, device);
|
||||
break;
|
||||
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
@ -2400,8 +2313,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
device = event->motion.device;
|
||||
|
||||
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
||||
* and the event is not a synthetic event with source set.
|
||||
*/
|
||||
@ -2434,8 +2345,7 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
}
|
||||
|
||||
/* fallthrough */
|
||||
|
||||
/* fallthrough from motion */
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_SCROLL:
|
||||
@ -2462,18 +2372,29 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
x, y);
|
||||
|
||||
event->button.source = stage;
|
||||
emit_pointer_event (event, event->button.device);
|
||||
event->button.click_count = 1;
|
||||
emit_pointer_event (event, device);
|
||||
}
|
||||
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),
|
||||
x, y,
|
||||
CLUTTER_PICK_REACTIVE);
|
||||
}
|
||||
|
||||
event->any.source = actor;
|
||||
if (!actor)
|
||||
if (event->any.source == NULL)
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -2482,7 +2403,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
actor = event->any.source;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: for an optimisation should check if there are
|
||||
* actually any reactive actors and avoid the pick all together
|
||||
* (signalling just the stage). Should be big help for gles.
|
||||
@ -2493,33 +2413,12 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
x, y,
|
||||
actor);
|
||||
|
||||
/* Create, enter/leave events if needed */
|
||||
generate_enter_leave_events (event);
|
||||
|
||||
if (event->type != CLUTTER_MOTION)
|
||||
{
|
||||
/* Generate click count */
|
||||
event_click_count_generate (event);
|
||||
}
|
||||
|
||||
if (device == NULL)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
device = event->button.device;
|
||||
break;
|
||||
case CLUTTER_SCROLL:
|
||||
device = event->scroll.device;
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
/* already handled in the MOTION case of the switch */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emit_pointer_event (event, device);
|
||||
break;
|
||||
}
|
||||
@ -3023,9 +2922,19 @@ clutter_get_font_flags (void)
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@ -3034,23 +2943,11 @@ clutter_get_font_flags (void)
|
||||
ClutterInputDevice *
|
||||
clutter_get_input_device_for_id (gint id)
|
||||
{
|
||||
GSList *item;
|
||||
ClutterInputDevice *device = NULL;
|
||||
ClutterMainContext *context;
|
||||
ClutterDeviceManager *manager;
|
||||
|
||||
context = _clutter_context_get_default ();
|
||||
manager = clutter_device_manager_get_default ();
|
||||
|
||||
for (item = context->input_devices;
|
||||
item != NULL;
|
||||
item = item->next)
|
||||
{
|
||||
device = item->data;
|
||||
|
||||
if (device->id == id)
|
||||
return device;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return clutter_device_manager_get_device (manager, id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@ VOID:INT,INT,INT,INT
|
||||
VOID:OBJECT
|
||||
VOID:OBJECT,OBJECT,PARAM
|
||||
VOID:OBJECT,POINTER
|
||||
VOID:POINTER
|
||||
VOID:STRING,BOOLEAN,BOOLEAN
|
||||
VOID:STRING,INT
|
||||
VOID:UINT
|
||||
|
@ -294,8 +294,7 @@ clutter_clock_dispatch (GSource *source,
|
||||
|
||||
master_clock->updated_stages = FALSE;
|
||||
|
||||
/* Process queued events
|
||||
*/
|
||||
/* Process queued events */
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
_clutter_stage_process_queued_events (l->data);
|
||||
|
||||
@ -446,7 +445,7 @@ _clutter_master_clock_start_running (ClutterMasterClock *master_clock)
|
||||
void
|
||||
_clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
||||
{
|
||||
GSList *l, *next;
|
||||
GSList *timelines, *l;
|
||||
|
||||
CLUTTER_STATIC_TIMER (master_timeline_advance,
|
||||
"Master Clock",
|
||||
@ -456,23 +455,38 @@ _clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
|
||||
|
||||
/* we protect ourselves from timelines being removed during
|
||||
* the advancement by other timelines
|
||||
*/
|
||||
g_slist_foreach (master_clock->timelines, (GFunc) g_object_ref, NULL);
|
||||
|
||||
CLUTTER_TIMER_START (_clutter_uprof_context, master_timeline_advance);
|
||||
|
||||
for (l = master_clock->timelines; l != NULL; l = next)
|
||||
{
|
||||
next = l->next;
|
||||
/* we protect ourselves from timelines being removed during
|
||||
* the advancement by other timelines by copying the list of
|
||||
* timelines, taking a reference on them, iterating over the
|
||||
* copied list and then releasing the reference.
|
||||
*
|
||||
* we cannot simply take a reference on the timelines and still
|
||||
* use the list held by the master clock because the do_tick()
|
||||
* might result in the creation of a new timeline, which gets
|
||||
* added at the end of the list with no reference increase and
|
||||
* thus gets disposed at the end of the iteration.
|
||||
*
|
||||
* this implies that a newly added timeline will not be advanced
|
||||
* by this clock iteration, which is perfectly fine since we're
|
||||
* in its first cycle.
|
||||
*
|
||||
* we also cannot steal the master clock timelines list because
|
||||
* a timeline might be removed as the direct result of do_tick()
|
||||
* and remove_timeline() would not find the timeline, failing
|
||||
* and leaving a dangling pointer behind.
|
||||
*/
|
||||
timelines = g_slist_copy (master_clock->timelines);
|
||||
g_slist_foreach (timelines, (GFunc) g_object_ref, NULL);
|
||||
|
||||
for (l = timelines; l != NULL; l = l->next)
|
||||
clutter_timeline_do_tick (l->data, &master_clock->cur_tick);
|
||||
}
|
||||
|
||||
g_slist_foreach (timelines, (GFunc) g_object_unref, NULL);
|
||||
g_slist_free (timelines);
|
||||
|
||||
CLUTTER_TIMER_STOP (_clutter_uprof_context, master_timeline_advance);
|
||||
|
||||
g_slist_foreach (master_clock->timelines, (GFunc) g_object_unref, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "pango/cogl-pango.h"
|
||||
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-device-manager.h"
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-id-pool.h"
|
||||
@ -52,6 +53,8 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ClutterMainContext ClutterMainContext;
|
||||
|
||||
typedef enum {
|
||||
CLUTTER_ACTOR_UNUSED_FLAG = 0,
|
||||
|
||||
@ -82,21 +85,54 @@ typedef enum {
|
||||
|
||||
struct _ClutterInputDevice
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gint id;
|
||||
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
ClutterActor *pointer_grab_actor;
|
||||
ClutterActor *motion_last_actor;
|
||||
gchar *device_name;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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_y;
|
||||
guint32 previous_time;
|
||||
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
|
||||
{
|
||||
@ -138,9 +174,6 @@ struct _ClutterMainContext
|
||||
PangoContext *pango_context; /* Global Pango context */
|
||||
CoglPangoFontMap *font_map; /* Global font map */
|
||||
|
||||
GSList *input_devices; /* For extra input devices, i.e
|
||||
MultiTouch */
|
||||
|
||||
ClutterEvent *current_event;
|
||||
guint32 last_event_time;
|
||||
|
||||
@ -170,21 +203,34 @@ PangoContext *_clutter_context_get_pango_context (ClutterMainContext *self);
|
||||
|
||||
#define I_(str) (g_intern_static_string ((str)))
|
||||
|
||||
/* device manager */
|
||||
void _clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device);
|
||||
void _clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device);
|
||||
void _clutter_device_manager_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 */
|
||||
struct _ClutterStageManager
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GSList *stages;
|
||||
};
|
||||
|
||||
void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage);
|
||||
void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage);
|
||||
|
||||
/* stage */
|
||||
|
||||
void _clutter_stage_set_window (ClutterStage *stage,
|
||||
ClutterStageWindow *stage_window);
|
||||
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
||||
@ -198,6 +244,7 @@ void _clutter_stage_queue_event (ClutterStage *stage,
|
||||
ClutterEvent *event);
|
||||
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
|
||||
void _clutter_stage_process_queued_events (ClutterStage *stage);
|
||||
void _clutter_stage_update_input_devices (ClutterStage *stage);
|
||||
|
||||
/* vfuncs implemented by backend */
|
||||
GType _clutter_backend_impl_get_type (void);
|
||||
@ -271,6 +318,9 @@ void _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
|
||||
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
||||
gboolean enable);
|
||||
|
||||
void _clutter_actor_set_has_pointer (ClutterActor *self,
|
||||
gboolean has_pointer);
|
||||
|
||||
void _clutter_run_repaint_functions (void);
|
||||
|
||||
gint32 _clutter_backend_get_units_serial (ClutterBackend *backend);
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "clutter-id-pool.h"
|
||||
#include "clutter-container.h"
|
||||
#include "clutter-profile.h"
|
||||
#include "clutter-input-device.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
@ -113,7 +114,8 @@ enum
|
||||
PROP_USER_RESIZE,
|
||||
PROP_USE_FOG,
|
||||
PROP_FOG,
|
||||
PROP_USE_ALPHA
|
||||
PROP_USE_ALPHA,
|
||||
PROP_KEY_FOCUS
|
||||
};
|
||||
|
||||
enum
|
||||
@ -454,6 +456,7 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
gboolean first_event;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
@ -461,14 +464,31 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
||||
|
||||
first_event = priv->event_queue->length == 0;
|
||||
|
||||
g_queue_push_tail (priv->event_queue,
|
||||
clutter_event_copy (event));
|
||||
g_queue_push_tail (priv->event_queue, clutter_event_copy (event));
|
||||
|
||||
if (first_event)
|
||||
{
|
||||
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
|
||||
_clutter_master_clock_start_running (master_clock);
|
||||
}
|
||||
|
||||
/* if needed, update the state of the input device of the event.
|
||||
* we do it here to avoid calling the same code from every backend
|
||||
* event processing function
|
||||
*/
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
{
|
||||
ClutterModifierType event_state = clutter_event_get_state (event);
|
||||
guint32 event_time = clutter_event_get_time (event);
|
||||
gfloat event_x, event_y;
|
||||
|
||||
clutter_event_get_coords (event, &event_x, &event_y);
|
||||
|
||||
_clutter_input_device_set_coords (device, event_x, event_y);
|
||||
_clutter_input_device_set_state (device, event_state);
|
||||
_clutter_input_device_set_time (device, event_time);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -487,7 +507,7 @@ void
|
||||
_clutter_stage_process_queued_events (ClutterStage *stage)
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
GList *events, *l;;
|
||||
GList *events, *l;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
@ -506,7 +526,7 @@ _clutter_stage_process_queued_events (ClutterStage *stage)
|
||||
priv->event_queue->tail = NULL;
|
||||
priv->event_queue->length = 0;
|
||||
|
||||
for (l = events; l; l = l->next)
|
||||
for (l = events; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterEvent *event;
|
||||
ClutterEvent *next_event;
|
||||
@ -694,6 +714,10 @@ clutter_stage_set_property (GObject *object,
|
||||
clutter_stage_set_use_alpha (stage, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_KEY_FOCUS:
|
||||
clutter_stage_set_key_focus (stage, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -750,6 +774,10 @@ clutter_stage_get_property (GObject *gobject,
|
||||
g_value_set_boolean (value, priv->use_alpha);
|
||||
break;
|
||||
|
||||
case PROP_KEY_FOCUS:
|
||||
g_value_set_object (value, priv->key_focused_actor);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@ -994,6 +1022,23 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_USE_ALPHA, pspec);
|
||||
|
||||
/**
|
||||
* ClutterStage:key-focus:
|
||||
*
|
||||
* The #ClutterActor that will receive key events from the underlying
|
||||
* windowing system.
|
||||
*
|
||||
* If %NULL, the #ClutterStage will receive the events.
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
pspec = g_param_spec_object ("key-focus",
|
||||
"Key Focus",
|
||||
"The currently key focused actor",
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_KEY_FOCUS, pspec);
|
||||
|
||||
/**
|
||||
* ClutterStage::fullscreen
|
||||
* @stage: the stage which was fullscreened
|
||||
@ -1749,6 +1794,8 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
||||
}
|
||||
else
|
||||
g_signal_emit_by_name (stage, "key-focus-in");
|
||||
|
||||
g_object_notify (G_OBJECT (stage), "key-focus");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,6 +260,7 @@ clutter_text_clear_selection (ClutterText *self)
|
||||
if (priv->selection_bound != priv->position)
|
||||
{
|
||||
priv->selection_bound = priv->position;
|
||||
g_object_notify (G_OBJECT (self), "selection-bound");
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
}
|
||||
@ -803,6 +804,7 @@ clutter_text_delete_selection (ClutterText *self)
|
||||
priv->position = start_index;
|
||||
priv->selection_bound = start_index;
|
||||
|
||||
/* Not required to be guarded by g_object_freeze/thaw_notify */
|
||||
if (priv->position != old_position)
|
||||
g_object_notify (G_OBJECT (self), "position");
|
||||
|
||||
@ -812,6 +814,21 @@ clutter_text_delete_selection (ClutterText *self)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to update both cursor position and selection bound
|
||||
* at once
|
||||
*/
|
||||
static inline void
|
||||
clutter_text_set_positions (ClutterText *self,
|
||||
gint new_pos,
|
||||
gint new_bound)
|
||||
{
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
clutter_text_set_cursor_position (self, new_pos);
|
||||
clutter_text_set_selection_bound (self, new_bound);
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_text_set_text_internal (ClutterText *self,
|
||||
const gchar *text)
|
||||
@ -857,8 +874,7 @@ clutter_text_set_text_internal (ClutterText *self,
|
||||
|
||||
if (priv->n_bytes == 0)
|
||||
{
|
||||
clutter_text_set_cursor_position (self, -1);
|
||||
clutter_text_set_selection_bound (self, -1);
|
||||
clutter_text_set_positions (self, -1, -1);
|
||||
}
|
||||
|
||||
clutter_text_dirty_cache (self);
|
||||
@ -1493,8 +1509,7 @@ clutter_text_button_press (ClutterActor *actor,
|
||||
*/
|
||||
if (priv->text == NULL || priv->text[0] == '\0')
|
||||
{
|
||||
clutter_text_set_cursor_position (self, -1);
|
||||
clutter_text_set_selection_bound (self, -1);
|
||||
clutter_text_set_positions (self, -1, -1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1519,8 +1534,7 @@ clutter_text_button_press (ClutterActor *actor,
|
||||
*/
|
||||
if (event->click_count == 1)
|
||||
{
|
||||
clutter_text_set_cursor_position (self, offset);
|
||||
clutter_text_set_selection_bound (self, offset);
|
||||
clutter_text_set_positions (self, offset, offset);
|
||||
}
|
||||
else if (event->click_count == 2)
|
||||
{
|
||||
@ -1565,8 +1579,7 @@ clutter_text_motion (ClutterActor *actor,
|
||||
clutter_text_set_cursor_position (self, offset);
|
||||
else
|
||||
{
|
||||
clutter_text_set_cursor_position (self, offset);
|
||||
clutter_text_set_selection_bound (self, offset);
|
||||
clutter_text_set_positions (self, offset, offset);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -1896,6 +1909,8 @@ clutter_text_real_move_left (ClutterText *self,
|
||||
|
||||
len = priv->n_chars;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
if (pos != 0 && len != 0)
|
||||
{
|
||||
if (modifiers & CLUTTER_CONTROL_MASK)
|
||||
@ -1919,6 +1934,8 @@ clutter_text_real_move_left (ClutterText *self,
|
||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||
clutter_text_clear_selection (self);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1935,6 +1952,8 @@ clutter_text_real_move_right (ClutterText *self,
|
||||
|
||||
len = priv->n_chars;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
if (pos != -1 && len !=0)
|
||||
{
|
||||
if (modifiers & CLUTTER_CONTROL_MASK)
|
||||
@ -1954,6 +1973,8 @@ clutter_text_real_move_right (ClutterText *self,
|
||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||
clutter_text_clear_selection (self);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1970,6 +1991,8 @@ clutter_text_real_move_up (ClutterText *self,
|
||||
gint index_, trailing;
|
||||
gint x;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
layout = clutter_text_get_layout (self);
|
||||
|
||||
if (priv->position == 0)
|
||||
@ -2007,6 +2030,8 @@ clutter_text_real_move_up (ClutterText *self,
|
||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||
clutter_text_clear_selection (self);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2023,6 +2048,8 @@ clutter_text_real_move_down (ClutterText *self,
|
||||
gint index_, trailing;
|
||||
gint x;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
layout = clutter_text_get_layout (self);
|
||||
|
||||
if (priv->position == 0)
|
||||
@ -2056,6 +2083,8 @@ clutter_text_real_move_down (ClutterText *self,
|
||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||
clutter_text_clear_selection (self);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2068,12 +2097,16 @@ clutter_text_real_line_start (ClutterText *self,
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
gint position;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
position = clutter_text_move_line_start (self, priv->position);
|
||||
clutter_text_set_cursor_position (self, position);
|
||||
|
||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||
clutter_text_clear_selection (self);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2086,12 +2119,16 @@ clutter_text_real_line_end (ClutterText *self,
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
gint position;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
position = clutter_text_move_line_end (self, priv->position);
|
||||
clutter_text_set_cursor_position (self, position);
|
||||
|
||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||
clutter_text_clear_selection (self);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2101,8 +2138,7 @@ clutter_text_real_select_all (ClutterText *self,
|
||||
guint keyval,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
clutter_text_set_cursor_position (self, 0);
|
||||
clutter_text_set_selection_bound (self, self->priv->n_chars);
|
||||
clutter_text_set_positions (self, 0, self->priv->n_chars);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -2151,15 +2187,13 @@ clutter_text_real_del_prev (ClutterText *self,
|
||||
{
|
||||
clutter_text_delete_text (self, len - 1, len);
|
||||
|
||||
clutter_text_set_cursor_position (self, -1);
|
||||
clutter_text_set_selection_bound (self, -1);
|
||||
clutter_text_set_positions (self, -1, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_text_delete_text (self, pos - 1, pos);
|
||||
|
||||
clutter_text_set_cursor_position (self, pos - 1);
|
||||
clutter_text_set_selection_bound (self, pos - 1);
|
||||
clutter_text_set_positions (self, pos - 1, pos - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3260,12 +3294,7 @@ clutter_text_set_selection (ClutterText *self,
|
||||
start_pos = MIN (priv->n_chars, start_pos);
|
||||
end_pos = MIN (priv->n_chars, end_pos);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
clutter_text_set_cursor_position (self, start_pos);
|
||||
clutter_text_set_selection_bound (self, end_pos);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
clutter_text_set_positions (self, start_pos, end_pos);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4349,8 +4378,7 @@ clutter_text_insert_unichar (ClutterText *self,
|
||||
|
||||
if (priv->position >= 0)
|
||||
{
|
||||
clutter_text_set_cursor_position (self, priv->position + 1);
|
||||
clutter_text_set_selection_bound (self, priv->position);
|
||||
clutter_text_set_positions (self, priv->position + 1, priv->position);
|
||||
}
|
||||
|
||||
g_string_free (new, TRUE);
|
||||
@ -4397,8 +4425,9 @@ clutter_text_insert_text (ClutterText *self,
|
||||
|
||||
if (position >= 0 && priv->position >= position)
|
||||
{
|
||||
clutter_text_set_cursor_position (self, priv->position + g_utf8_strlen (text, -1));
|
||||
clutter_text_set_selection_bound (self, priv->position);
|
||||
clutter_text_set_positions (self,
|
||||
priv->position + g_utf8_strlen (text, -1),
|
||||
priv->position);
|
||||
}
|
||||
|
||||
g_string_free (new, TRUE);
|
||||
|
@ -52,9 +52,12 @@ _clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
||||
ClutterTimeoutInterval *interval,
|
||||
gint *delay)
|
||||
{
|
||||
guint elapsed_time
|
||||
= _clutter_timeout_interval_get_ticks (current_time, interval);
|
||||
guint new_frame_num = elapsed_time * interval->fps / 1000;
|
||||
guint elapsed_time, new_frame_num;
|
||||
|
||||
elapsed_time = _clutter_timeout_interval_get_ticks (current_time,
|
||||
interval);
|
||||
new_frame_num = elapsed_time * interval->fps
|
||||
/ 1000;
|
||||
|
||||
/* If time has gone backwards or the time since the last frame is
|
||||
greater than the two frames worth then reset the time and do a
|
||||
@ -67,6 +70,7 @@ _clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
||||
|
||||
/* Reset the start time */
|
||||
interval->start_time = *current_time;
|
||||
|
||||
/* Move the start time as if one whole frame has elapsed */
|
||||
g_time_val_add (&interval->start_time, -(gint) frame_time * 1000);
|
||||
|
||||
@ -74,12 +78,14 @@ _clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
||||
|
||||
if (delay)
|
||||
*delay = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (new_frame_num > interval->frame_count)
|
||||
{
|
||||
if (delay)
|
||||
*delay = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
@ -87,6 +93,7 @@ _clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
||||
if (delay)
|
||||
*delay = ((interval->frame_count + 1) * 1000 / interval->fps
|
||||
- elapsed_time);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -99,9 +106,10 @@ _clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
|
||||
if ((* callback) (user_data))
|
||||
{
|
||||
interval->frame_count++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -359,12 +359,6 @@ clutter_timeout_pool_finalize (GSource *source)
|
||||
* always sorted, so that the extraction of the next timeout function is
|
||||
* a constant time operation.
|
||||
*
|
||||
* Inside Clutter, every #ClutterTimeline share the same timeout pool, unless
|
||||
* the CLUTTER_TIMELINE=no-pool environment variable is set.
|
||||
*
|
||||
* #ClutterTimeoutPool is part of the #ClutterTimeline implementation
|
||||
* and should not be used by application developers.
|
||||
*
|
||||
* Return value: the newly created #ClutterTimeoutPool. The created pool
|
||||
* is owned by the GLib default context and will be automatically
|
||||
* destroyed when the context is destroyed. It is possible to force
|
||||
@ -412,7 +406,7 @@ clutter_timeout_pool_new (gint priority)
|
||||
* won't be called again. If @notify is not %NULL, the @notify function
|
||||
* will be called. The first call to @func will be at the end of @interval.
|
||||
*
|
||||
* Since version 0.8 this will try to compensate for delays. For
|
||||
* Since Clutter 0.8 this will try to compensate for delays. For
|
||||
* example, if @func takes half the interval time to execute then the
|
||||
* function will be called again half the interval time after it
|
||||
* finished. Before version 0.8 it would not fire until a full
|
||||
@ -478,7 +472,8 @@ clutter_timeout_pool_remove (ClutterTimeoutPool *pool,
|
||||
clutter_timeout_find_by_id)))
|
||||
{
|
||||
clutter_timeout_unref (l->data);
|
||||
pool->dispatched_timeouts
|
||||
= g_list_delete_link (pool->dispatched_timeouts, l);
|
||||
|
||||
pool->dispatched_timeouts =
|
||||
g_list_delete_link (pool->dispatched_timeouts, l);
|
||||
}
|
||||
}
|
||||
|
@ -51,12 +51,14 @@
|
||||
#include "clutter-clone.h"
|
||||
#include "clutter-color.h"
|
||||
#include "clutter-container.h"
|
||||
#include "clutter-device-manager.h"
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-fixed-layout.h"
|
||||
#include "clutter-flow-layout.h"
|
||||
#include "clutter-frame-source.h"
|
||||
#include "clutter-group.h"
|
||||
#include "clutter-input-device.h"
|
||||
#include "clutter-interval.h"
|
||||
#include "clutter-keysyms.h"
|
||||
#include "clutter-layout-manager.h"
|
||||
|
@ -115,6 +115,12 @@ typedef struct
|
||||
CoglAtlas *atlas;
|
||||
CoglHandle atlas_texture;
|
||||
|
||||
/* This debugging variable is used to pick a colour for visually
|
||||
displaying the quad batches. It needs to be global so that it can
|
||||
be reset by cogl_clear. It needs to be reset to increase the
|
||||
chances of getting the same colour during an animation */
|
||||
guint8 journal_rectangles_color;
|
||||
|
||||
CoglContextDriver drv;
|
||||
} CoglContext;
|
||||
|
||||
|
@ -101,6 +101,8 @@ CoglTextureUnit *
|
||||
_cogl_get_texture_unit (int index_);
|
||||
void
|
||||
_cogl_destroy_texture_units (void);
|
||||
guint
|
||||
_cogl_get_max_texture_image_units (void);
|
||||
|
||||
void
|
||||
_cogl_flush_face_winding (void);
|
||||
|
@ -225,30 +225,51 @@ _cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* DEBUGGING CODE XXX:
|
||||
* This path will cause all rectangles to be drawn with a red, green
|
||||
* or blue outline with no blending. This may e.g. help with debugging
|
||||
* texture slicing issues or blending issues, plus it looks quite cool.
|
||||
/* DEBUGGING CODE XXX: This path will cause all rectangles to be
|
||||
* drawn with a coloured outline. Each batch will be rendered with
|
||||
* the same color. This may e.g. help with debugging texture slicing
|
||||
* issues, visually seeing what is batched and debugging blending
|
||||
* issues, plus it looks quite cool.
|
||||
*/
|
||||
if (cogl_debug_flags & COGL_DEBUG_RECTANGLES)
|
||||
{
|
||||
static CoglHandle outline = COGL_INVALID_HANDLE;
|
||||
static int color = 0;
|
||||
guint8 color_intensity;
|
||||
int i;
|
||||
|
||||
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
|
||||
|
||||
if (outline == COGL_INVALID_HANDLE)
|
||||
outline = cogl_material_new ();
|
||||
|
||||
cogl_enable (COGL_ENABLE_VERTEX_ARRAY);
|
||||
for (i = 0; i < batch_len; i++, color = (color + 1) % 3)
|
||||
{
|
||||
/* The least significant three bits represent the three
|
||||
components so that the order of colours goes red, green,
|
||||
yellow, blue, magenta, cyan. Black and white are skipped. The
|
||||
next two bits give four scales of intensity for those colours
|
||||
in the order 0xff, 0xcc, 0x99, and 0x66. This gives a total
|
||||
of 24 colours. If there are more than 24 batches on the stage
|
||||
then it will wrap around */
|
||||
color_intensity = 0xff - 0x33 * (ctxt->journal_rectangles_color >> 3);
|
||||
cogl_material_set_color4ub (outline,
|
||||
color == 0 ? 0xff : 0x00,
|
||||
color == 1 ? 0xff : 0x00,
|
||||
color == 2 ? 0xff : 0x00,
|
||||
(ctxt->journal_rectangles_color & 1) ?
|
||||
color_intensity : 0,
|
||||
(ctxt->journal_rectangles_color & 2) ?
|
||||
color_intensity : 0,
|
||||
(ctxt->journal_rectangles_color & 4) ?
|
||||
color_intensity : 0,
|
||||
0xff);
|
||||
_cogl_material_flush_gl_state (outline, NULL);
|
||||
GE( glDrawArrays (GL_LINE_LOOP, 4 * i, 4) );
|
||||
}
|
||||
cogl_enable (COGL_ENABLE_VERTEX_ARRAY);
|
||||
for (i = 0; i < batch_len; i++)
|
||||
GE( glDrawArrays (GL_LINE_LOOP, 4 * i + state->vertex_offset, 4) );
|
||||
|
||||
/* Go to the next color */
|
||||
do
|
||||
ctxt->journal_rectangles_color = ((ctxt->journal_rectangles_color + 1) &
|
||||
((1 << 5) - 1));
|
||||
/* We don't want to use black or white */
|
||||
while ((ctxt->journal_rectangles_color & 0x07) == 0
|
||||
|| (ctxt->journal_rectangles_color & 0x07) == 0x07);
|
||||
}
|
||||
|
||||
state->vertex_offset += (4 * batch_len);
|
||||
@ -779,8 +800,7 @@ _cogl_journal_log_quad (float x_1,
|
||||
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
|
||||
cogl_get_modelview_matrix (&entry->model_view);
|
||||
|
||||
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_BATCHING
|
||||
|| cogl_debug_flags & COGL_DEBUG_RECTANGLES))
|
||||
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_BATCHING))
|
||||
_cogl_journal_flush ();
|
||||
|
||||
COGL_TIMER_STOP (_cogl_uprof_context, log_timer);
|
||||
|
@ -48,12 +48,6 @@
|
||||
#include "../gles/cogl-gles2-wrapper.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COGL_GLES
|
||||
#define COGL_MATERIAL_MAX_TEXTURE_UNITS GL_MAX_TEXTURE_UNITS
|
||||
#else
|
||||
#define COGL_MATERIAL_MAX_TEXTURE_UNITS GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
#define glActiveTexture ctx->drv.pf_glActiveTexture
|
||||
#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
|
||||
@ -828,7 +822,7 @@ cogl_material_set_layer (CoglHandle material_handle,
|
||||
_cogl_material_pre_change_notify (material, FALSE, NULL);
|
||||
|
||||
material->n_layers = g_list_length (material->layers);
|
||||
if (material->n_layers >= COGL_MATERIAL_MAX_TEXTURE_UNITS)
|
||||
if (material->n_layers >= _cogl_get_max_texture_image_units ())
|
||||
{
|
||||
if (!(material->flags & COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING))
|
||||
{
|
||||
@ -1551,7 +1545,7 @@ _cogl_material_flush_layers_gl_state (CoglMaterial *material,
|
||||
|
||||
layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DIRTY;
|
||||
|
||||
if ((i+1) >= COGL_MATERIAL_MAX_TEXTURE_UNITS)
|
||||
if ((i+1) >= _cogl_get_max_texture_image_units ())
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -120,8 +120,8 @@ typedef struct _CoglTextureVertex CoglTextureVertex;
|
||||
* @COGL_PIXEL_FORMAT_RGB_565: RGB, 16 bits
|
||||
* @COGL_PIXEL_FORMAT_RGBA_4444: RGBA, 16 bits
|
||||
* @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits
|
||||
* @COGL_PIXEL_FORMAT_YUV: FIXME
|
||||
* @COGL_PIXEL_FORMAT_G_8: FIXME
|
||||
* @COGL_PIXEL_FORMAT_YUV: Not currently supported
|
||||
* @COGL_PIXEL_FORMAT_G_8: Single luminance component
|
||||
* @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits
|
||||
* @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits
|
||||
* @COGL_PIXEL_FORMAT_RGBA_8888: RGBA, 32 bits
|
||||
@ -135,7 +135,23 @@ typedef struct _CoglTextureVertex CoglTextureVertex;
|
||||
* @COGL_PIXEL_FORMAT_RGBA_4444_PRE: Premultiplied RGBA, 16 bits
|
||||
* @COGL_PIXEL_FORMAT_RGBA_5551_PRE: Premultiplied RGBA, 16 bits
|
||||
*
|
||||
* Pixel formats used by COGL.
|
||||
* Pixel formats used by COGL. For the formats with a byte per
|
||||
* component, the order of the components specify the order in
|
||||
* increasing memory addresses. So for example
|
||||
* %COGL_PIXEL_FORMAT_RGB_888 would have the red component in the
|
||||
* lowest address, green in the next address and blue after that
|
||||
* regardless of the endinanness of the system.
|
||||
*
|
||||
* For the 16-bit formats the component order specifies the order
|
||||
* within a 16-bit number from most significant bit to least
|
||||
* significant. So for %COGL_PIXEL_FORMAT_RGB_565, the red component
|
||||
* would be in bits 11-15, the green component would be in 6-11 and
|
||||
* the blue component would be in 1-5. Therefore the order in memory
|
||||
* depends on the endianness of the system.
|
||||
*
|
||||
* When uploading a texture %COGL_PIXEL_FORMAT_ANY can be used as the
|
||||
* internal format. Cogl will try to pick the best format to use
|
||||
* internally and convert the texture data if necessary.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
|
@ -237,8 +237,8 @@ cogl_fixed_get_type (void)
|
||||
g_value_register_transform_func (_cogl_fixed_type, G_TYPE_FLOAT,
|
||||
cogl_value_transform_fixed_float);
|
||||
g_value_register_transform_func (G_TYPE_FLOAT, _cogl_fixed_type,
|
||||
|
||||
cogl_value_transform_float_fixed);
|
||||
|
||||
g_value_register_transform_func (_cogl_fixed_type, G_TYPE_DOUBLE,
|
||||
cogl_value_transform_fixed_double);
|
||||
g_value_register_transform_func (G_TYPE_DOUBLE, _cogl_fixed_type,
|
||||
|
@ -1512,7 +1512,7 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
|
||||
GLuint generic_index = 0;
|
||||
#endif
|
||||
gulong enable_flags = 0;
|
||||
guint max_texcoord_attrib_unit = 0;
|
||||
guint max_texcoord_attrib_unit = -1;
|
||||
const GList *layers;
|
||||
guint32 fallback_layers = 0;
|
||||
guint32 disable_layers = ~0;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "cogl-winsys.h"
|
||||
#include "cogl-framebuffer-private.h"
|
||||
#include "cogl-matrix-private.h"
|
||||
#include "cogl-journal-private.h"
|
||||
|
||||
#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
|
||||
#include "cogl-gles2-wrapper.h"
|
||||
@ -155,6 +156,16 @@ cogl_clear (const CoglColor *color, gulong buffers)
|
||||
|
||||
glClear (gl_buffers);
|
||||
|
||||
/* This is a debugging variable used to visually display the quad
|
||||
batches from the journal. It is reset here to increase the
|
||||
chances of getting the same colours for each frame during an
|
||||
animation */
|
||||
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_RECTANGLES))
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
|
||||
ctxt->journal_rectangles_color = 1;
|
||||
}
|
||||
|
||||
COGL_NOTE (DRAW, "Clear end");
|
||||
}
|
||||
|
||||
@ -729,10 +740,11 @@ cogl_end_gl (void)
|
||||
}
|
||||
|
||||
static CoglTextureUnit *
|
||||
_cogl_texture_unit_new (void)
|
||||
_cogl_texture_unit_new (int index_)
|
||||
{
|
||||
CoglTextureUnit *unit = g_new0 (CoglTextureUnit, 1);
|
||||
unit->matrix_stack = _cogl_matrix_stack_new ();
|
||||
unit->index = index_;
|
||||
return unit;
|
||||
}
|
||||
|
||||
@ -766,7 +778,7 @@ _cogl_get_texture_unit (int index_)
|
||||
/* NB: if we now insert a new layer before l, that will maintain order.
|
||||
*/
|
||||
|
||||
unit = _cogl_texture_unit_new ();
|
||||
unit = _cogl_texture_unit_new (index_);
|
||||
|
||||
/* Note: see comment after for() loop above */
|
||||
ctx->texture_units =
|
||||
@ -787,6 +799,36 @@ _cogl_destroy_texture_units (void)
|
||||
g_list_free (ctx->texture_units);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is more complicated than that, another pass needs to be done when
|
||||
* cogl have a neat way of saying if we are using the fixed function pipeline
|
||||
* or not (for the GL case):
|
||||
* MAX_TEXTURE_UNITS: fixed function pipeline, a texture unit has both a
|
||||
* sampler and a set of texture coordinates
|
||||
* MAX_TEXTURE_IMAGE_UNITS: number of samplers one can use from a fragment
|
||||
* program/shader (ARBfp1.0 asm/GLSL)
|
||||
* MAX_VERTEX_TEXTURE_UNITS: number of samplers one can use from a vertex
|
||||
* program/shader (can be 0)
|
||||
* MAX_COMBINED_TEXTURE_IMAGE_UNITS: Maximum samplers one can use, counting both
|
||||
* the vertex and fragment shaders
|
||||
*
|
||||
* If both the vertex shader and the fragment processing stage access the same
|
||||
* texture image unit, then that counts as using two texture image units
|
||||
* against the latter limit: http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
|
||||
*
|
||||
* Note that, for now, we use GL_MAX_TEXTURE_UNITS as we are exposing the
|
||||
* fixed function pipeline.
|
||||
*/
|
||||
guint
|
||||
_cogl_get_max_texture_image_units (void)
|
||||
{
|
||||
GLint nb_texture_image_units;
|
||||
|
||||
GE( glGetIntegerv(GL_MAX_TEXTURE_UNITS, &nb_texture_image_units) );
|
||||
|
||||
return nb_texture_image_units;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_push_matrix (void)
|
||||
{
|
||||
|
@ -33,4 +33,4 @@ libclutter_win32_la_SOURCES = \
|
||||
|
||||
CLEANFILES = clutter-win32-$(CLUTTER_API_VERSION).pc
|
||||
|
||||
EXTRA_DIST = clutter-win32.pc.in
|
||||
EXTRA_DIST = clutter-win32.pc.in resources.rc invisible-cursor.cur
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "../clutter-event.h"
|
||||
#include "../clutter-main.h"
|
||||
#include "../clutter-input-device.h"
|
||||
#include "../clutter-debug.h"
|
||||
#include "../clutter-private.h"
|
||||
#include "../clutter-version.h"
|
||||
@ -47,6 +48,8 @@ static ClutterBackendWin32 *backend_singleton = NULL;
|
||||
|
||||
static gchar *clutter_vblank_name = NULL;
|
||||
|
||||
static HINSTANCE clutter_hinst = NULL;
|
||||
|
||||
gboolean
|
||||
clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
@ -62,11 +65,45 @@ clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
||||
static void
|
||||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
HCURSOR
|
||||
_clutter_backend_win32_get_invisible_cursor (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
||||
|
||||
if (backend_win32->invisible_cursor == NULL)
|
||||
backend_win32->invisible_cursor =
|
||||
LoadCursor (clutter_hinst, MAKEINTRESOURCE (42));
|
||||
|
||||
return backend_win32->invisible_cursor;
|
||||
}
|
||||
|
||||
static const GOptionEntry entries[] =
|
||||
{
|
||||
{
|
||||
@ -353,6 +390,7 @@ clutter_backend_win32_init (ClutterBackendWin32 *backend_win32)
|
||||
|
||||
backend_win32->gl_context = NULL;
|
||||
backend_win32->no_event_retrieval = FALSE;
|
||||
backend_win32->invisible_cursor = NULL;
|
||||
|
||||
/* FIXME: get from GetSystemMetric? */
|
||||
clutter_backend_set_double_click_time (backend, 250);
|
||||
@ -370,3 +408,13 @@ _clutter_backend_impl_get_type (void)
|
||||
{
|
||||
return clutter_backend_win32_get_type ();
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH)
|
||||
/* Store the module handle so that we can use it to load resources */
|
||||
clutter_hinst = hinst;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -48,7 +48,12 @@ struct _ClutterBackendWin32
|
||||
HGLRC gl_context;
|
||||
gboolean no_event_retrieval;
|
||||
|
||||
HCURSOR invisible_cursor;
|
||||
|
||||
GSource *event_source;
|
||||
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterInputDevice *core_keyboard;
|
||||
};
|
||||
|
||||
struct _ClutterBackendWin32Class
|
||||
@ -68,6 +73,8 @@ clutter_backend_win32_add_options (ClutterBackend *backend,
|
||||
ClutterFeatureFlags
|
||||
clutter_backend_win32_get_features (ClutterBackend *backend);
|
||||
|
||||
HCURSOR _clutter_backend_win32_get_invisible_cursor (ClutterBackend *backend);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BACKEND_WIN32_H__ */
|
||||
|
@ -201,9 +201,13 @@ get_modifier_state (WPARAM wparam)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
make_button_event (const MSG *msg, ClutterEvent *event,
|
||||
int button, int click_count, gboolean release)
|
||||
static inline void
|
||||
make_button_event (const MSG *msg,
|
||||
ClutterEvent *event,
|
||||
int button,
|
||||
int click_count,
|
||||
gboolean release,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
event->type = release ? CLUTTER_BUTTON_RELEASE : CLUTTER_BUTTON_PRESS;
|
||||
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.button = button;
|
||||
event->button.click_count = click_count;
|
||||
event->button.device = device;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -429,39 +434,39 @@ message_translate (ClutterBackend *backend,
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
make_button_event (msg, event, 1, 1, FALSE);
|
||||
make_button_event (msg, event, 1, 1, FALSE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_MBUTTONDOWN:
|
||||
make_button_event (msg, event, 2, 1, FALSE);
|
||||
make_button_event (msg, event, 2, 1, FALSE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
make_button_event (msg, event, 3, 1, FALSE);
|
||||
make_button_event (msg, event, 3, 1, FALSE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
make_button_event (msg, event, 1, 1, TRUE);
|
||||
make_button_event (msg, event, 1, 1, TRUE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_MBUTTONUP:
|
||||
make_button_event (msg, event, 2, 1, TRUE);
|
||||
make_button_event (msg, event, 2, 1, TRUE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_RBUTTONUP:
|
||||
make_button_event (msg, event, 3, 1, TRUE);
|
||||
make_button_event (msg, event, 3, 1, TRUE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDBLCLK:
|
||||
make_button_event (msg, event, 1, 2, FALSE);
|
||||
make_button_event (msg, event, 1, 2, FALSE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_MBUTTONDBLCLK:
|
||||
make_button_event (msg, event, 2, 2, FALSE);
|
||||
make_button_event (msg, event, 2, 2, FALSE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_RBUTTONDBLCLK:
|
||||
make_button_event (msg, event, 3, 2, FALSE);
|
||||
make_button_event (msg, event, 3, 2, FALSE, backend_win32->core_pointer);
|
||||
break;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
@ -469,8 +474,8 @@ message_translate (ClutterBackend *backend,
|
||||
|
||||
event->type = CLUTTER_SCROLL;
|
||||
event->scroll.time = msg->time;
|
||||
event->scroll.modifier_state
|
||||
= get_modifier_state (LOWORD (msg->wParam));
|
||||
event->scroll.modifier_state = get_modifier_state (LOWORD (msg->wParam));
|
||||
event->scroll.device = backend_win32->core_pointer;
|
||||
|
||||
/* conversion to window coordinates is required */
|
||||
{
|
||||
@ -500,7 +505,9 @@ message_translate (ClutterBackend *backend,
|
||||
event->motion.x = GET_X_LPARAM (msg->lParam);
|
||||
event->motion.y = GET_Y_LPARAM (msg->lParam);
|
||||
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 */
|
||||
if (!stage_win32->tracking_mouse)
|
||||
{
|
||||
@ -511,6 +518,9 @@ message_translate (ClutterBackend *backend,
|
||||
tmevent.hwndTrack = stage_win32->hwnd;
|
||||
TrackMouseEvent (&tmevent);
|
||||
|
||||
/* we entered the stage */
|
||||
_clutter_input_device_set_stage (event->motion.device, stage);
|
||||
|
||||
stage_win32->tracking_mouse = TRUE;
|
||||
}
|
||||
break;
|
||||
@ -520,6 +530,10 @@ message_translate (ClutterBackend *backend,
|
||||
event->crossing.time = msg->time;
|
||||
event->crossing.x = msg->pt.x;
|
||||
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
|
||||
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.modifier_state = get_key_modifier_state (key_states);
|
||||
event->key.hardware_keycode = scan_code;
|
||||
event->key.device = backend_win32->core_keyboard;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -616,6 +631,20 @@ message_translate (ClutterBackend *backend,
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SETCURSOR:
|
||||
/* If the cursor is in the window's client area and the stage's
|
||||
cursor should be invisible then we'll set a blank cursor
|
||||
instead */
|
||||
if (LOWORD (msg->lParam) == HTCLIENT && !stage_win32->is_cursor_visible)
|
||||
{
|
||||
if (call_def_window_proc)
|
||||
*call_def_window_proc = FALSE;
|
||||
_clutter_stage_win32_update_cursor (stage_win32);
|
||||
}
|
||||
|
||||
res = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ignore every other message */
|
||||
res = FALSE;
|
||||
|
@ -216,17 +216,51 @@ clutter_stage_win32_set_title (ClutterStageWindow *stage_window,
|
||||
SetWindowTextW (stage_win32->hwnd, stage_win32->wtitle);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_win32_update_cursor (ClutterStageWin32 *stage_win32)
|
||||
{
|
||||
HCURSOR cursor;
|
||||
|
||||
if (stage_win32->is_cursor_visible)
|
||||
cursor = (HCURSOR) GetClassLongPtrW (stage_win32->hwnd, GCL_HCURSOR);
|
||||
else
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
/* The documentation implies that we can just use
|
||||
SetCursor(NULL) to get rid of the cursor but apparently this
|
||||
doesn't work very well so instead we create an invisible
|
||||
cursor */
|
||||
cursor = _clutter_backend_win32_get_invisible_cursor (backend);
|
||||
}
|
||||
|
||||
SetCursor (cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_win32_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||
gboolean cursor_visible)
|
||||
{
|
||||
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
|
||||
|
||||
if (stage_win32->is_cursor_visible != cursor_visible &&
|
||||
stage_win32->tracking_mouse)
|
||||
ShowCursor (cursor_visible);
|
||||
if (stage_win32->is_cursor_visible != cursor_visible)
|
||||
{
|
||||
POINT cursor_pos;
|
||||
RECT client_rect;
|
||||
|
||||
stage_win32->is_cursor_visible = cursor_visible;
|
||||
|
||||
/* If the cursor is already over the client area of the window
|
||||
then we need to update it immediately */
|
||||
GetCursorPos (&cursor_pos);
|
||||
if (WindowFromPoint (cursor_pos) == stage_win32->hwnd &&
|
||||
ScreenToClient (stage_win32->hwnd, &cursor_pos) &&
|
||||
GetClientRect (stage_win32->hwnd, &client_rect) &&
|
||||
cursor_pos.x >= client_rect.left &&
|
||||
cursor_pos.y >= client_rect.top &&
|
||||
cursor_pos.x < client_rect.right &&
|
||||
cursor_pos.y < client_rect.bottom)
|
||||
_clutter_stage_win32_update_cursor (stage_win32);
|
||||
}
|
||||
}
|
||||
|
||||
static LONG
|
||||
@ -442,7 +476,7 @@ clutter_stage_win32_realize (ClutterStageWindow *stage_window)
|
||||
win_xpos = stage_win32->fullscreen_rect.left;
|
||||
win_ypos = stage_win32->fullscreen_rect.top;
|
||||
win_width = stage_win32->fullscreen_rect.right - win_xpos;
|
||||
win_height = stage_win32->fullscreen_rect.left - win_ypos;
|
||||
win_height = stage_win32->fullscreen_rect.bottom - win_ypos;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -80,6 +80,8 @@ LRESULT CALLBACK _clutter_stage_win32_window_proc (HWND hwnd,
|
||||
void _clutter_stage_win32_get_min_max_info (ClutterStageWin32 *stage_win32,
|
||||
MINMAXINFO *min_max_info);
|
||||
|
||||
void _clutter_stage_win32_update_cursor (ClutterStageWin32 *stage_win32);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_H__ */
|
||||
|
BIN
clutter/win32/invisible-cursor.cur
Normal file
BIN
clutter/win32/invisible-cursor.cur
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 B |
1
clutter/win32/resources.rc
Normal file
1
clutter/win32/resources.rc
Normal file
@ -0,0 +1 @@
|
||||
42 CURSOR "invisible-cursor.cur"
|
@ -43,6 +43,8 @@ libclutter_x11_la_SOURCES = \
|
||||
clutter-backend-x11.h \
|
||||
clutter-backend-x11.c \
|
||||
clutter-event-x11.c \
|
||||
clutter-input-device-x11.h \
|
||||
clutter-input-device-x11.c \
|
||||
clutter-stage-x11.h \
|
||||
clutter-stage-x11.c \
|
||||
clutter-x11-enum-types.h \
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "clutter-backend-x11.h"
|
||||
#include "clutter-input-device-x11.h"
|
||||
#include "clutter-stage-x11.h"
|
||||
#include "clutter-x11.h"
|
||||
|
||||
@ -46,31 +47,16 @@
|
||||
#include <X11/extensions/XInput.h>
|
||||
#endif
|
||||
|
||||
#include "../clutter-event.h"
|
||||
#include "../clutter-main.h"
|
||||
#include "../clutter-debug.h"
|
||||
#include "../clutter-private.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);
|
||||
|
||||
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
|
||||
* the member of the ClutterBackendX11 structure if you add an
|
||||
* atom name here. do not change the order!
|
||||
@ -109,6 +95,129 @@ static gboolean clutter_synchronise = FALSE;
|
||||
static int TrappedErrorCode = 0;
|
||||
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
|
||||
clutter_backend_x11_pre_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
@ -199,9 +308,8 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
|
||||
|
||||
clutter_backend_set_resolution (backend, dpi);
|
||||
|
||||
#ifdef HAVE_XINPUT
|
||||
_clutter_x11_register_xinput ();
|
||||
#endif
|
||||
/* register input devices */
|
||||
clutter_x11_register_input_devices (backend_x11);
|
||||
|
||||
if (clutter_synchronise)
|
||||
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
|
||||
_clutter_x11_select_events (Window xwin)
|
||||
{
|
||||
#ifdef HAVE_XINPUT
|
||||
GSList *list_it;
|
||||
ClutterX11XInputDevice *device = NULL;
|
||||
ClutterDeviceManager *manager;
|
||||
const GSList *l;
|
||||
|
||||
ClutterMainContext *context;
|
||||
|
||||
context = _clutter_context_get_default ();
|
||||
|
||||
if (!backend_singleton)
|
||||
if (G_UNLIKELY (backend_singleton == NULL))
|
||||
{
|
||||
g_critical ("X11 backend has not been initialised");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (list_it = context->input_devices;
|
||||
list_it != NULL;
|
||||
list_it = list_it->next)
|
||||
{
|
||||
device = (ClutterX11XInputDevice *)list_it->data;
|
||||
manager = clutter_device_manager_get_default ();
|
||||
|
||||
XSelectExtensionEvent (backend_singleton->xdpy,
|
||||
xwin,
|
||||
device->xevent_list,
|
||||
device->num_events);
|
||||
for (l = clutter_device_manager_peek_devices (manager);
|
||||
l != NULL;
|
||||
l = l->next)
|
||||
{
|
||||
ClutterInputDevice *device = l->data;
|
||||
|
||||
_clutter_input_device_x11_select_events (device, backend_singleton, xwin);
|
||||
}
|
||||
#endif /* HAVE_XINPUT */
|
||||
}
|
||||
@ -884,49 +782,34 @@ _clutter_x11_select_events (Window xwin)
|
||||
ClutterInputDevice *
|
||||
_clutter_x11_get_device_for_xid (XID id)
|
||||
{
|
||||
#ifdef HAVE_XINPUT
|
||||
ClutterMainContext *context;
|
||||
GSList *l;
|
||||
ClutterDeviceManager *manager;
|
||||
|
||||
context = _clutter_context_get_default ();
|
||||
manager = clutter_device_manager_get_default ();
|
||||
|
||||
if (!backend_singleton)
|
||||
{
|
||||
g_critical ("X11 backend has not been initialised");
|
||||
return NULL;
|
||||
return clutter_device_manager_get_device (manager, (gint) id);
|
||||
}
|
||||
|
||||
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 *
|
||||
clutter_x11_get_input_devices (void)
|
||||
{
|
||||
#ifdef HAVE_XINPUT
|
||||
ClutterMainContext *context;
|
||||
ClutterDeviceManager *manager;
|
||||
|
||||
if (!backend_singleton)
|
||||
{
|
||||
g_critical ("X11 backend has not been initialised");
|
||||
return NULL;
|
||||
}
|
||||
manager = clutter_device_manager_get_default ();
|
||||
|
||||
context = _clutter_context_get_default ();
|
||||
|
||||
return context->input_devices;
|
||||
#else /* !HAVE_XINPUT */
|
||||
return NULL;
|
||||
#endif /* HAVE_XINPUT */
|
||||
return clutter_device_manager_peek_devices (manager);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -943,7 +826,7 @@ gboolean
|
||||
clutter_x11_has_xinput (void)
|
||||
{
|
||||
#ifdef HAVE_XINPUT
|
||||
if (!backend_singleton)
|
||||
if (backend_singleton == NULL)
|
||||
{
|
||||
g_critical ("X11 backend has not been initialised");
|
||||
return FALSE;
|
||||
|
@ -76,10 +76,14 @@ struct _ClutterBackendX11
|
||||
Atom atom_NET_WM_NAME;
|
||||
Atom atom_UTF8_STRING;
|
||||
|
||||
int xi_event_base;
|
||||
int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
|
||||
gboolean have_xinput;
|
||||
|
||||
Time last_event_time;
|
||||
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterInputDevice *core_keyboard;
|
||||
};
|
||||
|
||||
struct _ClutterBackendX11Class
|
||||
@ -125,12 +129,6 @@ clutter_backend_x11_get_features (ClutterBackend *backend);
|
||||
XVisualInfo *
|
||||
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11);
|
||||
|
||||
void
|
||||
_clutter_x11_register_xinput (void);
|
||||
|
||||
void
|
||||
_clutter_x11_unregister_xinput (void);
|
||||
|
||||
ClutterInputDevice *
|
||||
_clutter_x11_get_device_for_xid (XID id);
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
/* Clutter.
|
||||
* 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
|
||||
* 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
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authored by:
|
||||
* Matthew Allum <mallum@openedhand.com>
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#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_set_can_recurse (source, TRUE);
|
||||
g_source_attach (source, NULL);
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
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->xkey.serial = xkev->serial;
|
||||
@ -416,6 +421,8 @@ event_translate (ClutterBackend *backend,
|
||||
ClutterStageWindow *impl;
|
||||
gboolean res, not_yet_handled = FALSE;
|
||||
Window xwindow, stage_xwindow;
|
||||
ClutterDeviceManager *manager;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
|
||||
@ -424,13 +431,12 @@ event_translate (ClutterBackend *backend,
|
||||
if (backend_x11->event_filters)
|
||||
{
|
||||
GSList *node;
|
||||
ClutterX11EventFilter *filter;
|
||||
|
||||
node = backend_x11->event_filters;
|
||||
|
||||
while (node)
|
||||
{
|
||||
filter = node->data;
|
||||
ClutterX11EventFilter *filter = node->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 filters might be getting events for other windows, so do not
|
||||
* mess them about.
|
||||
/* Do further processing only on events for the stage window (the x11
|
||||
* filters might be getting events for other windows, so do not mess
|
||||
* them about.
|
||||
*/
|
||||
stage = clutter_x11_get_stage_from_window (xwindow);
|
||||
|
||||
if (stage == NULL)
|
||||
return FALSE;
|
||||
|
||||
manager = clutter_device_manager_get_default ();
|
||||
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||
stage_xwindow = xwindow; /* clutter_x11_get_stage_window (stage); */
|
||||
@ -621,6 +627,8 @@ event_translate (ClutterBackend *backend,
|
||||
|
||||
case KeyPress:
|
||||
event->key.type = event->type = CLUTTER_KEY_PRESS;
|
||||
event->key.device = backend_x11->core_keyboard;
|
||||
|
||||
translate_key_event (backend, event, xevent);
|
||||
|
||||
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.device = backend_x11->core_keyboard;
|
||||
|
||||
translate_key_event (backend, event, xevent);
|
||||
break;
|
||||
|
||||
@ -666,14 +676,11 @@ event_translate (ClutterBackend *backend,
|
||||
/* Input device event handling.. */
|
||||
if (not_yet_handled)
|
||||
{
|
||||
if (!clutter_x11_has_xinput ())
|
||||
{
|
||||
device = backend_x11->core_pointer;
|
||||
|
||||
/* Regular X event */
|
||||
switch (xevent->type)
|
||||
{
|
||||
/* KeyPress / KeyRelease should reside here if XInput
|
||||
* worked properly
|
||||
*/
|
||||
case ButtonPress:
|
||||
switch (xevent->xbutton.button)
|
||||
{
|
||||
@ -696,8 +703,9 @@ event_translate (ClutterBackend *backend,
|
||||
event->scroll.x = xevent->xbutton.x;
|
||||
event->scroll.y = xevent->xbutton.y;
|
||||
event->scroll.modifier_state = xevent->xbutton.state;
|
||||
|
||||
event->scroll.device = device;
|
||||
break;
|
||||
|
||||
default:
|
||||
event->button.type = event->type = CLUTTER_BUTTON_PRESS;
|
||||
event->button.time = xevent->xbutton.time;
|
||||
@ -705,11 +713,13 @@ event_translate (ClutterBackend *backend,
|
||||
event->button.y = xevent->xbutton.y;
|
||||
event->button.modifier_state = xevent->xbutton.state;
|
||||
event->button.button = xevent->xbutton.button;
|
||||
|
||||
event->button.device = device;
|
||||
break;
|
||||
}
|
||||
|
||||
set_user_time (backend_x11, &xwindow, event->button.time);
|
||||
|
||||
res = TRUE;
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
@ -720,7 +730,7 @@ event_translate (ClutterBackend *backend,
|
||||
xevent->xbutton.button == 7)
|
||||
{
|
||||
res = FALSE;
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
|
||||
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
||||
@ -729,6 +739,9 @@ event_translate (ClutterBackend *backend,
|
||||
event->button.y = xevent->xbutton.y;
|
||||
event->button.modifier_state = xevent->xbutton.state;
|
||||
event->button.button = xevent->xbutton.button;
|
||||
event->button.device = device;
|
||||
|
||||
res = TRUE;
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
@ -737,9 +750,16 @@ event_translate (ClutterBackend *backend,
|
||||
event->motion.x = xevent->xmotion.x;
|
||||
event->motion.y = xevent->xmotion.y;
|
||||
event->motion.modifier_state = xevent->xmotion.state;
|
||||
event->motion.device = device;
|
||||
|
||||
res = TRUE;
|
||||
break;
|
||||
|
||||
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
|
||||
doesn't emit the corresponding motion notify */
|
||||
event->motion.type = event->type = CLUTTER_MOTION;
|
||||
@ -747,34 +767,70 @@ event_translate (ClutterBackend *backend,
|
||||
event->motion.x = xevent->xcrossing.x;
|
||||
event->motion.y = xevent->xcrossing.y;
|
||||
event->motion.modifier_state = xevent->xcrossing.state;
|
||||
event->motion.source = CLUTTER_ACTOR (stage);
|
||||
event->motion.device = device;
|
||||
|
||||
res = TRUE;
|
||||
break;
|
||||
|
||||
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.time = xevent->xcrossing.time;
|
||||
event->crossing.x = xevent->xcrossing.x;
|
||||
event->crossing.y = xevent->xcrossing.y;
|
||||
event->crossing.source = CLUTTER_ACTOR (stage);
|
||||
event->crossing.device = device;
|
||||
res = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ignore every other event */
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* XInput fun.. Needs clean up. */
|
||||
|
||||
/* XInput fun...*/
|
||||
if (!res && clutter_x11_has_xinput ())
|
||||
{
|
||||
#ifdef HAVE_XINPUT
|
||||
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);
|
||||
|
||||
if (xevent->type == ev_types [CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT])
|
||||
if (xevent->type == button_press)
|
||||
{
|
||||
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,
|
||||
device->device_name,
|
||||
xbev->x,
|
||||
xbev->y);
|
||||
|
||||
@ -799,7 +855,7 @@ event_translate (ClutterBackend *backend,
|
||||
event->scroll.x = xbev->x;
|
||||
event->scroll.y = xbev->y;
|
||||
event->scroll.modifier_state = xbev->state;
|
||||
event->scroll.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||
event->scroll.device = device;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -809,19 +865,24 @@ event_translate (ClutterBackend *backend,
|
||||
event->button.y = xbev->y;
|
||||
event->button.modifier_state = xbev->state;
|
||||
event->button.button = xbev->button;
|
||||
event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||
event->button.device = device;
|
||||
break;
|
||||
}
|
||||
|
||||
set_user_time (backend_x11, &xwindow, xbev->time);
|
||||
|
||||
res = TRUE;
|
||||
}
|
||||
else if (xevent->type
|
||||
== ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT])
|
||||
else if (xevent->type == button_release)
|
||||
{
|
||||
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,
|
||||
device->device_name,
|
||||
xbev->x,
|
||||
xbev->y);
|
||||
|
||||
@ -831,7 +892,8 @@ event_translate (ClutterBackend *backend,
|
||||
xbev->button == 6 ||
|
||||
xbev->button == 7)
|
||||
{
|
||||
return FALSE;
|
||||
res = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
||||
@ -840,15 +902,20 @@ event_translate (ClutterBackend *backend,
|
||||
event->button.y = xbev->y;
|
||||
event->button.modifier_state = xbev->state;
|
||||
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
|
||||
== ev_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT])
|
||||
else if (xevent->type == motion_notify)
|
||||
{
|
||||
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,
|
||||
device->device_name,
|
||||
xmev->x,
|
||||
xmev->y);
|
||||
|
||||
@ -857,39 +924,30 @@ event_translate (ClutterBackend *backend,
|
||||
event->motion.x = xmev->x;
|
||||
event->motion.y = xmev->y;
|
||||
event->motion.modifier_state = xmev->state;
|
||||
event->motion.device = _clutter_x11_get_device_for_xid (xmev->deviceid);
|
||||
}
|
||||
#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
|
||||
*/
|
||||
event->motion.device = device;
|
||||
|
||||
else if (xevent->type
|
||||
== ev_types [CLUTTER_X11_XINPUT_KEY_PRESS_EVENT])
|
||||
res = TRUE;
|
||||
}
|
||||
else if (xevent->type == key_press || xevent->type == key_release)
|
||||
{
|
||||
XEvent xevent_converted;
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
|
||||
if (xevent->type == key_press)
|
||||
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
|
||||
#endif /* HAVE_XINPUT */
|
||||
{
|
||||
@ -897,8 +955,8 @@ event_translate (ClutterBackend *backend,
|
||||
res = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
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,14 +121,16 @@ gboolean clutter_x11_has_event_retrieval (void);
|
||||
|
||||
ClutterStage *clutter_x11_get_stage_from_window (Window win);
|
||||
|
||||
#ifndef CLUTTER_DISABLE_DEPRECATED
|
||||
G_CONST_RETURN GSList* clutter_x11_get_input_devices (void);
|
||||
#endif
|
||||
|
||||
void clutter_x11_enable_xinput (void);
|
||||
gboolean clutter_x11_has_xinput (void);
|
||||
|
||||
gboolean clutter_x11_has_composite_extension (void);
|
||||
|
||||
void clutter_X11_set_use_argb_visual (gboolean use_argb);
|
||||
void clutter_x11_set_use_argb_visual (gboolean use_argb);
|
||||
gboolean clutter_x11_get_use_argb_visual (void);
|
||||
|
||||
Time clutter_x11_get_current_event_time (void);
|
||||
|
58
configure.ac
58
configure.ac
@ -12,7 +12,7 @@
|
||||
# - increase clutter_interface_version to the next odd number
|
||||
m4_define([clutter_major_version], [1])
|
||||
m4_define([clutter_minor_version], [1])
|
||||
m4_define([clutter_micro_version], [5])
|
||||
m4_define([clutter_micro_version], [7])
|
||||
|
||||
m4_define([clutter_release_status],
|
||||
[m4_if(m4_eval(clutter_micro_version % 2), [1], [git],
|
||||
@ -56,7 +56,7 @@ AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_AUX_DIR([build])
|
||||
AC_CONFIG_MACRO_DIR([build/autotools])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.9.6 foreign])
|
||||
AM_INIT_AUTOMAKE([1.9.6 foreign -Wno-portability no-define])
|
||||
|
||||
CLUTTER_MAJOR_VERSION=clutter_major_version
|
||||
CLUTTER_MINOR_VERSION=clutter_minor_version
|
||||
@ -364,11 +364,18 @@ AS_CASE([$CLUTTER_WINSYS],
|
||||
WIN32_CFLAGS="-D_WIN32_WINNT=0x0500"
|
||||
WIN32_LIBS="-lopengl32 -lgdi32 -lwinmm"
|
||||
CLUTTER_LT_LDFLAGS="$CLUTTER_LT_LDFLAGS -no-undefined"
|
||||
|
||||
AC_CHECK_TOOL(WINDRES, windres, no)
|
||||
if test "$WINDRES" = no; then
|
||||
AC_MSG_ERROR([*** windres is required])
|
||||
fi
|
||||
],
|
||||
|
||||
[AC_MSG_ERROR([Invalid backend for Clutter: use glx, sdl, osx, win32, eglx, eglnative or fruity])]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(WINSYS_WIN32, [test "x$CLUTTER_WINSYS" = "xwin32"])
|
||||
|
||||
# at this point we must have a GL header to check
|
||||
AS_IF([test "x$clutter_gl_header" = "x"], [AC_MSG_ERROR([Internal error: no GL header set])])
|
||||
AC_CHECK_HEADERS([$clutter_gl_header],
|
||||
@ -689,6 +696,18 @@ AS_CASE([$enable_cogl_debug],
|
||||
|
||||
AC_SUBST(COGL_DEBUG_CFLAGS)
|
||||
|
||||
dnl === Conformance test suite ================================================
|
||||
|
||||
AC_ARG_ENABLE([conformance],
|
||||
[AC_HELP_STRING([--enable-conformance=@<:@no/yes@:>@],
|
||||
[Build conformance test suite @<:@default=yes@:>@])],
|
||||
[],
|
||||
[enable_conformance=yes])
|
||||
|
||||
AM_CONDITIONAL([BUILD_TESTS], [test "x$enable_conformance" = "xyes"])
|
||||
|
||||
dnl === Profiling =============================================================
|
||||
|
||||
m4_define([profile_default], [no])
|
||||
AC_ARG_ENABLE(profile,
|
||||
AC_HELP_STRING([--enable-profile=@<:@no/yes@:>@],
|
||||
@ -698,22 +717,27 @@ AC_ARG_ENABLE(profile,
|
||||
|
||||
AS_CASE([$enable_profile],
|
||||
|
||||
[yes], [
|
||||
if test "x$GCC" = "xyes"; then
|
||||
[yes],
|
||||
[
|
||||
AS_IF([test "x$GCC" = "xyes"],
|
||||
[
|
||||
PKG_CHECK_MODULES([PROFILE_DEP], [uprof-0.2])
|
||||
CLUTTER_PROFILE_CFLAGS=" -DCLUTTER_ENABLE_PROFILE -DCOGL_ENABLE_PROFILE $PROFILE_DEP_CFLAGS"
|
||||
CLUTTER_PROFILE_LDFLAGS=" $PROFILE_DEP_LIBS"
|
||||
if test "x$enable_debug" = "xyes"; then
|
||||
CLUTTER_PROFILE_CFLAGS+=" -DUPROF_DEBUG"
|
||||
fi
|
||||
else
|
||||
AC_MSG_ERROR([--enable-profile is currently only supported if using GCC])
|
||||
fi
|
||||
|
||||
AS_IF([test "x$enable_debug" = "xyes"], [CLUTTER_PROFILE_CFLAGS+=" -DUPROF_DEBUG"])
|
||||
],
|
||||
[no], [
|
||||
[
|
||||
AC_MSG_ERROR([--enable-profile is currently only supported if using GCC])
|
||||
])
|
||||
],
|
||||
|
||||
[no],
|
||||
[
|
||||
CLUTTER_PROFILE_CFLAGS=""
|
||||
CLUTTER_PROFILE_LDFLAGS=""
|
||||
],
|
||||
|
||||
[*], [AC_MSG_ERROR([Invalid value for --enable-profile])]
|
||||
)
|
||||
AM_CONDITIONAL(PROFILE, test "x$enable_profile" != "xno")
|
||||
@ -735,15 +759,20 @@ and gcov)])],
|
||||
|
||||
AS_IF([test "x$enable_gcov" = "xyes" && test "x$GCC" = "xyes"],
|
||||
[
|
||||
AS_IF([test "x$enable_conformance" = "xno"],
|
||||
[AC_MSG_WARN([Conformance test suite is disabled, the coverage report will be incomplete])],
|
||||
[AC_MSG_RESULT([yes])]
|
||||
)
|
||||
|
||||
GCOV_CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage"
|
||||
GCOV_LDFLAGS="-lgcov"
|
||||
]
|
||||
],
|
||||
[AC_MSG_RESULT([no])]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([GCOV_ENABLED], [test "x$enable_gcov" = "xyes"])
|
||||
AC_SUBST([GCOV_CFLAGS])
|
||||
AC_SUBST([GCOV_LDFLAGS])
|
||||
AC_MSG_RESULT([$enable_gcov])
|
||||
|
||||
dnl === Enable strict compiler flags ==========================================
|
||||
|
||||
@ -868,6 +897,7 @@ AC_CONFIG_FILES([
|
||||
Makefile
|
||||
build/Makefile
|
||||
build/autotools/Makefile
|
||||
build/mingw/Makefile
|
||||
clutter/Makefile
|
||||
clutter/clutter-version.h
|
||||
clutter/clutter-json.h
|
||||
@ -945,7 +975,7 @@ echo " Build Additional Documentation: ${enable_docs} (Generate PDF: ${en
|
||||
echo ""
|
||||
echo " • Extra:"
|
||||
echo " Build introspection data: ${enable_introspection}"
|
||||
echo " Build test suite: ${enable_glibtest}"
|
||||
echo " Build conformance test suite: ${enable_conformance}"
|
||||
|
||||
if test "x$have_json" = "xyes"; then
|
||||
echo " JSON-GLib: system"
|
||||
|
@ -57,7 +57,7 @@ Short explanation of the commit
|
||||
Longer explanation explaining exactly what's changed, whether any
|
||||
external or private interfaces changed, what bugs were fixed (with bug
|
||||
tracker reference if applicable) and so forth. Be concise but not too
|
||||
brief.
|
||||
brief. Don't be afraid of using UTF-8, or even ASCII art.
|
||||
=== end example commit ===
|
||||
|
||||
Always add a brief description of the commit to the _first_ line of
|
||||
|
@ -68,6 +68,7 @@ IGNORE_HFILES=\
|
||||
clutter-debug.h \
|
||||
clutter-deprecated.h \
|
||||
clutter-enum-types.h \
|
||||
clutter-id-pool.h \
|
||||
clutter-json.h \
|
||||
clutter-keysyms.h \
|
||||
clutter-keysyms-table.h \
|
||||
@ -75,7 +76,7 @@ IGNORE_HFILES=\
|
||||
clutter-master-clock.h \
|
||||
clutter-model-private.h \
|
||||
clutter-private.h \
|
||||
clutter-id-pool.h \
|
||||
clutter-profile.h \
|
||||
clutter-script-private.h \
|
||||
clutter-stage-window.h \
|
||||
clutter-timeout-interval.h \
|
||||
|
@ -298,13 +298,12 @@ main (int argc, char *argv[])
|
||||
ClutterBehaviour *behave;
|
||||
ClutterAlpha *alpha;
|
||||
ClutterActor *stage, *actor;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
actor = clutter_texture_new_from_file ("ohpowers.png, NULL);
|
||||
actor = clutter_texture_new_from_file ("ohpowers.png", NULL);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
|
||||
|
||||
/* set up the animation to be 4 seconds long */
|
||||
@ -315,7 +314,7 @@ main (int argc, char *argv[])
|
||||
* alpha will take a reference on the timeline so we can safely
|
||||
* release the reference we hold
|
||||
*/
|
||||
alpha = clutter_alpha_new_full (timeline, CLUTTER_EASE_SINE_IN_OUT);
|
||||
alpha = clutter_alpha_new_full (timeline, CLUTTER_EASE_IN_OUT_SINE);
|
||||
g_object_unref (timeline);
|
||||
|
||||
/* the behaviour will own the alpha by sinking its floating
|
||||
@ -385,9 +384,9 @@ main (int argc, char *argv[])
|
||||
position and a new set of coordinates. The animation takes 200
|
||||
milliseconds to complete and uses a linear progression.</para>
|
||||
<programlisting>
|
||||
clutter_actor_animate (actor, CLUTTER_LINEAR, 200
|
||||
"x", 200,
|
||||
"y", 200,
|
||||
clutter_actor_animate (actor, CLUTTER_LINEAR, 200,
|
||||
"x", 200.0f,
|
||||
"y", 200.0f,
|
||||
NULL);
|
||||
</programlisting>
|
||||
</example>
|
||||
|
@ -139,8 +139,11 @@
|
||||
<xi:include href="xml/clutter-main.xml"/>
|
||||
<xi:include href="xml/clutter-shader.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-util.xml"/>
|
||||
<xi:include href="xml/clutter-feature.xml"/>
|
||||
<xi:include href="xml/clutter-version.xml"/>
|
||||
</chapter>
|
||||
|
||||
|
@ -404,6 +404,7 @@ clutter_actor_create_pango_layout
|
||||
clutter_actor_is_in_clone_paint
|
||||
clutter_actor_set_text_direction
|
||||
clutter_actor_get_text_direction
|
||||
clutter_actor_has_pointer
|
||||
|
||||
<SUBSECTION>
|
||||
ClutterActorBox
|
||||
@ -874,7 +875,7 @@ clutter_param_fixed_get_type
|
||||
|
||||
<SECTION>
|
||||
<FILE>clutter-feature</FILE>
|
||||
<TITLE>GL Features</TITLE>
|
||||
<TITLE>Features</TITLE>
|
||||
ClutterFeatureFlags
|
||||
clutter_feature_available
|
||||
clutter_feature_get_all
|
||||
@ -940,7 +941,6 @@ ClutterMotionEvent
|
||||
ClutterScrollEvent
|
||||
ClutterStageStateEvent
|
||||
ClutterCrossingEvent
|
||||
ClutterInputDevice
|
||||
clutter_event_new
|
||||
clutter_event_copy
|
||||
clutter_event_free
|
||||
@ -977,13 +977,9 @@ clutter_event_get_related
|
||||
clutter_event_get_scroll_direction
|
||||
|
||||
<SUBSECTION>
|
||||
ClutterInputDeviceType
|
||||
clutter_event_get_device
|
||||
clutter_event_get_device_id
|
||||
clutter_event_get_device_type
|
||||
clutter_get_input_device_for_id
|
||||
clutter_input_device_get_device_id
|
||||
clutter_input_device_get_device_type
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_get_current_event_time
|
||||
@ -996,6 +992,51 @@ ClutterAnyEvent
|
||||
clutter_event_get_type
|
||||
</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>
|
||||
<FILE>clutter-main</FILE>
|
||||
<TITLE>General</TITLE>
|
||||
|
@ -40,3 +40,5 @@ clutter_fixed_layout_get_type
|
||||
clutter_bin_layout_get_type
|
||||
clutter_flow_layout_get_type
|
||||
clutter_box_layout_get_type
|
||||
clutter_input_device_get_type
|
||||
clutter_device_manager_get_type
|
||||
|
@ -59,14 +59,13 @@ to this OpenGL code:
|
||||
<programlisting>
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_COLOR);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_COLOR);
|
||||
</programlisting>
|
||||
|
||||
</section>
|
||||
|
@ -1,13 +1,28 @@
|
||||
SUBDIRS = data conform interactive micro-bench tools
|
||||
SUBDIRS = data interactive micro-bench tools
|
||||
|
||||
if BUILD_TESTS
|
||||
SUBDIRS += conform
|
||||
endif
|
||||
|
||||
DIST_SUBDIRS = data conform interactive micro-bench tools
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
||||
.PHONY: test conform
|
||||
if BUILD_TESTS
|
||||
test conform:
|
||||
$(MAKE) -C ./conform test
|
||||
.PHONY: test-report full-report
|
||||
( cd ./conform && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$?
|
||||
|
||||
test-report full-report:
|
||||
$(MAKE) -C ./conform $(@)
|
||||
( cd ./conform && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$?
|
||||
else
|
||||
test conform:
|
||||
@true
|
||||
|
||||
test-report full-report:
|
||||
@true
|
||||
endif # BUILD_TESTS
|
||||
|
||||
.PHONY: test conform test-report full-report
|
||||
|
||||
# run make test as part of make check
|
||||
check-local: test
|
||||
|
@ -41,9 +41,9 @@ check_pixel (GLubyte *pixel, guint32 color)
|
||||
g_print (" expected = %x, %x, %x, %x\n",
|
||||
r, g, b, a);
|
||||
/* FIXME - allow for hardware in-precision */
|
||||
g_assert (pixel[RED] == r);
|
||||
g_assert (pixel[GREEN] == g);
|
||||
g_assert (pixel[BLUE] == b);
|
||||
g_assert_cmpint (pixel[RED], ==, r);
|
||||
g_assert_cmpint (pixel[GREEN], ==, g);
|
||||
g_assert_cmpint (pixel[BLUE], ==, b);
|
||||
|
||||
/* FIXME
|
||||
* We ignore the alpha, since we don't know if our render target is
|
||||
|
@ -180,6 +180,7 @@ test_texture_fbo (TestConformSimpleFixture *fixture,
|
||||
{
|
||||
TestState state;
|
||||
guint idle_source;
|
||||
gulong paint_handler;
|
||||
ClutterActor *actor;
|
||||
int ypos = 0;
|
||||
|
||||
@ -236,12 +237,15 @@ test_texture_fbo (TestConformSimpleFixture *fixture,
|
||||
* will trigger redrawing. */
|
||||
idle_source = g_idle_add (queue_redraw, state.stage);
|
||||
|
||||
g_signal_connect_after (state.stage, "paint", G_CALLBACK (on_paint), &state);
|
||||
paint_handler = g_signal_connect_after (state.stage, "paint",
|
||||
G_CALLBACK (on_paint), &state);
|
||||
|
||||
clutter_actor_show_all (state.stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_signal_handler_disconnect (state.stage, paint_handler);
|
||||
|
||||
g_source_remove (idle_source);
|
||||
|
||||
/* Remove all of the actors from the stage */
|
||||
|
@ -12,14 +12,21 @@
|
||||
typedef struct _TestMultiLayerMaterialState
|
||||
{
|
||||
ClutterActor *group;
|
||||
CoglHandle material;
|
||||
CoglHandle alpha_tex;
|
||||
CoglHandle redhand_tex;
|
||||
CoglHandle light_tex0;
|
||||
gfloat *tex_coords;
|
||||
|
||||
CoglMatrix tex_matrix;
|
||||
CoglMatrix rot_matrix;
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
CoglHandle material0;
|
||||
CoglMatrix tex_matrix0;
|
||||
CoglMatrix rot_matrix0;
|
||||
CoglHandle light_tex0;
|
||||
|
||||
CoglHandle material1;
|
||||
CoglMatrix tex_matrix1;
|
||||
CoglMatrix rot_matrix1;
|
||||
CoglHandle light_tex1;
|
||||
|
||||
} TestMultiLayerMaterialState;
|
||||
|
||||
@ -31,10 +38,15 @@ frame_cb (ClutterTimeline *timeline,
|
||||
{
|
||||
TestMultiLayerMaterialState *state = data;
|
||||
|
||||
cogl_matrix_multiply (&state->tex_matrix,
|
||||
&state->tex_matrix,
|
||||
&state->rot_matrix);
|
||||
cogl_material_set_layer_matrix (state->material, 2, &state->tex_matrix);
|
||||
cogl_matrix_multiply (&state->tex_matrix0,
|
||||
&state->tex_matrix0,
|
||||
&state->rot_matrix0);
|
||||
cogl_material_set_layer_matrix (state->material0, 2, &state->tex_matrix0);
|
||||
|
||||
cogl_matrix_multiply (&state->tex_matrix1,
|
||||
&state->tex_matrix1,
|
||||
&state->rot_matrix1);
|
||||
cogl_material_set_layer_matrix (state->material1, 2, &state->tex_matrix1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -42,18 +54,51 @@ material_rectangle_paint (ClutterActor *actor, gpointer data)
|
||||
{
|
||||
TestMultiLayerMaterialState *state = data;
|
||||
|
||||
cogl_set_source (state->material);
|
||||
cogl_rectangle_with_multitexture_coords (0, 0, 200, 200,
|
||||
cogl_push_matrix ();
|
||||
|
||||
cogl_translate (150, 15, 0);
|
||||
|
||||
cogl_set_source (state->material0);
|
||||
cogl_rectangle_with_multitexture_coords (0, 0, 200, 213,
|
||||
state->tex_coords,
|
||||
12);
|
||||
cogl_translate (-300, -30, 0);
|
||||
cogl_set_source (state->material1);
|
||||
cogl_rectangle_with_multitexture_coords (0, 0, 200, 213,
|
||||
state->tex_coords,
|
||||
12);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
}
|
||||
|
||||
static void
|
||||
animation_completed_cb (ClutterAnimation *animation,
|
||||
TestMultiLayerMaterialState *state)
|
||||
{
|
||||
static gboolean go_back = FALSE;
|
||||
gdouble new_rotation_y;
|
||||
|
||||
if (go_back)
|
||||
new_rotation_y = 30;
|
||||
else
|
||||
new_rotation_y = -30;
|
||||
go_back = !go_back;
|
||||
|
||||
clutter_actor_animate_with_timeline (state->group,
|
||||
CLUTTER_LINEAR,
|
||||
state->timeline,
|
||||
"rotation-angle-y", new_rotation_y,
|
||||
"signal-after::completed",
|
||||
animation_completed_cb, state,
|
||||
NULL);
|
||||
|
||||
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_multitexture_main (int argc, char *argv[])
|
||||
{
|
||||
GError *error = NULL;
|
||||
ClutterTimeline *timeline;
|
||||
ClutterBehaviour *r_behave;
|
||||
ClutterActor *stage;
|
||||
ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff };
|
||||
TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
|
||||
@ -113,55 +158,71 @@ test_cogl_multitexture_main (int argc, char *argv[])
|
||||
if (!state->light_tex0)
|
||||
g_critical ("Failed to load light0.png: %s", error->message);
|
||||
|
||||
state->light_tex1 =
|
||||
cogl_texture_new_from_file (files[2],
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (!state->light_tex1)
|
||||
g_critical ("Failed to load light0.png: %s", error->message);
|
||||
|
||||
g_strfreev (files);
|
||||
|
||||
state->material = cogl_material_new ();
|
||||
cogl_material_set_layer (state->material, 0, state->alpha_tex);
|
||||
cogl_material_set_layer (state->material, 1, state->redhand_tex);
|
||||
cogl_material_set_layer (state->material, 2, state->light_tex0);
|
||||
state->material0 = cogl_material_new ();
|
||||
cogl_material_set_layer (state->material0, 0, state->alpha_tex);
|
||||
cogl_material_set_layer (state->material0, 1, state->redhand_tex);
|
||||
cogl_material_set_layer (state->material0, 2, state->light_tex0);
|
||||
|
||||
state->material1 = cogl_material_new ();
|
||||
cogl_material_set_layer (state->material1, 0, state->alpha_tex);
|
||||
cogl_material_set_layer (state->material1, 1, state->redhand_tex);
|
||||
cogl_material_set_layer (state->material1, 2, state->light_tex1);
|
||||
|
||||
state->tex_coords = tex_coords;
|
||||
|
||||
cogl_matrix_init_identity (&state->tex_matrix);
|
||||
cogl_matrix_init_identity (&state->rot_matrix);
|
||||
cogl_matrix_init_identity (&state->tex_matrix0);
|
||||
cogl_matrix_init_identity (&state->tex_matrix1);
|
||||
cogl_matrix_init_identity (&state->rot_matrix0);
|
||||
cogl_matrix_init_identity (&state->rot_matrix1);
|
||||
|
||||
cogl_matrix_translate (&state->rot_matrix, 0.5, 0.5, 0);
|
||||
cogl_matrix_rotate (&state->rot_matrix, 10.0, 0, 0, 1.0);
|
||||
cogl_matrix_translate (&state->rot_matrix, -0.5, -0.5, 0);
|
||||
cogl_matrix_translate (&state->rot_matrix0, 0.5, 0.5, 0);
|
||||
cogl_matrix_rotate (&state->rot_matrix0, 10.0, 0, 0, 1.0);
|
||||
cogl_matrix_translate (&state->rot_matrix0, -0.5, -0.5, 0);
|
||||
|
||||
cogl_matrix_translate (&state->rot_matrix1, 0.5, 0.5, 0);
|
||||
cogl_matrix_rotate (&state->rot_matrix1, -10.0, 0, 0, 1.0);
|
||||
cogl_matrix_translate (&state->rot_matrix1, -0.5, -0.5, 0);
|
||||
|
||||
clutter_actor_set_anchor_point (state->group, 86, 125);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER(stage),
|
||||
state->group);
|
||||
|
||||
timeline = clutter_timeline_new (7692);
|
||||
clutter_timeline_set_loop (timeline, TRUE);
|
||||
state->timeline = clutter_timeline_new (2812);
|
||||
|
||||
g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), state);
|
||||
g_signal_connect (state->timeline, "new-frame", G_CALLBACK (frame_cb), state);
|
||||
|
||||
r_behave =
|
||||
clutter_behaviour_rotate_new (clutter_alpha_new_full (timeline,
|
||||
CLUTTER_LINEAR),
|
||||
CLUTTER_Y_AXIS,
|
||||
CLUTTER_ROTATE_CW,
|
||||
0.0, 360.0);
|
||||
|
||||
/* Apply it to our actor */
|
||||
clutter_behaviour_apply (r_behave, state->group);
|
||||
clutter_actor_animate_with_timeline (state->group,
|
||||
CLUTTER_LINEAR,
|
||||
state->timeline,
|
||||
"rotation-angle-y", 30.0,
|
||||
"signal-after::completed",
|
||||
animation_completed_cb, state,
|
||||
NULL);
|
||||
|
||||
/* start the timeline and thus the animations */
|
||||
clutter_timeline_start (timeline);
|
||||
clutter_timeline_start (state->timeline);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main();
|
||||
|
||||
cogl_handle_unref (state->material);
|
||||
cogl_handle_unref (state->material1);
|
||||
cogl_handle_unref (state->material0);
|
||||
cogl_handle_unref (state->alpha_tex);
|
||||
cogl_handle_unref (state->redhand_tex);
|
||||
cogl_handle_unref (state->light_tex0);
|
||||
cogl_handle_unref (state->light_tex1);
|
||||
g_free (state);
|
||||
|
||||
g_object_unref (r_behave);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,7 +9,31 @@ typedef struct {
|
||||
|
||||
} 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
|
||||
stage_motion_event_cb (ClutterActor *actor,
|
||||
@ -24,6 +48,11 @@ stage_motion_event_cb (ClutterActor *actor,
|
||||
|
||||
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)
|
||||
{
|
||||
gfloat event_x, event_y;
|
||||
@ -43,6 +72,7 @@ test_devices_main (int argc, char **argv)
|
||||
ClutterActor *stage;
|
||||
TestDevicesApp *app;
|
||||
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
||||
ClutterDeviceManager *manager;
|
||||
const GSList *stage_devices, *l;
|
||||
|
||||
/* force enabling X11 support */
|
||||
@ -63,10 +93,11 @@ test_devices_main (int argc, char **argv)
|
||||
|
||||
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)
|
||||
g_error ("No extended input devices found.");
|
||||
g_error ("No input devices found.");
|
||||
|
||||
for (l = stage_devices; l != NULL; l = l->next)
|
||||
{
|
||||
@ -74,12 +105,15 @@ test_devices_main (int argc, char **argv)
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterActor *hand = NULL;
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
if (device_type == CLUTTER_POINTER_DEVICE)
|
||||
{
|
||||
g_print ("got a pointer device with id %d...\n",
|
||||
g_print ("got a %s device '%s' with id %d...\n",
|
||||
device_type_name (device),
|
||||
clutter_input_device_get_device_name (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
|
||||
G_DIR_SEPARATOR_S
|
||||
"redhand.png",
|
||||
|
@ -48,6 +48,8 @@ static gboolean recenter = FALSE;
|
||||
static ClutterActor *main_stage = NULL;
|
||||
static ClutterActor *easing_mode_label = NULL;
|
||||
|
||||
static ClutterAnimation *last_animation = NULL;
|
||||
|
||||
static void
|
||||
on_animation_completed (ClutterAnimation *animation,
|
||||
ClutterActor *rectangle)
|
||||
@ -113,10 +115,12 @@ on_button_press (ClutterActor *actor,
|
||||
"y", event->y,
|
||||
NULL);
|
||||
|
||||
if (recenter)
|
||||
if (recenter && last_animation != animation)
|
||||
g_signal_connect_after (animation, "completed",
|
||||
G_CALLBACK (on_animation_completed),
|
||||
rectangle);
|
||||
|
||||
last_animation = animation;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -27,6 +27,12 @@ get_event_type_name (const ClutterEvent *event)
|
||||
case CLUTTER_LEAVE:
|
||||
return "LEAVE";
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
return "MOTION";
|
||||
|
||||
case CLUTTER_DELETE:
|
||||
return "DELETE";
|
||||
|
||||
default:
|
||||
return "EVENT";
|
||||
}
|
||||
@ -127,26 +133,33 @@ fill_keybuf (char *keybuf, ClutterKeyEvent *event)
|
||||
sprintf (keybuf, "'%s' ", utf8);
|
||||
|
||||
/* key combination (<Mod1>s, <Shift><Mod1>S, <Ctrl><Mod1>Delete) */
|
||||
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval),
|
||||
utf8);
|
||||
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval), utf8);
|
||||
utf8[len] = '\0';
|
||||
|
||||
if (event->modifier_state & CLUTTER_SHIFT_MASK)
|
||||
strcat (keybuf, "<Shift>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_LOCK_MASK)
|
||||
strcat (keybuf, "<Lock>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_CONTROL_MASK)
|
||||
strcat (keybuf, "<Control>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD1_MASK)
|
||||
strcat (keybuf, "<Mod1>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD2_MASK)
|
||||
strcat (keybuf, "<Mod2>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD3_MASK)
|
||||
strcat (keybuf, "<Mod3>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD4_MASK)
|
||||
strcat (keybuf, "<Mod4>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD5_MASK)
|
||||
strcat (keybuf, "<Mod5>");
|
||||
|
||||
strcat (keybuf, utf8);
|
||||
}
|
||||
|
||||
@ -156,62 +169,83 @@ input_cb (ClutterActor *actor,
|
||||
gpointer data)
|
||||
{
|
||||
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)
|
||||
{
|
||||
case CLUTTER_KEY_PRESS:
|
||||
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;
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
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;
|
||||
case CLUTTER_MOTION:
|
||||
g_print ("[%s] MOTION", source);
|
||||
g_print ("[%s] MOTION",
|
||||
clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
g_print ("[%s] BUTTON PRESS (click count:%i)",
|
||||
source, event->button.click_count);
|
||||
g_print ("[%s] BUTTON PRESS (button:%i, click count:%i)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_button (event),
|
||||
clutter_event_get_click_count (event));
|
||||
break;
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
g_print ("[%s] BUTTON RELEASE (click count:%i)",
|
||||
source, event->button.click_count);
|
||||
g_print ("[%s] BUTTON RELEASE (button:%i, click count:%i)",
|
||||
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);
|
||||
else if (clutter_event_get_source (event) == actor
|
||||
&& clutter_actor_get_parent (actor) == CLUTTER_ACTOR (stage))
|
||||
else if (source_actor == actor &&
|
||||
clutter_actor_get_parent (actor) == CLUTTER_ACTOR (stage))
|
||||
clutter_stage_set_key_focus (stage, actor);
|
||||
break;
|
||||
case CLUTTER_SCROLL:
|
||||
g_print ("[%s] BUTTON SCROLL (click count:%i)",
|
||||
source, event->button.click_count);
|
||||
g_print ("[%s] BUTTON SCROLL (direction:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_scroll_direction (event) == CLUTTER_SCROLL_UP
|
||||
? "up"
|
||||
: "down");
|
||||
break;
|
||||
case CLUTTER_STAGE_STATE:
|
||||
g_print ("[%s] STAGE STATE", source);
|
||||
g_print ("[%s] STAGE STATE", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
g_print ("[%s] DESTROY NOTIFY", source);
|
||||
g_print ("[%s] DESTROY NOTIFY", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
g_print ("[%s] CLIENT MESSAGE", source);
|
||||
g_print ("[%s] CLIENT MESSAGE", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_DELETE:
|
||||
g_print ("[%s] DELETE", source);
|
||||
g_print ("[%s] DELETE", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_NOTHING:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (clutter_event_get_source (event) == actor)
|
||||
if (source_actor == actor)
|
||||
g_print (" *source*");
|
||||
|
||||
g_print ("\n");
|
||||
@ -234,8 +268,8 @@ test_events_main (int argc, char *argv[])
|
||||
|
||||
|
||||
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, "fullscreen",
|
||||
G_CALLBACK (stage_state_cb), "fullscreen");
|
||||
g_signal_connect (stage, "unfullscreen",
|
||||
@ -244,24 +278,21 @@ test_events_main (int argc, char *argv[])
|
||||
G_CALLBACK (stage_state_cb), "activate");
|
||||
g_signal_connect (stage, "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);
|
||||
clutter_actor_set_name (focus_box, "Focus Box");
|
||||
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&rcol);
|
||||
clutter_actor_set_name (actor, "Red Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 100, 100);
|
||||
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "red box");
|
||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
|
||||
/* Toggle motion - enter/leave capture */
|
||||
g_signal_connect (actor, "button-press-event",
|
||||
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);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&gcol);
|
||||
clutter_actor_set_name (actor, "Green Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 250, 100);
|
||||
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "green box");
|
||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
|
||||
g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&bcol);
|
||||
clutter_actor_set_name (actor, "Blue Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 400, 100);
|
||||
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
||||
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
@ -299,20 +325,19 @@ test_events_main (int argc, char *argv[])
|
||||
|
||||
/* non reactive */
|
||||
actor = clutter_rectangle_new_with_color (&ncol);
|
||||
clutter_actor_set_name (actor, "Black Box");
|
||||
clutter_actor_set_size (actor, 400, 50);
|
||||
clutter_actor_set_position (actor, 100, 250);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
||||
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
|
||||
g_signal_connect (stage, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
|
||||
/* non reactive group, with reactive child */
|
||||
actor = clutter_rectangle_new_with_color (&ycol);
|
||||
clutter_actor_set_name (actor, "Yellow Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user