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-script-named-object
|
||||||
/tests/conform/test-actor-destruction
|
/tests/conform/test-actor-destruction
|
||||||
/tests/conform/test-color-operators
|
/tests/conform/test-color-operators
|
||||||
|
/tests/conform/test-cogl-texture-mipmaps
|
||||||
/tests/micro-bench/test-text-perf
|
/tests/micro-bench/test-text-perf
|
||||||
/tests/micro-bench/test-text
|
/tests/micro-bench/test-text
|
||||||
/tests/micro-bench/test-picking
|
/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)
|
Clutter 1.1.4 (03/01/2010)
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
||||||
|
103
README
103
README
@ -1,19 +1,25 @@
|
|||||||
Clutter - README
|
Clutter - README
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
||||||
Clutter is an open source software library for creating fast, visually
|
Clutter is an open source software library for creating portable, fast,
|
||||||
rich and animated graphical user interfaces.
|
visually rich and animated graphical user interfaces.
|
||||||
|
|
||||||
Clutter currently requires:
|
Clutter currently requires:
|
||||||
|
|
||||||
• GLib >= 2.16.0
|
• GLib >= 2.16.0
|
||||||
• Cairo >= 1.6
|
• Cairo >= 1.6
|
||||||
• PangoCairo >= 1.20
|
• 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
|
• GLX, SDL, WGL or an EGL Implementation
|
||||||
• JSON-GLib >= 0.8 (optional)
|
• JSON-GLib >= 0.8 (optional)
|
||||||
• GDK-Pixbuf >= 2.0 (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:
|
If you are building the API reference you will also need:
|
||||||
|
|
||||||
• GTK-Doc >= 1.11
|
• 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:
|
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:
|
UProf is available from:
|
||||||
http://www.clutter-project.org
|
|
||||||
|
|
||||||
The Clutter blog is at
|
git://git.moblin.org/uprof.git
|
||||||
http://www.clutter-project.org/blog
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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
|
clutter+subscribe@o-hand.com
|
||||||
|
|
||||||
The official mailing list archive is:
|
The official mailing list archive is:
|
||||||
|
|
||||||
http://lists.o-hand.com/clutter/
|
http://lists.o-hand.com/clutter/
|
||||||
|
|
||||||
New bug page on Bugzilla:
|
New bug page on Bugzilla:
|
||||||
|
|
||||||
http://bugzilla.o-hand.com/enter_bug.cgi?product=Clutter
|
http://bugzilla.o-hand.com/enter_bug.cgi?product=Clutter
|
||||||
|
|
||||||
Clutter is licensed under the terms of the GNU Lesser General Public
|
Clutter is licensed under the terms of the GNU Lesser General Public
|
||||||
License, version 2.1 or (at your option) later.
|
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]
|
--enable-debug=[no/minimum/yes]
|
||||||
Controls Clutter debugging level:
|
Controls Clutter debugging level:
|
||||||
@ -55,7 +84,7 @@ See the INSTALL file. Info on specific Clutter options;
|
|||||||
yes:
|
yes:
|
||||||
All GLib asserts, checks and support for runtime Clutter
|
All GLib asserts, checks and support for runtime Clutter
|
||||||
debugging notes through CLUTTER_DEBUG. This is the default
|
debugging notes through CLUTTER_DEBUG. This is the default
|
||||||
value for snapshots.
|
value for developers snapshots.
|
||||||
|
|
||||||
minimum:
|
minimum:
|
||||||
Just GType cast checks and support for runtime Clutter
|
Just GType cast checks and support for runtime Clutter
|
||||||
@ -65,26 +94,27 @@ See the INSTALL file. Info on specific Clutter options;
|
|||||||
no:
|
no:
|
||||||
No GLib asserts or checks and no support for runtime Clutter
|
No GLib asserts or checks and no support for runtime Clutter
|
||||||
debugging notes. Only use in extreme performance and/or size
|
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]
|
--enable-cogl-debug=[no/minimum/yes]
|
||||||
Controls COGL debugging level (default=minimum):
|
Controls COGL debugging level (default=minimum):
|
||||||
|
|
||||||
yes:
|
yes:
|
||||||
Support for COGL debugging notes through COGL_DEBUG and
|
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:
|
minimum:
|
||||||
Support for COGL debugging notes through COGL_DEBUG. This is
|
Support for COGL debugging notes through COGL_DEBUG. This is
|
||||||
the default for snapshots.
|
the default for developers snapshots.
|
||||||
|
|
||||||
no:
|
no:
|
||||||
Disable support for COGL runtime debugging notes. This is
|
Disable support for COGL runtime debugging notes. This is
|
||||||
the default for stable releases.
|
the default for stable releases.
|
||||||
|
|
||||||
--enable-maintainer-flags=[no/yes]
|
--enable-maintainer-flags=[no/yes]
|
||||||
Use strict compiler flags. This defaults to 'yes' for snapshots and
|
Use strict compiler flags. This defaults to 'yes' for developers
|
||||||
to 'no' for stable releases.
|
snapshots and to 'no' for stable releases.
|
||||||
|
|
||||||
--enable-gtk-doc
|
--enable-gtk-doc
|
||||||
use gtk-doc to build API documentation (default=no). Requires 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
|
Build additional documentation. Requires xsltproc for DocBook
|
||||||
conversion, and optionally jw for PDF generation.
|
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]
|
--with-flavour=[glx/eglx/eglnative/sdl/osx/win32/fruity]
|
||||||
Select the Clutter backend: (default=glx)
|
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
|
and if it is available, make Clutter depend on it
|
||||||
|
|
||||||
system:
|
system:
|
||||||
Only use the system copy of JSON-GLib
|
Only use the system copy of JSON-GLib and warn if not found
|
||||||
|
|
||||||
VERSIONING
|
VERSIONING
|
||||||
===============================================================================
|
===============================================================================
|
||||||
@ -167,22 +208,23 @@ the newly added API might still change.
|
|||||||
|
|
||||||
The micro version indicates the origin of the release: even micro
|
The micro version indicates the origin of the release: even micro
|
||||||
numbers are only used for released archives; odd micro numbers are
|
numbers are only used for released archives; odd micro numbers are
|
||||||
only used on the SVN repository.
|
only used on the Git repository.
|
||||||
|
|
||||||
HACKING
|
HACKING
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
||||||
If you want to hack on and improve Clutter, check the contained TODO
|
If you want to hack on and improve Clutter, check the contained TODO file for
|
||||||
file for pending tasks, the HACKING file for general implementation guidelines,
|
pending tasks, the HACKING file for general implementation guidelines, and the
|
||||||
HACKING.backends for backend-specific implementation issues. The CODING_STYLE
|
HACKING.backends for backend-specific implementation issues.
|
||||||
file contains the rules for writing code conformant to the style guidelines
|
|
||||||
used throughout Clutter. Remember: the coding style is mandatory; patches
|
The CODING_STYLE file contains the rules for writing code conformant to the
|
||||||
not conforming to it will be rejected.
|
style guidelines used throughout Clutter. Remember: the coding style is
|
||||||
|
mandatory; patches not conforming to it will be rejected.
|
||||||
|
|
||||||
BUGS
|
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
|
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;
|
• what system you're running Clutter on;
|
||||||
• which version of Clutter you are using;
|
• 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
|
• which video card and which drivers you are using, including output of
|
||||||
glxinfo and xdpyinfo (if applicable);
|
glxinfo and xdpyinfo (if applicable);
|
||||||
• how to reproduce the bug.
|
• how to reproduce the bug.
|
||||||
@ -235,7 +277,8 @@ RELEASE NOTES
|
|||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
||||||
Relevant information for developers with existing Clutter applications
|
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
|
Release Notes for Clutter 1.2
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -342,7 +385,7 @@ Release Notes for Clutter 1.0
|
|||||||
correct HLS intervals:
|
correct HLS intervals:
|
||||||
|
|
||||||
Hue: [ 0, 360 )
|
Hue: [ 0, 360 )
|
||||||
Luminance: [ 0, 1]
|
Luminance: [ 0, 1 ]
|
||||||
Saturation: [ 0, 1 ]
|
Saturation: [ 0, 1 ]
|
||||||
|
|
||||||
* The ClutterFixed symbols have been completely removed: fixed-point
|
* The ClutterFixed symbols have been completely removed: fixed-point
|
||||||
@ -852,5 +895,3 @@ Release Notes for Clutter 0.3
|
|||||||
ClutterGroup::remove signals have been deprecated:
|
ClutterGroup::remove signals have been deprecated:
|
||||||
ClutterContainer::actor-added and ClutterContainer::actor-removed should
|
ClutterContainer::actor-added and ClutterContainer::actor-removed should
|
||||||
be used instead.
|
be used instead.
|
||||||
|
|
||||||
$LastChangedDate$
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
SUBDIRS = autotools
|
SUBDIRS = autotools mingw
|
||||||
|
|
||||||
EXTRA_DIST = gen-gcov.pl
|
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 =
|
EXTRA_DIST =
|
||||||
BUILT_SOURCES =
|
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 = \
|
INCLUDES = \
|
||||||
-I$(top_srcdir) \
|
-I$(top_srcdir) \
|
||||||
-I$(top_srcdir)/clutter/cogl \
|
-I$(top_srcdir)/clutter/cogl \
|
||||||
@ -67,6 +84,7 @@ source_h = \
|
|||||||
$(srcdir)/clutter-color.h \
|
$(srcdir)/clutter-color.h \
|
||||||
$(srcdir)/clutter-container.h \
|
$(srcdir)/clutter-container.h \
|
||||||
$(srcdir)/clutter-deprecated.h \
|
$(srcdir)/clutter-deprecated.h \
|
||||||
|
$(srcdir)/clutter-device-manager.h \
|
||||||
$(srcdir)/clutter-event.h \
|
$(srcdir)/clutter-event.h \
|
||||||
$(srcdir)/clutter-feature.h \
|
$(srcdir)/clutter-feature.h \
|
||||||
$(srcdir)/clutter-fixed.h \
|
$(srcdir)/clutter-fixed.h \
|
||||||
@ -74,6 +92,7 @@ source_h = \
|
|||||||
$(srcdir)/clutter-flow-layout.h \
|
$(srcdir)/clutter-flow-layout.h \
|
||||||
$(srcdir)/clutter-frame-source.h \
|
$(srcdir)/clutter-frame-source.h \
|
||||||
$(srcdir)/clutter-group.h \
|
$(srcdir)/clutter-group.h \
|
||||||
|
$(srcdir)/clutter-input-device.h \
|
||||||
$(srcdir)/clutter-interval.h \
|
$(srcdir)/clutter-interval.h \
|
||||||
$(srcdir)/clutter-keysyms.h \
|
$(srcdir)/clutter-keysyms.h \
|
||||||
$(srcdir)/clutter-layout-manager.h \
|
$(srcdir)/clutter-layout-manager.h \
|
||||||
@ -137,6 +156,7 @@ source_c = \
|
|||||||
$(srcdir)/clutter-clone.c \
|
$(srcdir)/clutter-clone.c \
|
||||||
$(srcdir)/clutter-color.c \
|
$(srcdir)/clutter-color.c \
|
||||||
$(srcdir)/clutter-container.c \
|
$(srcdir)/clutter-container.c \
|
||||||
|
$(srcdir)/clutter-device-manager.c \
|
||||||
clutter-enum-types.c \
|
clutter-enum-types.c \
|
||||||
$(srcdir)/clutter-event.c \
|
$(srcdir)/clutter-event.c \
|
||||||
$(srcdir)/clutter-feature.c \
|
$(srcdir)/clutter-feature.c \
|
||||||
@ -145,6 +165,7 @@ source_c = \
|
|||||||
$(srcdir)/clutter-flow-layout.c \
|
$(srcdir)/clutter-flow-layout.c \
|
||||||
$(srcdir)/clutter-frame-source.c \
|
$(srcdir)/clutter-frame-source.c \
|
||||||
$(srcdir)/clutter-group.c \
|
$(srcdir)/clutter-group.c \
|
||||||
|
$(srcdir)/clutter-input-device.c \
|
||||||
$(srcdir)/clutter-interval.c \
|
$(srcdir)/clutter-interval.c \
|
||||||
$(srcdir)/clutter-layout-manager.c \
|
$(srcdir)/clutter-layout-manager.c \
|
||||||
$(srcdir)/clutter-layout-meta.c \
|
$(srcdir)/clutter-layout-meta.c \
|
||||||
@ -205,7 +226,8 @@ libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_DEPENDENCIES = \
|
|||||||
$(top_builddir)/clutter/cogl/pango/libcoglpango.la \
|
$(top_builddir)/clutter/cogl/pango/libcoglpango.la \
|
||||||
$(top_builddir)/clutter/$(CLUTTER_WINSYS)/libclutter-$(CLUTTER_WINSYS).la \
|
$(top_builddir)/clutter/$(CLUTTER_WINSYS)/libclutter-$(CLUTTER_WINSYS).la \
|
||||||
$(clutter_json_dep) \
|
$(clutter_json_dep) \
|
||||||
$(CLUTTER_WINSYS_BASE_LIB)
|
$(CLUTTER_WINSYS_BASE_LIB) \
|
||||||
|
$(win32_resources)
|
||||||
|
|
||||||
libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_SOURCES = \
|
libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_SOURCES = \
|
||||||
$(source_c) \
|
$(source_c) \
|
||||||
@ -219,6 +241,7 @@ libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_LDFLAGS = \
|
|||||||
-export-dynamic \
|
-export-dynamic \
|
||||||
-export-symbols-regex "^(clutter|cogl|json).*" \
|
-export-symbols-regex "^(clutter|cogl|json).*" \
|
||||||
-rpath $(libdir) \
|
-rpath $(libdir) \
|
||||||
|
$(win32_resources_ldflag) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
lib_LTLIBRARIES = $(CLUTTER_WINSYS_LIB)
|
lib_LTLIBRARIES = $(CLUTTER_WINSYS_LIB)
|
||||||
|
@ -308,6 +308,7 @@ struct _ClutterActorPrivate
|
|||||||
guint clip_to_allocation : 1;
|
guint clip_to_allocation : 1;
|
||||||
guint enable_model_view_transform : 1;
|
guint enable_model_view_transform : 1;
|
||||||
guint enable_paint_unmapped : 1;
|
guint enable_paint_unmapped : 1;
|
||||||
|
guint has_pointer : 1;
|
||||||
|
|
||||||
gfloat clip[4];
|
gfloat clip[4];
|
||||||
|
|
||||||
@ -429,7 +430,8 @@ enum
|
|||||||
|
|
||||||
PROP_SHOW_ON_SET_PARENT,
|
PROP_SHOW_ON_SET_PARENT,
|
||||||
|
|
||||||
PROP_TEXT_DIRECTION
|
PROP_TEXT_DIRECTION,
|
||||||
|
PROP_HAS_POINTER
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -2581,7 +2583,7 @@ clutter_actor_set_property (GObject *object,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_OPACITY:
|
case PROP_OPACITY:
|
||||||
clutter_actor_set_opacity (actor, g_value_get_uchar (value));
|
clutter_actor_set_opacity (actor, g_value_get_uint (value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_NAME:
|
case PROP_NAME:
|
||||||
@ -2864,7 +2866,7 @@ clutter_actor_get_property (GObject *object,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_OPACITY:
|
case PROP_OPACITY:
|
||||||
g_value_set_uchar (value, priv->opacity);
|
g_value_set_uint (value, priv->opacity);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_NAME:
|
case PROP_NAME:
|
||||||
@ -3031,6 +3033,10 @@ clutter_actor_get_property (GObject *object,
|
|||||||
g_value_set_enum (value, priv->text_direction);
|
g_value_set_enum (value, priv->text_direction);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_HAS_POINTER:
|
||||||
|
g_value_set_boolean (value, priv->has_pointer);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -3462,12 +3468,12 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||||||
/**
|
/**
|
||||||
* ClutterActor:opacity:
|
* ClutterActor:opacity:
|
||||||
*
|
*
|
||||||
* Opacity of the actor, between 0 (fully transparent) and
|
* Opacity of an actor, between 0 (fully transparent) and
|
||||||
* 255 (fully opaque)
|
* 255 (fully opaque)
|
||||||
*/
|
*/
|
||||||
pspec = g_param_spec_uchar ("opacity",
|
pspec = g_param_spec_uint ("opacity",
|
||||||
"Opacity",
|
"Opacity",
|
||||||
"Opacity of actor",
|
"Opacity of an actor",
|
||||||
0, 255,
|
0, 255,
|
||||||
255,
|
255,
|
||||||
CLUTTER_PARAM_READWRITE);
|
CLUTTER_PARAM_READWRITE);
|
||||||
@ -3858,6 +3864,24 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||||||
PROP_TEXT_DIRECTION,
|
PROP_TEXT_DIRECTION,
|
||||||
pspec);
|
pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterActor:has-pointer:
|
||||||
|
*
|
||||||
|
* Whether the actor contains the pointer of a #ClutterInputDevice
|
||||||
|
* or not.
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_boolean ("has-pointer",
|
||||||
|
"Has Pointer",
|
||||||
|
"Whether the actor contains the pointer "
|
||||||
|
"of an input device",
|
||||||
|
FALSE,
|
||||||
|
CLUTTER_PARAM_READABLE);
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_HAS_POINTER,
|
||||||
|
pspec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterActor::destroy:
|
* ClutterActor::destroy:
|
||||||
* @actor: the object which received the signal
|
* @actor: the object which received the signal
|
||||||
@ -9638,6 +9662,20 @@ clutter_actor_set_text_direction (ClutterActor *self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_actor_set_has_pointer (ClutterActor *self,
|
||||||
|
gboolean has_pointer)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->has_pointer != has_pointer)
|
||||||
|
{
|
||||||
|
priv->has_pointer = has_pointer;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (self), "has-pointer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_actor_get_text_direction:
|
* clutter_actor_get_text_direction:
|
||||||
* @self: a #ClutterActor
|
* @self: a #ClutterActor
|
||||||
@ -9748,3 +9786,23 @@ clutter_actor_pop_internal (void)
|
|||||||
|
|
||||||
ctx->internal_child -= 1;
|
ctx->internal_child -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_actor_has_pointer:
|
||||||
|
* @self: a #ClutterActor
|
||||||
|
*
|
||||||
|
* Checks whether an actor contains the the pointer of a
|
||||||
|
* #ClutterInputDevice
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the actor contains the pointer, and
|
||||||
|
* %FALSE otherwise
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
clutter_actor_has_pointer (ClutterActor *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||||
|
|
||||||
|
return self->priv->has_pointer;
|
||||||
|
}
|
||||||
|
@ -532,6 +532,7 @@ void clutter_actor_get_transformation_matrix (ClutterActor *self
|
|||||||
CoglMatrix *matrix);
|
CoglMatrix *matrix);
|
||||||
|
|
||||||
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
|
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
|
||||||
|
gboolean clutter_actor_has_pointer (ClutterActor *self);
|
||||||
|
|
||||||
void clutter_actor_set_text_direction (ClutterActor *self,
|
void clutter_actor_set_text_direction (ClutterActor *self,
|
||||||
ClutterTextDirection text_dir);
|
ClutterTextDirection text_dir);
|
||||||
|
@ -201,7 +201,10 @@ on_actor_dispose (gpointer user_data,
|
|||||||
ClutterAnimation *self = user_data;
|
ClutterAnimation *self = user_data;
|
||||||
|
|
||||||
if (self->priv->object == actor_pointer)
|
if (self->priv->object == actor_pointer)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (ANIMATION, "Object [%p] was unref'd", actor_pointer);
|
||||||
g_object_unref (self);
|
g_object_unref (self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -219,6 +222,7 @@ clutter_animation_real_completed (ClutterAnimation *self)
|
|||||||
direction = clutter_timeline_get_direction (timeline);
|
direction = clutter_timeline_get_direction (timeline);
|
||||||
|
|
||||||
/* explicitly set the final state of the animation */
|
/* 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);
|
g_hash_table_iter_init (&iter, priv->properties);
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
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);
|
animation = g_object_get_qdata (priv->object, quark_object_animation);
|
||||||
if (animation == self)
|
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_set_qdata (priv->object, quark_object_animation, NULL);
|
||||||
g_object_weak_unref (priv->object, on_actor_dispose, self);
|
g_object_weak_unref (priv->object, on_actor_dispose, self);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (ANIMATION, "Releasing the reference Animation [%p]",
|
||||||
|
animation);
|
||||||
g_object_unref (animation);
|
g_object_unref (animation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,7 +266,9 @@ clutter_animation_finalize (GObject *gobject)
|
|||||||
{
|
{
|
||||||
ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
|
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_hash_table_destroy (priv->properties);
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_animation_parent_class)->finalize (gobject);
|
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;
|
gobject_class->finalize = clutter_animation_finalize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterAnimation:objct:
|
* ClutterAnimation:object:
|
||||||
*
|
*
|
||||||
* The #GObject to which the animation applies.
|
* The #GObject to which the animation applies.
|
||||||
*
|
*
|
||||||
@ -629,6 +641,7 @@ clutter_animation_validate_bind (ClutterAnimation *animation,
|
|||||||
ClutterAnimationPrivate *priv;
|
ClutterAnimationPrivate *priv;
|
||||||
GObjectClass *klass;
|
GObjectClass *klass;
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
|
GType pspec_type;
|
||||||
|
|
||||||
priv = animation->priv;
|
priv = animation->priv;
|
||||||
|
|
||||||
@ -667,14 +680,17 @@ clutter_animation_validate_bind (ClutterAnimation *animation,
|
|||||||
return NULL;
|
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 "
|
g_warning ("Cannot bind property '%s': the interval value of "
|
||||||
"type '%s' is not compatible with the property value "
|
"type '%s' is not compatible with the property value "
|
||||||
"of type '%s'",
|
"of type '%s'",
|
||||||
property_name,
|
property_name,
|
||||||
g_type_name (argtype),
|
g_type_name (argtype),
|
||||||
g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
g_type_name (pspec_type));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,6 +862,7 @@ clutter_animation_update_interval (ClutterAnimation *animation,
|
|||||||
ClutterAnimationPrivate *priv;
|
ClutterAnimationPrivate *priv;
|
||||||
GObjectClass *klass;
|
GObjectClass *klass;
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
|
GType pspec_type, int_type;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||||
g_return_if_fail (property_name != NULL);
|
g_return_if_fail (property_name != NULL);
|
||||||
@ -872,15 +889,18 @@ clutter_animation_update_interval (ClutterAnimation *animation,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_value_type_compatible (G_PARAM_SPEC_VALUE_TYPE (pspec),
|
pspec_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
||||||
clutter_interval_get_value_type (interval)))
|
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 "
|
g_warning ("Cannot update property '%s': the interval value of "
|
||||||
"type '%s' is not compatible with the property value "
|
"type '%s' is not compatible with the property value "
|
||||||
"of type '%s'",
|
"of type '%s'",
|
||||||
property_name,
|
property_name,
|
||||||
g_type_name (clutter_interval_get_value_type (interval)),
|
g_type_name (int_type),
|
||||||
g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
g_type_name (pspec_type));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -906,6 +926,7 @@ clutter_animation_update (ClutterAnimation *animation,
|
|||||||
{
|
{
|
||||||
ClutterAnimationPrivate *priv;
|
ClutterAnimationPrivate *priv;
|
||||||
ClutterInterval *interval;
|
ClutterInterval *interval;
|
||||||
|
GType int_type;
|
||||||
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
|
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
|
||||||
g_return_val_if_fail (property_name != NULL, NULL);
|
g_return_val_if_fail (property_name != NULL, NULL);
|
||||||
@ -923,14 +944,16 @@ clutter_animation_update (ClutterAnimation *animation,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_value_type_compatible (G_VALUE_TYPE (final),
|
int_type = clutter_interval_get_value_type (interval);
|
||||||
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 "
|
g_warning ("Cannot update property '%s': the interval value of "
|
||||||
"type '%s' is not compatible with the property value "
|
"type '%s' is not compatible with the property value "
|
||||||
"of type '%s'",
|
"of type '%s'",
|
||||||
property_name,
|
property_name,
|
||||||
g_type_name (clutter_interval_get_value_type (interval)),
|
g_type_name (int_type),
|
||||||
g_type_name (G_VALUE_TYPE (final)));
|
g_type_name (G_VALUE_TYPE (final)));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1221,6 +1244,8 @@ clutter_animation_set_mode (ClutterAnimation *animation,
|
|||||||
g_object_freeze_notify (G_OBJECT (animation));
|
g_object_freeze_notify (G_OBJECT (animation));
|
||||||
|
|
||||||
alpha = clutter_animation_get_alpha_internal (animation);
|
alpha = clutter_animation_get_alpha_internal (animation);
|
||||||
|
g_assert (CLUTTER_IS_ALPHA (alpha));
|
||||||
|
|
||||||
clutter_alpha_set_mode (alpha, mode);
|
clutter_alpha_set_mode (alpha, mode);
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (animation), "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));
|
g_object_freeze_notify (G_OBJECT (animation));
|
||||||
|
|
||||||
timeline = clutter_animation_get_timeline_internal (animation);
|
timeline = clutter_animation_get_timeline_internal (animation);
|
||||||
|
g_assert (CLUTTER_IS_TIMELINE (timeline));
|
||||||
|
|
||||||
clutter_timeline_set_duration (timeline, msecs);
|
clutter_timeline_set_duration (timeline, msecs);
|
||||||
clutter_timeline_rewind (timeline);
|
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_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (&real_value)))
|
||||||
{
|
{
|
||||||
if (!g_value_type_compatible (G_VALUE_TYPE (value),
|
/* are these two types compatible (can be directly copied)? */
|
||||||
G_VALUE_TYPE (&real_value)) &&
|
if (g_value_type_compatible (G_VALUE_TYPE (value),
|
||||||
!g_value_type_compatible (G_VALUE_TYPE (&real_value),
|
G_VALUE_TYPE (&real_value)))
|
||||||
G_VALUE_TYPE (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 "
|
g_warning ("%s: Unable to convert from %s to %s for "
|
||||||
"the property '%s' of object %s",
|
"the property '%s' of object %s",
|
||||||
G_STRLOC,
|
G_STRLOC,
|
||||||
@ -1649,20 +1688,10 @@ clutter_animation_setup_property (ClutterAnimation *animation,
|
|||||||
g_value_unset (&real_value);
|
g_value_unset (&real_value);
|
||||||
return;
|
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
|
else
|
||||||
g_value_copy (value, &real_value);
|
g_value_copy (value, &real_value);
|
||||||
|
|
||||||
|
done:
|
||||||
/* create an interval and bind it to the property, in case
|
/* create an interval and bind it to the property, in case
|
||||||
* it's not a fixed property, otherwise just set it
|
* 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;
|
return context->current_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_input_device_get_device_type:
|
|
||||||
* @device: a #ClutterInputDevice
|
|
||||||
*
|
|
||||||
* Retrieves the type of @device
|
|
||||||
*
|
|
||||||
* Return value: the type of the device
|
|
||||||
*
|
|
||||||
* Since: 1.0
|
|
||||||
*/
|
|
||||||
ClutterInputDeviceType
|
|
||||||
clutter_input_device_get_device_type (ClutterInputDevice *device)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (device != NULL, CLUTTER_POINTER_DEVICE);
|
|
||||||
|
|
||||||
return device->device_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_input_device_get_device_id:
|
|
||||||
* @device: a #ClutterInputDevice
|
|
||||||
*
|
|
||||||
* Retrieves the unique identifier of @device
|
|
||||||
*
|
|
||||||
* Return value: the identifier of the device
|
|
||||||
*
|
|
||||||
* Since: 1.0
|
|
||||||
*/
|
|
||||||
gint
|
|
||||||
clutter_input_device_get_device_id (ClutterInputDevice *device)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (device != NULL, -1);
|
|
||||||
|
|
||||||
return device->id;
|
|
||||||
}
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#define __CLUTTER_EVENT_H__
|
#define __CLUTTER_EVENT_H__
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-input-device.h>
|
||||||
#include <clutter/clutter-types.h>
|
#include <clutter/clutter-types.h>
|
||||||
|
|
||||||
#define CLUTTER_TYPE_EVENT (clutter_event_get_type ())
|
#define CLUTTER_TYPE_EVENT (clutter_event_get_type ())
|
||||||
@ -201,37 +202,6 @@ typedef struct _ClutterScrollEvent ClutterScrollEvent;
|
|||||||
typedef struct _ClutterStageStateEvent ClutterStageStateEvent;
|
typedef struct _ClutterStageStateEvent ClutterStageStateEvent;
|
||||||
typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
|
typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
|
||||||
|
|
||||||
/**
|
|
||||||
* ClutterInputDevice:
|
|
||||||
*
|
|
||||||
* Generic representation of an input device. The
|
|
||||||
* actual contents of this structure depend on the
|
|
||||||
* backend used.
|
|
||||||
*/
|
|
||||||
typedef struct _ClutterInputDevice ClutterInputDevice;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ClutterInputDeviceType:
|
|
||||||
* @CLUTTER_POINTER_DEVICE: A pointer device
|
|
||||||
* @CLUTTER_KEYBOARD_DEVICE: A keyboard device
|
|
||||||
* @CLUTTER_EXTENSION_DEVICE: A generic extension device
|
|
||||||
* @CLUTTER_N_DEVICE_TYPES: The number of device types
|
|
||||||
*
|
|
||||||
* The types of input devices available.
|
|
||||||
*
|
|
||||||
* The #ClutterInputDeviceType enumeration can be extended at later
|
|
||||||
* date; not every platform supports every input device type.
|
|
||||||
*
|
|
||||||
* Since: 1.0
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
CLUTTER_POINTER_DEVICE,
|
|
||||||
CLUTTER_KEYBOARD_DEVICE,
|
|
||||||
CLUTTER_EXTENSION_DEVICE,
|
|
||||||
|
|
||||||
CLUTTER_N_DEVICE_TYPES
|
|
||||||
} ClutterInputDeviceType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterAnyEvent:
|
* ClutterAnyEvent:
|
||||||
* @type: event type
|
* @type: event type
|
||||||
@ -509,9 +479,6 @@ guint32 clutter_keysym_to_unicode (guint k
|
|||||||
guint32 clutter_get_current_event_time (void);
|
guint32 clutter_get_current_event_time (void);
|
||||||
G_CONST_RETURN ClutterEvent *clutter_get_current_event (void);
|
G_CONST_RETURN ClutterEvent *clutter_get_current_event (void);
|
||||||
|
|
||||||
ClutterInputDeviceType clutter_input_device_get_device_type (ClutterInputDevice *device);
|
|
||||||
gint clutter_input_device_get_device_id (ClutterInputDevice *device);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_EVENT_H__ */
|
#endif /* __CLUTTER_EVENT_H__ */
|
||||||
|
@ -25,9 +25,16 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:clutter-feature
|
* 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
|
#ifdef HAVE_CONFIG_H
|
||||||
|
@ -25,14 +25,6 @@
|
|||||||
#error "Only <clutter/clutter.h> can be included directly."
|
#error "Only <clutter/clutter.h> can be included directly."
|
||||||
#endif
|
#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__
|
#ifndef __CLUTTER_FEATURE_H__
|
||||||
#define __CLUTTER_FEATURE_H__
|
#define __CLUTTER_FEATURE_H__
|
||||||
|
|
||||||
|
@ -39,24 +39,25 @@ struct _ClutterFrameSource
|
|||||||
ClutterTimeoutInterval timeout;
|
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_check (GSource *source);
|
||||||
static gboolean clutter_frame_source_dispatch (GSource *source,
|
static gboolean clutter_frame_source_dispatch (GSource *source,
|
||||||
GSourceFunc callback,
|
GSourceFunc callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
static GSourceFuncs clutter_frame_source_funcs =
|
static GSourceFuncs clutter_frame_source_funcs =
|
||||||
{
|
{
|
||||||
clutter_frame_source_prepare,
|
clutter_frame_source_prepare,
|
||||||
clutter_frame_source_check,
|
clutter_frame_source_check,
|
||||||
clutter_frame_source_dispatch,
|
clutter_frame_source_dispatch,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_frame_source_add_full:
|
* clutter_frame_source_add_full:
|
||||||
* @priority: the priority of the frame source. Typically this will be in the
|
* @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
|
* @fps: the number of times per second to call the function
|
||||||
* @func: function to call
|
* @func: function to call
|
||||||
* @data: data to pass to the function
|
* @data: data to pass to the function
|
||||||
@ -131,7 +132,8 @@ clutter_frame_source_add (guint fps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
clutter_frame_source_prepare (GSource *source, gint *delay)
|
clutter_frame_source_prepare (GSource *source,
|
||||||
|
gint *delay)
|
||||||
{
|
{
|
||||||
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
|
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
|
||||||
GTimeVal current_time;
|
GTimeVal current_time;
|
||||||
|
@ -277,10 +277,12 @@ clutter_group_real_foreach (ClutterContainer *container,
|
|||||||
{
|
{
|
||||||
ClutterGroup *group = CLUTTER_GROUP (container);
|
ClutterGroup *group = CLUTTER_GROUP (container);
|
||||||
ClutterGroupPrivate *priv = group->priv;
|
ClutterGroupPrivate *priv = group->priv;
|
||||||
GList *l;
|
|
||||||
|
|
||||||
for (l = priv->children; l; l = l->next)
|
/* Using g_list_foreach instead of iterating the list manually
|
||||||
(* callback) (CLUTTER_ACTOR (l->data), user_data);
|
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
|
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,69 +2045,93 @@ event_click_count_generate (ClutterEvent *event)
|
|||||||
static guint32 previous_time = 0;
|
static guint32 previous_time = 0;
|
||||||
static gint previous_button_number = -1;
|
static gint previous_button_number = -1;
|
||||||
|
|
||||||
|
ClutterInputDevice *device = NULL;
|
||||||
ClutterBackend *backend;
|
ClutterBackend *backend;
|
||||||
guint double_click_time;
|
guint double_click_time;
|
||||||
guint double_click_distance;
|
guint double_click_distance;
|
||||||
|
|
||||||
backend = _clutter_context_get_default ()->backend;
|
backend = clutter_get_default_backend ();
|
||||||
double_click_distance = clutter_backend_get_double_click_distance (backend);
|
double_click_distance = clutter_backend_get_double_click_distance (backend);
|
||||||
double_click_time = clutter_backend_get_double_click_time (backend);
|
double_click_time = clutter_backend_get_double_click_time (backend);
|
||||||
|
|
||||||
if (event->button.device != NULL)
|
device = clutter_event_get_device (event);
|
||||||
|
if (device != NULL)
|
||||||
{
|
{
|
||||||
click_count = event->button.device->click_count;
|
click_count = device->click_count;
|
||||||
previous_x = event->button.device->previous_x;
|
previous_x = device->previous_x;
|
||||||
previous_y = event->button.device->previous_y;
|
previous_y = device->previous_y;
|
||||||
previous_time = event->button.device->previous_time;
|
previous_time = device->previous_time;
|
||||||
previous_button_number = event->button.device->previous_button_number;
|
previous_button_number = device->previous_button_number;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"Restoring previous click count:%d (device:%d, time:%u)",
|
||||||
|
click_count,
|
||||||
|
clutter_input_device_get_device_id (device),
|
||||||
|
previous_time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"Restoring previous click count:%d (time:%u)",
|
||||||
|
click_count,
|
||||||
|
previous_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event->type)
|
switch (clutter_event_type (event))
|
||||||
{
|
{
|
||||||
case CLUTTER_BUTTON_PRESS:
|
case CLUTTER_BUTTON_PRESS:
|
||||||
case CLUTTER_SCROLL:
|
|
||||||
/* check if we are in time and within distance to increment an
|
/* check if we are in time and within distance to increment an
|
||||||
* existing click count
|
* existing click count
|
||||||
*/
|
*/
|
||||||
if (event->button.time < previous_time + double_click_time &&
|
if (event->button.button == previous_button_number &&
|
||||||
|
event->button.time < (previous_time + double_click_time) &&
|
||||||
(ABS (event->button.x - previous_x) <= double_click_distance) &&
|
(ABS (event->button.x - previous_x) <= double_click_distance) &&
|
||||||
(ABS (event->button.y - previous_y) <= double_click_distance)
|
(ABS (event->button.y - previous_y) <= double_click_distance))
|
||||||
&& event->button.button == previous_button_number)
|
|
||||||
{
|
{
|
||||||
click_count ++;
|
CLUTTER_NOTE (EVENT, "Increase click count (button: %d, time: %u)",
|
||||||
|
event->button.button,
|
||||||
|
event->button.time);
|
||||||
|
|
||||||
|
click_count += 1;
|
||||||
}
|
}
|
||||||
else /* start a new click count*/
|
else /* start a new click count*/
|
||||||
{
|
{
|
||||||
click_count=1;
|
CLUTTER_NOTE (EVENT, "Reset click count (button: %d, time: %u)",
|
||||||
|
event->button.button,
|
||||||
|
event->button.time);
|
||||||
|
|
||||||
|
click_count = 1;
|
||||||
previous_button_number = event->button.button;
|
previous_button_number = event->button.button;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store time and position for this click for comparison with
|
|
||||||
* next event
|
|
||||||
*/
|
|
||||||
previous_time = event->button.time;
|
|
||||||
previous_x = event->button.x;
|
previous_x = event->button.x;
|
||||||
previous_y = event->button.y;
|
previous_y = event->button.y;
|
||||||
|
previous_time = event->button.time;
|
||||||
|
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case CLUTTER_BUTTON_RELEASE:
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
event->button.click_count=click_count;
|
event->button.click_count = click_count;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert (NULL);
|
g_assert (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->button.device != NULL)
|
if (event->type == CLUTTER_BUTTON_PRESS && device != NULL)
|
||||||
{
|
{
|
||||||
event->button.device->click_count = click_count;
|
CLUTTER_NOTE (EVENT, "Storing click count: %d (device:%d, time:%u)",
|
||||||
event->button.device->previous_x = previous_x;
|
click_count,
|
||||||
event->button.device->previous_y = previous_y;
|
clutter_input_device_get_device_id (device),
|
||||||
event->button.device->previous_time = previous_time;
|
previous_time);
|
||||||
event->button.device->previous_button_number = previous_button_number;
|
|
||||||
|
device->click_count = click_count;
|
||||||
|
device->previous_x = previous_x;
|
||||||
|
device->previous_y = previous_y;
|
||||||
|
device->previous_time = previous_time;
|
||||||
|
device->previous_button_number = previous_button_number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
emit_event (ClutterEvent *event,
|
emit_event (ClutterEvent *event,
|
||||||
gboolean is_key_event)
|
gboolean is_key_event)
|
||||||
@ -2118,7 +2142,7 @@ emit_event (ClutterEvent *event,
|
|||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
gint i = 0;
|
gint i = 0;
|
||||||
|
|
||||||
if (!event->any.source)
|
if (event->any.source == NULL)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (EVENT, "No source set, discarding event");
|
CLUTTER_NOTE (EVENT, "No source set, discarding event");
|
||||||
return;
|
return;
|
||||||
@ -2182,136 +2206,38 @@ static inline void
|
|||||||
emit_pointer_event (ClutterEvent *event,
|
emit_pointer_event (ClutterEvent *event,
|
||||||
ClutterInputDevice *device)
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
/* Using the global variable directly, since it has to be initialized
|
ClutterMainContext *context = _clutter_context_get_default ();
|
||||||
* at this point
|
|
||||||
*/
|
|
||||||
ClutterMainContext *context = ClutterCntx;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (context->pointer_grab_actor != NULL &&
|
if (context->pointer_grab_actor == NULL &&
|
||||||
device == NULL))
|
(device == NULL || device->pointer_grab_actor == NULL))
|
||||||
|
{
|
||||||
|
/* no grab, time to capture and bubble */
|
||||||
|
emit_event (event, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (context->pointer_grab_actor != NULL)
|
||||||
{
|
{
|
||||||
/* global grab */
|
/* global grab */
|
||||||
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
|
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
|
||||||
}
|
}
|
||||||
else if (G_UNLIKELY (device != NULL &&
|
else if (device != NULL && device->pointer_grab_actor != NULL)
|
||||||
device->pointer_grab_actor != NULL))
|
|
||||||
{
|
{
|
||||||
/* per device grab */
|
/* per device grab */
|
||||||
clutter_actor_event (device->pointer_grab_actor, event, FALSE);
|
clutter_actor_event (device->pointer_grab_actor, event, FALSE);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* no grab, time to capture and bubble */
|
|
||||||
emit_event (event, FALSE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
emit_keyboard_event (ClutterEvent *event)
|
emit_keyboard_event (ClutterEvent *event)
|
||||||
{
|
{
|
||||||
ClutterMainContext *context = ClutterCntx;
|
ClutterMainContext *context = _clutter_context_get_default ();
|
||||||
|
|
||||||
if (G_UNLIKELY (context->keyboard_grab_actor != NULL))
|
if (context->keyboard_grab_actor == NULL)
|
||||||
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
|
||||||
else
|
|
||||||
emit_event (event, TRUE);
|
emit_event (event, TRUE);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
unset_motion_last_actor (ClutterActor *actor, ClutterInputDevice *dev)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = ClutterCntx;
|
|
||||||
|
|
||||||
if (dev == NULL)
|
|
||||||
context->motion_last_actor = NULL;
|
|
||||||
else
|
else
|
||||||
dev->motion_last_actor = NULL;
|
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_motion_last_actor (ClutterActor *motion_current_actor,
|
|
||||||
ClutterInputDevice *device)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = ClutterCntx;
|
|
||||||
ClutterActor *last_actor = context->motion_last_actor;
|
|
||||||
|
|
||||||
if (device != NULL)
|
|
||||||
last_actor = device->motion_last_actor;
|
|
||||||
|
|
||||||
if (last_actor && last_actor != motion_current_actor)
|
|
||||||
{
|
|
||||||
g_signal_handlers_disconnect_by_func
|
|
||||||
(last_actor,
|
|
||||||
G_CALLBACK (unset_motion_last_actor),
|
|
||||||
device);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (motion_current_actor && last_actor != motion_current_actor)
|
|
||||||
{
|
|
||||||
g_signal_connect (motion_current_actor, "destroy",
|
|
||||||
G_CALLBACK (unset_motion_last_actor),
|
|
||||||
device);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device != NULL)
|
|
||||||
device->motion_last_actor = motion_current_actor;
|
|
||||||
else
|
|
||||||
context->motion_last_actor = motion_current_actor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
generate_enter_leave_events (ClutterEvent *event)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = ClutterCntx;
|
|
||||||
ClutterActor *motion_current_actor = event->motion.source;
|
|
||||||
ClutterActor *last_actor = context->motion_last_actor;
|
|
||||||
ClutterInputDevice *device = clutter_event_get_device (event);
|
|
||||||
|
|
||||||
if (device != NULL)
|
|
||||||
last_actor = device->motion_last_actor;
|
|
||||||
|
|
||||||
if (last_actor != motion_current_actor)
|
|
||||||
{
|
|
||||||
if (motion_current_actor)
|
|
||||||
{
|
|
||||||
ClutterEvent cev;
|
|
||||||
gfloat x, y;
|
|
||||||
|
|
||||||
cev.crossing.device = device;
|
|
||||||
clutter_event_get_coords (event, &x, &y);
|
|
||||||
|
|
||||||
if (context->motion_last_actor)
|
|
||||||
{
|
|
||||||
cev.crossing.type = CLUTTER_LEAVE;
|
|
||||||
cev.crossing.time = event->any.time;
|
|
||||||
cev.crossing.flags = 0;
|
|
||||||
cev.crossing.x = x;
|
|
||||||
cev.crossing.y = y;
|
|
||||||
cev.crossing.source = last_actor;
|
|
||||||
cev.crossing.stage = event->any.stage;
|
|
||||||
cev.crossing.related = motion_current_actor;
|
|
||||||
|
|
||||||
emit_pointer_event (&cev, device);
|
|
||||||
}
|
|
||||||
|
|
||||||
cev.crossing.type = CLUTTER_ENTER;
|
|
||||||
cev.crossing.time = event->any.time;
|
|
||||||
cev.crossing.flags = 0;
|
|
||||||
cev.crossing.x = x;
|
|
||||||
cev.crossing.y = y;
|
|
||||||
cev.crossing.source = motion_current_actor;
|
|
||||||
cev.crossing.stage = event->any.stage;
|
|
||||||
|
|
||||||
if (context->motion_last_actor)
|
|
||||||
cev.crossing.related = last_actor;
|
|
||||||
else
|
|
||||||
cev.crossing.related = NULL;
|
|
||||||
|
|
||||||
emit_pointer_event (&cev, device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_motion_last_actor (motion_current_actor, device);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2345,6 +2271,8 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
{
|
{
|
||||||
ClutterInputDevice *device = NULL;
|
ClutterInputDevice *device = NULL;
|
||||||
|
|
||||||
|
device = clutter_event_get_device (event);
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case CLUTTER_NOTHING:
|
case CLUTTER_NOTHING:
|
||||||
@ -2352,23 +2280,8 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_LEAVE:
|
case CLUTTER_LEAVE:
|
||||||
/* The source is set for generated events, not for events
|
|
||||||
* resulting from the cursor leaving the stage
|
|
||||||
*/
|
|
||||||
if (event->any.source == NULL)
|
|
||||||
{
|
|
||||||
ClutterActor *last_actor = context->motion_last_actor;
|
|
||||||
|
|
||||||
if (event->crossing.device != NULL)
|
|
||||||
last_actor = event->crossing.device->motion_last_actor;
|
|
||||||
|
|
||||||
event->any.source = last_actor;
|
|
||||||
|
|
||||||
set_motion_last_actor (NULL, event->crossing.device);
|
|
||||||
}
|
|
||||||
/* flow through */
|
|
||||||
case CLUTTER_ENTER:
|
case CLUTTER_ENTER:
|
||||||
emit_pointer_event (event, event->crossing.device);
|
emit_pointer_event (event, device);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_DESTROY_NOTIFY:
|
case CLUTTER_DESTROY_NOTIFY:
|
||||||
@ -2400,8 +2313,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_MOTION:
|
case CLUTTER_MOTION:
|
||||||
device = event->motion.device;
|
|
||||||
|
|
||||||
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
||||||
* and the event is not a synthetic event with source set.
|
* and the event is not a synthetic event with source set.
|
||||||
*/
|
*/
|
||||||
@ -2434,8 +2345,7 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fallthrough */
|
/* fallthrough from motion */
|
||||||
|
|
||||||
case CLUTTER_BUTTON_PRESS:
|
case CLUTTER_BUTTON_PRESS:
|
||||||
case CLUTTER_BUTTON_RELEASE:
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
case CLUTTER_SCROLL:
|
case CLUTTER_SCROLL:
|
||||||
@ -2462,18 +2372,29 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
x, y);
|
x, y);
|
||||||
|
|
||||||
event->button.source = stage;
|
event->button.source = stage;
|
||||||
emit_pointer_event (event, event->button.device);
|
event->button.click_count = 1;
|
||||||
|
emit_pointer_event (event, device);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map the event to a reactive actor */
|
/* if the backend provides a device then we should
|
||||||
|
* already have everything we need to update it and
|
||||||
|
* get the actor underneath
|
||||||
|
*/
|
||||||
|
if (device != NULL)
|
||||||
|
actor = _clutter_input_device_update (device);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (EVENT, "No device found: picking");
|
||||||
|
|
||||||
actor = _clutter_do_pick (CLUTTER_STAGE (stage),
|
actor = _clutter_do_pick (CLUTTER_STAGE (stage),
|
||||||
x, y,
|
x, y,
|
||||||
CLUTTER_PICK_REACTIVE);
|
CLUTTER_PICK_REACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
event->any.source = actor;
|
event->any.source = actor;
|
||||||
if (!actor)
|
if (event->any.source == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2482,7 +2403,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
actor = event->any.source;
|
actor = event->any.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: for an optimisation should check if there are
|
/* FIXME: for an optimisation should check if there are
|
||||||
* actually any reactive actors and avoid the pick all together
|
* actually any reactive actors and avoid the pick all together
|
||||||
* (signalling just the stage). Should be big help for gles.
|
* (signalling just the stage). Should be big help for gles.
|
||||||
@ -2493,33 +2413,12 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
x, y,
|
x, y,
|
||||||
actor);
|
actor);
|
||||||
|
|
||||||
/* Create, enter/leave events if needed */
|
|
||||||
generate_enter_leave_events (event);
|
|
||||||
|
|
||||||
if (event->type != CLUTTER_MOTION)
|
if (event->type != CLUTTER_MOTION)
|
||||||
{
|
{
|
||||||
/* Generate click count */
|
/* Generate click count */
|
||||||
event_click_count_generate (event);
|
event_click_count_generate (event);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device == NULL)
|
|
||||||
{
|
|
||||||
switch (event->type)
|
|
||||||
{
|
|
||||||
case CLUTTER_BUTTON_PRESS:
|
|
||||||
case CLUTTER_BUTTON_RELEASE:
|
|
||||||
device = event->button.device;
|
|
||||||
break;
|
|
||||||
case CLUTTER_SCROLL:
|
|
||||||
device = event->scroll.device;
|
|
||||||
break;
|
|
||||||
case CLUTTER_MOTION:
|
|
||||||
/* already handled in the MOTION case of the switch */
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_pointer_event (event, device);
|
emit_pointer_event (event, device);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3023,9 +2922,19 @@ clutter_get_font_flags (void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_get_input_device_for_id:
|
* clutter_get_input_device_for_id:
|
||||||
* @id: a device id
|
* @id: the unique id for a device
|
||||||
*
|
*
|
||||||
* Retrieves the #ClutterInputDevice from its id.
|
* Retrieves the #ClutterInputDevice from its @id. This is a convenience
|
||||||
|
* wrapper for clutter_device_manager_get_device() and it is functionally
|
||||||
|
* equivalent to:
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* ClutterDeviceManager *manager;
|
||||||
|
* ClutterInputDevice *device;
|
||||||
|
*
|
||||||
|
* manager = clutter_device_manager_get_default ();
|
||||||
|
* device = clutter_device_manager_get_device (manager, id);
|
||||||
|
* ]|
|
||||||
*
|
*
|
||||||
* Return value: (transfer none): a #ClutterInputDevice, or %NULL
|
* Return value: (transfer none): a #ClutterInputDevice, or %NULL
|
||||||
*
|
*
|
||||||
@ -3034,23 +2943,11 @@ clutter_get_font_flags (void)
|
|||||||
ClutterInputDevice *
|
ClutterInputDevice *
|
||||||
clutter_get_input_device_for_id (gint id)
|
clutter_get_input_device_for_id (gint id)
|
||||||
{
|
{
|
||||||
GSList *item;
|
ClutterDeviceManager *manager;
|
||||||
ClutterInputDevice *device = NULL;
|
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
for (item = context->input_devices;
|
return clutter_device_manager_get_device (manager, id);
|
||||||
item != NULL;
|
|
||||||
item = item->next)
|
|
||||||
{
|
|
||||||
device = item->data;
|
|
||||||
|
|
||||||
if (device->id == id)
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,6 +12,7 @@ VOID:INT,INT,INT,INT
|
|||||||
VOID:OBJECT
|
VOID:OBJECT
|
||||||
VOID:OBJECT,OBJECT,PARAM
|
VOID:OBJECT,OBJECT,PARAM
|
||||||
VOID:OBJECT,POINTER
|
VOID:OBJECT,POINTER
|
||||||
|
VOID:POINTER
|
||||||
VOID:STRING,BOOLEAN,BOOLEAN
|
VOID:STRING,BOOLEAN,BOOLEAN
|
||||||
VOID:STRING,INT
|
VOID:STRING,INT
|
||||||
VOID:UINT
|
VOID:UINT
|
||||||
|
@ -288,14 +288,13 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
* event handling
|
* event handling
|
||||||
*/
|
*/
|
||||||
stages = clutter_stage_manager_list_stages (stage_manager);
|
stages = clutter_stage_manager_list_stages (stage_manager);
|
||||||
g_slist_foreach (stages, (GFunc)g_object_ref, NULL);
|
g_slist_foreach (stages, (GFunc) g_object_ref, NULL);
|
||||||
|
|
||||||
CLUTTER_TIMER_START (_clutter_uprof_context, master_event_process);
|
CLUTTER_TIMER_START (_clutter_uprof_context, master_event_process);
|
||||||
|
|
||||||
master_clock->updated_stages = FALSE;
|
master_clock->updated_stages = FALSE;
|
||||||
|
|
||||||
/* Process queued events
|
/* Process queued events */
|
||||||
*/
|
|
||||||
for (l = stages; l != NULL; l = l->next)
|
for (l = stages; l != NULL; l = l->next)
|
||||||
_clutter_stage_process_queued_events (l->data);
|
_clutter_stage_process_queued_events (l->data);
|
||||||
|
|
||||||
@ -311,7 +310,7 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
for (l = stages; l != NULL; l = l->next)
|
for (l = stages; l != NULL; l = l->next)
|
||||||
master_clock->updated_stages |= _clutter_stage_do_update (l->data);
|
master_clock->updated_stages |= _clutter_stage_do_update (l->data);
|
||||||
|
|
||||||
g_slist_foreach (stages, (GFunc)g_object_unref, NULL);
|
g_slist_foreach (stages, (GFunc) g_object_unref, NULL);
|
||||||
g_slist_free (stages);
|
g_slist_free (stages);
|
||||||
|
|
||||||
master_clock->prev_tick = master_clock->cur_tick;
|
master_clock->prev_tick = master_clock->cur_tick;
|
||||||
@ -446,7 +445,7 @@ _clutter_master_clock_start_running (ClutterMasterClock *master_clock)
|
|||||||
void
|
void
|
||||||
_clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
_clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
||||||
{
|
{
|
||||||
GSList *l, *next;
|
GSList *timelines, *l;
|
||||||
|
|
||||||
CLUTTER_STATIC_TIMER (master_timeline_advance,
|
CLUTTER_STATIC_TIMER (master_timeline_advance,
|
||||||
"Master Clock",
|
"Master Clock",
|
||||||
@ -456,23 +455,38 @@ _clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
|||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (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);
|
CLUTTER_TIMER_START (_clutter_uprof_context, master_timeline_advance);
|
||||||
|
|
||||||
for (l = master_clock->timelines; l != NULL; l = next)
|
/* we protect ourselves from timelines being removed during
|
||||||
{
|
* the advancement by other timelines by copying the list of
|
||||||
next = l->next;
|
* 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);
|
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);
|
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 "pango/cogl-pango.h"
|
||||||
|
|
||||||
#include "clutter-backend.h"
|
#include "clutter-backend.h"
|
||||||
|
#include "clutter-device-manager.h"
|
||||||
#include "clutter-event.h"
|
#include "clutter-event.h"
|
||||||
#include "clutter-feature.h"
|
#include "clutter-feature.h"
|
||||||
#include "clutter-id-pool.h"
|
#include "clutter-id-pool.h"
|
||||||
@ -52,6 +53,8 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _ClutterMainContext ClutterMainContext;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CLUTTER_ACTOR_UNUSED_FLAG = 0,
|
CLUTTER_ACTOR_UNUSED_FLAG = 0,
|
||||||
|
|
||||||
@ -82,21 +85,54 @@ typedef enum {
|
|||||||
|
|
||||||
struct _ClutterInputDevice
|
struct _ClutterInputDevice
|
||||||
{
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
gint id;
|
gint id;
|
||||||
|
|
||||||
ClutterInputDeviceType device_type;
|
ClutterInputDeviceType device_type;
|
||||||
|
|
||||||
ClutterActor *pointer_grab_actor;
|
gchar *device_name;
|
||||||
ClutterActor *motion_last_actor;
|
|
||||||
|
|
||||||
|
/* the actor underneath the pointer */
|
||||||
|
ClutterActor *cursor_actor;
|
||||||
|
|
||||||
|
/* the actor that has a grab in place for the device */
|
||||||
|
ClutterActor *pointer_grab_actor;
|
||||||
|
|
||||||
|
/* the current click count */
|
||||||
gint click_count;
|
gint click_count;
|
||||||
|
|
||||||
|
/* the stage the device is on */
|
||||||
|
ClutterStage *stage;
|
||||||
|
|
||||||
|
/* the current state */
|
||||||
|
gint current_x;
|
||||||
|
gint current_y;
|
||||||
|
guint32 current_time;
|
||||||
|
gint current_button_number;
|
||||||
|
ClutterModifierType current_state;
|
||||||
|
|
||||||
|
/* the previous state, used for click count generation */
|
||||||
gint previous_x;
|
gint previous_x;
|
||||||
gint previous_y;
|
gint previous_y;
|
||||||
guint32 previous_time;
|
guint32 previous_time;
|
||||||
gint previous_button_number;
|
gint previous_button_number;
|
||||||
|
ClutterModifierType previous_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _ClutterMainContext ClutterMainContext;
|
struct _ClutterStageManager
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GSList *stages;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterDeviceManager
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GSList *devices;
|
||||||
|
};
|
||||||
|
|
||||||
struct _ClutterMainContext
|
struct _ClutterMainContext
|
||||||
{
|
{
|
||||||
@ -138,9 +174,6 @@ struct _ClutterMainContext
|
|||||||
PangoContext *pango_context; /* Global Pango context */
|
PangoContext *pango_context; /* Global Pango context */
|
||||||
CoglPangoFontMap *font_map; /* Global font map */
|
CoglPangoFontMap *font_map; /* Global font map */
|
||||||
|
|
||||||
GSList *input_devices; /* For extra input devices, i.e
|
|
||||||
MultiTouch */
|
|
||||||
|
|
||||||
ClutterEvent *current_event;
|
ClutterEvent *current_event;
|
||||||
guint32 last_event_time;
|
guint32 last_event_time;
|
||||||
|
|
||||||
@ -170,21 +203,34 @@ PangoContext *_clutter_context_get_pango_context (ClutterMainContext *self);
|
|||||||
|
|
||||||
#define I_(str) (g_intern_static_string ((str)))
|
#define I_(str) (g_intern_static_string ((str)))
|
||||||
|
|
||||||
|
/* device manager */
|
||||||
|
void _clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
|
||||||
|
ClutterInputDevice *device);
|
||||||
|
void _clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
|
||||||
|
ClutterInputDevice *device);
|
||||||
|
void _clutter_device_manager_update_devices (ClutterDeviceManager *device_manager);
|
||||||
|
|
||||||
|
/* input device */
|
||||||
|
void _clutter_input_device_set_coords (ClutterInputDevice *device,
|
||||||
|
gint x,
|
||||||
|
gint y);
|
||||||
|
void _clutter_input_device_set_state (ClutterInputDevice *device,
|
||||||
|
ClutterModifierType state);
|
||||||
|
void _clutter_input_device_set_time (ClutterInputDevice *device,
|
||||||
|
guint32 time_);
|
||||||
|
void _clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||||
|
ClutterStage *stage);
|
||||||
|
void _clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||||
|
ClutterActor *actor);
|
||||||
|
ClutterActor *_clutter_input_device_update (ClutterInputDevice *device);
|
||||||
|
|
||||||
/* stage manager */
|
/* stage manager */
|
||||||
struct _ClutterStageManager
|
|
||||||
{
|
|
||||||
GObject parent_instance;
|
|
||||||
|
|
||||||
GSList *stages;
|
|
||||||
};
|
|
||||||
|
|
||||||
void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
||||||
ClutterStage *stage);
|
ClutterStage *stage);
|
||||||
void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
||||||
ClutterStage *stage);
|
ClutterStage *stage);
|
||||||
|
|
||||||
/* stage */
|
/* stage */
|
||||||
|
|
||||||
void _clutter_stage_set_window (ClutterStage *stage,
|
void _clutter_stage_set_window (ClutterStage *stage,
|
||||||
ClutterStageWindow *stage_window);
|
ClutterStageWindow *stage_window);
|
||||||
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
||||||
@ -198,6 +244,7 @@ void _clutter_stage_queue_event (ClutterStage *stage,
|
|||||||
ClutterEvent *event);
|
ClutterEvent *event);
|
||||||
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
|
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
|
||||||
void _clutter_stage_process_queued_events (ClutterStage *stage);
|
void _clutter_stage_process_queued_events (ClutterStage *stage);
|
||||||
|
void _clutter_stage_update_input_devices (ClutterStage *stage);
|
||||||
|
|
||||||
/* vfuncs implemented by backend */
|
/* vfuncs implemented by backend */
|
||||||
GType _clutter_backend_impl_get_type (void);
|
GType _clutter_backend_impl_get_type (void);
|
||||||
@ -271,6 +318,9 @@ void _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
|
|||||||
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
||||||
gboolean enable);
|
gboolean enable);
|
||||||
|
|
||||||
|
void _clutter_actor_set_has_pointer (ClutterActor *self,
|
||||||
|
gboolean has_pointer);
|
||||||
|
|
||||||
void _clutter_run_repaint_functions (void);
|
void _clutter_run_repaint_functions (void);
|
||||||
|
|
||||||
gint32 _clutter_backend_get_units_serial (ClutterBackend *backend);
|
gint32 _clutter_backend_get_units_serial (ClutterBackend *backend);
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
#include "clutter-id-pool.h"
|
#include "clutter-id-pool.h"
|
||||||
#include "clutter-container.h"
|
#include "clutter-container.h"
|
||||||
#include "clutter-profile.h"
|
#include "clutter-profile.h"
|
||||||
|
#include "clutter-input-device.h"
|
||||||
|
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
|
|
||||||
@ -113,7 +114,8 @@ enum
|
|||||||
PROP_USER_RESIZE,
|
PROP_USER_RESIZE,
|
||||||
PROP_USE_FOG,
|
PROP_USE_FOG,
|
||||||
PROP_FOG,
|
PROP_FOG,
|
||||||
PROP_USE_ALPHA
|
PROP_USE_ALPHA,
|
||||||
|
PROP_KEY_FOCUS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -454,6 +456,7 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
|||||||
{
|
{
|
||||||
ClutterStagePrivate *priv;
|
ClutterStagePrivate *priv;
|
||||||
gboolean first_event;
|
gboolean first_event;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||||
|
|
||||||
@ -461,14 +464,31 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
|||||||
|
|
||||||
first_event = priv->event_queue->length == 0;
|
first_event = priv->event_queue->length == 0;
|
||||||
|
|
||||||
g_queue_push_tail (priv->event_queue,
|
g_queue_push_tail (priv->event_queue, clutter_event_copy (event));
|
||||||
clutter_event_copy (event));
|
|
||||||
|
|
||||||
if (first_event)
|
if (first_event)
|
||||||
{
|
{
|
||||||
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
|
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
|
||||||
_clutter_master_clock_start_running (master_clock);
|
_clutter_master_clock_start_running (master_clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if needed, update the state of the input device of the event.
|
||||||
|
* we do it here to avoid calling the same code from every backend
|
||||||
|
* event processing function
|
||||||
|
*/
|
||||||
|
device = clutter_event_get_device (event);
|
||||||
|
if (device != NULL)
|
||||||
|
{
|
||||||
|
ClutterModifierType event_state = clutter_event_get_state (event);
|
||||||
|
guint32 event_time = clutter_event_get_time (event);
|
||||||
|
gfloat event_x, event_y;
|
||||||
|
|
||||||
|
clutter_event_get_coords (event, &event_x, &event_y);
|
||||||
|
|
||||||
|
_clutter_input_device_set_coords (device, event_x, event_y);
|
||||||
|
_clutter_input_device_set_state (device, event_state);
|
||||||
|
_clutter_input_device_set_time (device, event_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -487,7 +507,7 @@ void
|
|||||||
_clutter_stage_process_queued_events (ClutterStage *stage)
|
_clutter_stage_process_queued_events (ClutterStage *stage)
|
||||||
{
|
{
|
||||||
ClutterStagePrivate *priv;
|
ClutterStagePrivate *priv;
|
||||||
GList *events, *l;;
|
GList *events, *l;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||||
|
|
||||||
@ -506,7 +526,7 @@ _clutter_stage_process_queued_events (ClutterStage *stage)
|
|||||||
priv->event_queue->tail = NULL;
|
priv->event_queue->tail = NULL;
|
||||||
priv->event_queue->length = 0;
|
priv->event_queue->length = 0;
|
||||||
|
|
||||||
for (l = events; l; l = l->next)
|
for (l = events; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
ClutterEvent *event;
|
ClutterEvent *event;
|
||||||
ClutterEvent *next_event;
|
ClutterEvent *next_event;
|
||||||
@ -694,6 +714,10 @@ clutter_stage_set_property (GObject *object,
|
|||||||
clutter_stage_set_use_alpha (stage, g_value_get_boolean (value));
|
clutter_stage_set_use_alpha (stage, g_value_get_boolean (value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_KEY_FOCUS:
|
||||||
|
clutter_stage_set_key_focus (stage, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -750,6 +774,10 @@ clutter_stage_get_property (GObject *gobject,
|
|||||||
g_value_set_boolean (value, priv->use_alpha);
|
g_value_set_boolean (value, priv->use_alpha);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_KEY_FOCUS:
|
||||||
|
g_value_set_object (value, priv->key_focused_actor);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -994,6 +1022,23 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
|||||||
CLUTTER_PARAM_READWRITE);
|
CLUTTER_PARAM_READWRITE);
|
||||||
g_object_class_install_property (gobject_class, PROP_USE_ALPHA, pspec);
|
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
|
* ClutterStage::fullscreen
|
||||||
* @stage: the stage which was fullscreened
|
* @stage: the stage which was fullscreened
|
||||||
@ -1749,6 +1794,8 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
g_signal_emit_by_name (stage, "key-focus-in");
|
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)
|
if (priv->selection_bound != priv->position)
|
||||||
{
|
{
|
||||||
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));
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -803,6 +804,7 @@ clutter_text_delete_selection (ClutterText *self)
|
|||||||
priv->position = start_index;
|
priv->position = start_index;
|
||||||
priv->selection_bound = start_index;
|
priv->selection_bound = start_index;
|
||||||
|
|
||||||
|
/* Not required to be guarded by g_object_freeze/thaw_notify */
|
||||||
if (priv->position != old_position)
|
if (priv->position != old_position)
|
||||||
g_object_notify (G_OBJECT (self), "position");
|
g_object_notify (G_OBJECT (self), "position");
|
||||||
|
|
||||||
@ -812,6 +814,21 @@ clutter_text_delete_selection (ClutterText *self)
|
|||||||
return TRUE;
|
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
|
static inline void
|
||||||
clutter_text_set_text_internal (ClutterText *self,
|
clutter_text_set_text_internal (ClutterText *self,
|
||||||
const gchar *text)
|
const gchar *text)
|
||||||
@ -857,8 +874,7 @@ clutter_text_set_text_internal (ClutterText *self,
|
|||||||
|
|
||||||
if (priv->n_bytes == 0)
|
if (priv->n_bytes == 0)
|
||||||
{
|
{
|
||||||
clutter_text_set_cursor_position (self, -1);
|
clutter_text_set_positions (self, -1, -1);
|
||||||
clutter_text_set_selection_bound (self, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clutter_text_dirty_cache (self);
|
clutter_text_dirty_cache (self);
|
||||||
@ -1493,8 +1509,7 @@ clutter_text_button_press (ClutterActor *actor,
|
|||||||
*/
|
*/
|
||||||
if (priv->text == NULL || priv->text[0] == '\0')
|
if (priv->text == NULL || priv->text[0] == '\0')
|
||||||
{
|
{
|
||||||
clutter_text_set_cursor_position (self, -1);
|
clutter_text_set_positions (self, -1, -1);
|
||||||
clutter_text_set_selection_bound (self, -1);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -1519,8 +1534,7 @@ clutter_text_button_press (ClutterActor *actor,
|
|||||||
*/
|
*/
|
||||||
if (event->click_count == 1)
|
if (event->click_count == 1)
|
||||||
{
|
{
|
||||||
clutter_text_set_cursor_position (self, offset);
|
clutter_text_set_positions (self, offset, offset);
|
||||||
clutter_text_set_selection_bound (self, offset);
|
|
||||||
}
|
}
|
||||||
else if (event->click_count == 2)
|
else if (event->click_count == 2)
|
||||||
{
|
{
|
||||||
@ -1565,8 +1579,7 @@ clutter_text_motion (ClutterActor *actor,
|
|||||||
clutter_text_set_cursor_position (self, offset);
|
clutter_text_set_cursor_position (self, offset);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clutter_text_set_cursor_position (self, offset);
|
clutter_text_set_positions (self, offset, offset);
|
||||||
clutter_text_set_selection_bound (self, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1896,6 +1909,8 @@ clutter_text_real_move_left (ClutterText *self,
|
|||||||
|
|
||||||
len = priv->n_chars;
|
len = priv->n_chars;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
if (pos != 0 && len != 0)
|
if (pos != 0 && len != 0)
|
||||||
{
|
{
|
||||||
if (modifiers & CLUTTER_CONTROL_MASK)
|
if (modifiers & CLUTTER_CONTROL_MASK)
|
||||||
@ -1919,6 +1934,8 @@ clutter_text_real_move_left (ClutterText *self,
|
|||||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||||
clutter_text_clear_selection (self);
|
clutter_text_clear_selection (self);
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1935,6 +1952,8 @@ clutter_text_real_move_right (ClutterText *self,
|
|||||||
|
|
||||||
len = priv->n_chars;
|
len = priv->n_chars;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
if (pos != -1 && len !=0)
|
if (pos != -1 && len !=0)
|
||||||
{
|
{
|
||||||
if (modifiers & CLUTTER_CONTROL_MASK)
|
if (modifiers & CLUTTER_CONTROL_MASK)
|
||||||
@ -1954,6 +1973,8 @@ clutter_text_real_move_right (ClutterText *self,
|
|||||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||||
clutter_text_clear_selection (self);
|
clutter_text_clear_selection (self);
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1970,6 +1991,8 @@ clutter_text_real_move_up (ClutterText *self,
|
|||||||
gint index_, trailing;
|
gint index_, trailing;
|
||||||
gint x;
|
gint x;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
layout = clutter_text_get_layout (self);
|
layout = clutter_text_get_layout (self);
|
||||||
|
|
||||||
if (priv->position == 0)
|
if (priv->position == 0)
|
||||||
@ -2007,6 +2030,8 @@ clutter_text_real_move_up (ClutterText *self,
|
|||||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||||
clutter_text_clear_selection (self);
|
clutter_text_clear_selection (self);
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2023,6 +2048,8 @@ clutter_text_real_move_down (ClutterText *self,
|
|||||||
gint index_, trailing;
|
gint index_, trailing;
|
||||||
gint x;
|
gint x;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
layout = clutter_text_get_layout (self);
|
layout = clutter_text_get_layout (self);
|
||||||
|
|
||||||
if (priv->position == 0)
|
if (priv->position == 0)
|
||||||
@ -2056,6 +2083,8 @@ clutter_text_real_move_down (ClutterText *self,
|
|||||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||||
clutter_text_clear_selection (self);
|
clutter_text_clear_selection (self);
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2068,12 +2097,16 @@ clutter_text_real_line_start (ClutterText *self,
|
|||||||
ClutterTextPrivate *priv = self->priv;
|
ClutterTextPrivate *priv = self->priv;
|
||||||
gint position;
|
gint position;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
position = clutter_text_move_line_start (self, priv->position);
|
position = clutter_text_move_line_start (self, priv->position);
|
||||||
clutter_text_set_cursor_position (self, position);
|
clutter_text_set_cursor_position (self, position);
|
||||||
|
|
||||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||||
clutter_text_clear_selection (self);
|
clutter_text_clear_selection (self);
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2086,12 +2119,16 @@ clutter_text_real_line_end (ClutterText *self,
|
|||||||
ClutterTextPrivate *priv = self->priv;
|
ClutterTextPrivate *priv = self->priv;
|
||||||
gint position;
|
gint position;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
position = clutter_text_move_line_end (self, priv->position);
|
position = clutter_text_move_line_end (self, priv->position);
|
||||||
clutter_text_set_cursor_position (self, position);
|
clutter_text_set_cursor_position (self, position);
|
||||||
|
|
||||||
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK)))
|
||||||
clutter_text_clear_selection (self);
|
clutter_text_clear_selection (self);
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2101,8 +2138,7 @@ clutter_text_real_select_all (ClutterText *self,
|
|||||||
guint keyval,
|
guint keyval,
|
||||||
ClutterModifierType modifiers)
|
ClutterModifierType modifiers)
|
||||||
{
|
{
|
||||||
clutter_text_set_cursor_position (self, 0);
|
clutter_text_set_positions (self, 0, self->priv->n_chars);
|
||||||
clutter_text_set_selection_bound (self, self->priv->n_chars);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -2151,15 +2187,13 @@ clutter_text_real_del_prev (ClutterText *self,
|
|||||||
{
|
{
|
||||||
clutter_text_delete_text (self, len - 1, len);
|
clutter_text_delete_text (self, len - 1, len);
|
||||||
|
|
||||||
clutter_text_set_cursor_position (self, -1);
|
clutter_text_set_positions (self, -1, -1);
|
||||||
clutter_text_set_selection_bound (self, -1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clutter_text_delete_text (self, pos - 1, pos);
|
clutter_text_delete_text (self, pos - 1, pos);
|
||||||
|
|
||||||
clutter_text_set_cursor_position (self, pos - 1);
|
clutter_text_set_positions (self, pos - 1, pos - 1);
|
||||||
clutter_text_set_selection_bound (self, pos - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3260,12 +3294,7 @@ clutter_text_set_selection (ClutterText *self,
|
|||||||
start_pos = MIN (priv->n_chars, start_pos);
|
start_pos = MIN (priv->n_chars, start_pos);
|
||||||
end_pos = MIN (priv->n_chars, end_pos);
|
end_pos = MIN (priv->n_chars, end_pos);
|
||||||
|
|
||||||
g_object_freeze_notify (G_OBJECT (self));
|
clutter_text_set_positions (self, start_pos, end_pos);
|
||||||
|
|
||||||
clutter_text_set_cursor_position (self, start_pos);
|
|
||||||
clutter_text_set_selection_bound (self, end_pos);
|
|
||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (self));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4349,8 +4378,7 @@ clutter_text_insert_unichar (ClutterText *self,
|
|||||||
|
|
||||||
if (priv->position >= 0)
|
if (priv->position >= 0)
|
||||||
{
|
{
|
||||||
clutter_text_set_cursor_position (self, priv->position + 1);
|
clutter_text_set_positions (self, priv->position + 1, priv->position);
|
||||||
clutter_text_set_selection_bound (self, priv->position);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_string_free (new, TRUE);
|
g_string_free (new, TRUE);
|
||||||
@ -4397,8 +4425,9 @@ clutter_text_insert_text (ClutterText *self,
|
|||||||
|
|
||||||
if (position >= 0 && priv->position >= position)
|
if (position >= 0 && priv->position >= position)
|
||||||
{
|
{
|
||||||
clutter_text_set_cursor_position (self, priv->position + g_utf8_strlen (text, -1));
|
clutter_text_set_positions (self,
|
||||||
clutter_text_set_selection_bound (self, priv->position);
|
priv->position + g_utf8_strlen (text, -1),
|
||||||
|
priv->position);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_string_free (new, TRUE);
|
g_string_free (new, TRUE);
|
||||||
|
@ -52,9 +52,12 @@ _clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
|||||||
ClutterTimeoutInterval *interval,
|
ClutterTimeoutInterval *interval,
|
||||||
gint *delay)
|
gint *delay)
|
||||||
{
|
{
|
||||||
guint elapsed_time
|
guint elapsed_time, new_frame_num;
|
||||||
= _clutter_timeout_interval_get_ticks (current_time, interval);
|
|
||||||
guint new_frame_num = elapsed_time * interval->fps / 1000;
|
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
|
/* 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
|
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 */
|
/* Reset the start time */
|
||||||
interval->start_time = *current_time;
|
interval->start_time = *current_time;
|
||||||
|
|
||||||
/* Move the start time as if one whole frame has elapsed */
|
/* Move the start time as if one whole frame has elapsed */
|
||||||
g_time_val_add (&interval->start_time, -(gint) frame_time * 1000);
|
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)
|
if (delay)
|
||||||
*delay = 0;
|
*delay = 0;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (new_frame_num > interval->frame_count)
|
else if (new_frame_num > interval->frame_count)
|
||||||
{
|
{
|
||||||
if (delay)
|
if (delay)
|
||||||
*delay = 0;
|
*delay = 0;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -87,6 +93,7 @@ _clutter_timeout_interval_prepare (const GTimeVal *current_time,
|
|||||||
if (delay)
|
if (delay)
|
||||||
*delay = ((interval->frame_count + 1) * 1000 / interval->fps
|
*delay = ((interval->frame_count + 1) * 1000 / interval->fps
|
||||||
- elapsed_time);
|
- elapsed_time);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,9 +106,10 @@ _clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
|
|||||||
if ((* callback) (user_data))
|
if ((* callback) (user_data))
|
||||||
{
|
{
|
||||||
interval->frame_count++;
|
interval->frame_count++;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,12 +359,6 @@ clutter_timeout_pool_finalize (GSource *source)
|
|||||||
* always sorted, so that the extraction of the next timeout function is
|
* always sorted, so that the extraction of the next timeout function is
|
||||||
* a constant time operation.
|
* 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
|
* Return value: the newly created #ClutterTimeoutPool. The created pool
|
||||||
* is owned by the GLib default context and will be automatically
|
* is owned by the GLib default context and will be automatically
|
||||||
* destroyed when the context is destroyed. It is possible to force
|
* 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
|
* 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.
|
* 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
|
* example, if @func takes half the interval time to execute then the
|
||||||
* function will be called again half the interval time after it
|
* function will be called again half the interval time after it
|
||||||
* finished. Before version 0.8 it would not fire until a full
|
* 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_find_by_id)))
|
||||||
{
|
{
|
||||||
clutter_timeout_unref (l->data);
|
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-clone.h"
|
||||||
#include "clutter-color.h"
|
#include "clutter-color.h"
|
||||||
#include "clutter-container.h"
|
#include "clutter-container.h"
|
||||||
|
#include "clutter-device-manager.h"
|
||||||
#include "clutter-event.h"
|
#include "clutter-event.h"
|
||||||
#include "clutter-feature.h"
|
#include "clutter-feature.h"
|
||||||
#include "clutter-fixed-layout.h"
|
#include "clutter-fixed-layout.h"
|
||||||
#include "clutter-flow-layout.h"
|
#include "clutter-flow-layout.h"
|
||||||
#include "clutter-frame-source.h"
|
#include "clutter-frame-source.h"
|
||||||
#include "clutter-group.h"
|
#include "clutter-group.h"
|
||||||
|
#include "clutter-input-device.h"
|
||||||
#include "clutter-interval.h"
|
#include "clutter-interval.h"
|
||||||
#include "clutter-keysyms.h"
|
#include "clutter-keysyms.h"
|
||||||
#include "clutter-layout-manager.h"
|
#include "clutter-layout-manager.h"
|
||||||
|
@ -115,6 +115,12 @@ typedef struct
|
|||||||
CoglAtlas *atlas;
|
CoglAtlas *atlas;
|
||||||
CoglHandle atlas_texture;
|
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;
|
CoglContextDriver drv;
|
||||||
} CoglContext;
|
} CoglContext;
|
||||||
|
|
||||||
|
@ -101,6 +101,8 @@ CoglTextureUnit *
|
|||||||
_cogl_get_texture_unit (int index_);
|
_cogl_get_texture_unit (int index_);
|
||||||
void
|
void
|
||||||
_cogl_destroy_texture_units (void);
|
_cogl_destroy_texture_units (void);
|
||||||
|
guint
|
||||||
|
_cogl_get_max_texture_image_units (void);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_flush_face_winding (void);
|
_cogl_flush_face_winding (void);
|
||||||
|
@ -225,30 +225,51 @@ _cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* DEBUGGING CODE XXX:
|
/* DEBUGGING CODE XXX: This path will cause all rectangles to be
|
||||||
* This path will cause all rectangles to be drawn with a red, green
|
* drawn with a coloured outline. Each batch will be rendered with
|
||||||
* or blue outline with no blending. This may e.g. help with debugging
|
* the same color. This may e.g. help with debugging texture slicing
|
||||||
* texture slicing issues or blending issues, plus it looks quite cool.
|
* issues, visually seeing what is batched and debugging blending
|
||||||
|
* issues, plus it looks quite cool.
|
||||||
*/
|
*/
|
||||||
if (cogl_debug_flags & COGL_DEBUG_RECTANGLES)
|
if (cogl_debug_flags & COGL_DEBUG_RECTANGLES)
|
||||||
{
|
{
|
||||||
static CoglHandle outline = COGL_INVALID_HANDLE;
|
static CoglHandle outline = COGL_INVALID_HANDLE;
|
||||||
static int color = 0;
|
guint8 color_intensity;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
|
||||||
|
|
||||||
if (outline == COGL_INVALID_HANDLE)
|
if (outline == COGL_INVALID_HANDLE)
|
||||||
outline = cogl_material_new ();
|
outline = cogl_material_new ();
|
||||||
|
|
||||||
cogl_enable (COGL_ENABLE_VERTEX_ARRAY);
|
/* The least significant three bits represent the three
|
||||||
for (i = 0; i < batch_len; i++, color = (color + 1) % 3)
|
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,
|
cogl_material_set_color4ub (outline,
|
||||||
color == 0 ? 0xff : 0x00,
|
(ctxt->journal_rectangles_color & 1) ?
|
||||||
color == 1 ? 0xff : 0x00,
|
color_intensity : 0,
|
||||||
color == 2 ? 0xff : 0x00,
|
(ctxt->journal_rectangles_color & 2) ?
|
||||||
|
color_intensity : 0,
|
||||||
|
(ctxt->journal_rectangles_color & 4) ?
|
||||||
|
color_intensity : 0,
|
||||||
0xff);
|
0xff);
|
||||||
_cogl_material_flush_gl_state (outline, NULL);
|
_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);
|
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))
|
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
|
||||||
cogl_get_modelview_matrix (&entry->model_view);
|
cogl_get_modelview_matrix (&entry->model_view);
|
||||||
|
|
||||||
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_BATCHING
|
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_BATCHING))
|
||||||
|| cogl_debug_flags & COGL_DEBUG_RECTANGLES))
|
|
||||||
_cogl_journal_flush ();
|
_cogl_journal_flush ();
|
||||||
|
|
||||||
COGL_TIMER_STOP (_cogl_uprof_context, log_timer);
|
COGL_TIMER_STOP (_cogl_uprof_context, log_timer);
|
||||||
|
@ -48,12 +48,6 @@
|
|||||||
#include "../gles/cogl-gles2-wrapper.h"
|
#include "../gles/cogl-gles2-wrapper.h"
|
||||||
#endif
|
#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
|
#ifdef HAVE_COGL_GL
|
||||||
#define glActiveTexture ctx->drv.pf_glActiveTexture
|
#define glActiveTexture ctx->drv.pf_glActiveTexture
|
||||||
#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
|
#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);
|
_cogl_material_pre_change_notify (material, FALSE, NULL);
|
||||||
|
|
||||||
material->n_layers = g_list_length (material->layers);
|
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))
|
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;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +120,8 @@ typedef struct _CoglTextureVertex CoglTextureVertex;
|
|||||||
* @COGL_PIXEL_FORMAT_RGB_565: RGB, 16 bits
|
* @COGL_PIXEL_FORMAT_RGB_565: RGB, 16 bits
|
||||||
* @COGL_PIXEL_FORMAT_RGBA_4444: RGBA, 16 bits
|
* @COGL_PIXEL_FORMAT_RGBA_4444: RGBA, 16 bits
|
||||||
* @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits
|
* @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits
|
||||||
* @COGL_PIXEL_FORMAT_YUV: FIXME
|
* @COGL_PIXEL_FORMAT_YUV: Not currently supported
|
||||||
* @COGL_PIXEL_FORMAT_G_8: FIXME
|
* @COGL_PIXEL_FORMAT_G_8: Single luminance component
|
||||||
* @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits
|
* @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits
|
||||||
* @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits
|
* @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits
|
||||||
* @COGL_PIXEL_FORMAT_RGBA_8888: RGBA, 32 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_4444_PRE: Premultiplied RGBA, 16 bits
|
||||||
* @COGL_PIXEL_FORMAT_RGBA_5551_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
|
* Since: 0.8
|
||||||
*/
|
*/
|
||||||
|
@ -51,9 +51,9 @@
|
|||||||
int
|
int
|
||||||
cogl_util_next_p2 (int a)
|
cogl_util_next_p2 (int a)
|
||||||
{
|
{
|
||||||
int rval=1;
|
int rval = 1;
|
||||||
|
|
||||||
while(rval < a)
|
while (rval < a)
|
||||||
rval <<= 1;
|
rval <<= 1;
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
@ -237,8 +237,8 @@ cogl_fixed_get_type (void)
|
|||||||
g_value_register_transform_func (_cogl_fixed_type, G_TYPE_FLOAT,
|
g_value_register_transform_func (_cogl_fixed_type, G_TYPE_FLOAT,
|
||||||
cogl_value_transform_fixed_float);
|
cogl_value_transform_fixed_float);
|
||||||
g_value_register_transform_func (G_TYPE_FLOAT, _cogl_fixed_type,
|
g_value_register_transform_func (G_TYPE_FLOAT, _cogl_fixed_type,
|
||||||
|
|
||||||
cogl_value_transform_float_fixed);
|
cogl_value_transform_float_fixed);
|
||||||
|
|
||||||
g_value_register_transform_func (_cogl_fixed_type, G_TYPE_DOUBLE,
|
g_value_register_transform_func (_cogl_fixed_type, G_TYPE_DOUBLE,
|
||||||
cogl_value_transform_fixed_double);
|
cogl_value_transform_fixed_double);
|
||||||
g_value_register_transform_func (G_TYPE_DOUBLE, _cogl_fixed_type,
|
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;
|
GLuint generic_index = 0;
|
||||||
#endif
|
#endif
|
||||||
gulong enable_flags = 0;
|
gulong enable_flags = 0;
|
||||||
guint max_texcoord_attrib_unit = 0;
|
guint max_texcoord_attrib_unit = -1;
|
||||||
const GList *layers;
|
const GList *layers;
|
||||||
guint32 fallback_layers = 0;
|
guint32 fallback_layers = 0;
|
||||||
guint32 disable_layers = ~0;
|
guint32 disable_layers = ~0;
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "cogl-winsys.h"
|
#include "cogl-winsys.h"
|
||||||
#include "cogl-framebuffer-private.h"
|
#include "cogl-framebuffer-private.h"
|
||||||
#include "cogl-matrix-private.h"
|
#include "cogl-matrix-private.h"
|
||||||
|
#include "cogl-journal-private.h"
|
||||||
|
|
||||||
#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
|
#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
|
||||||
#include "cogl-gles2-wrapper.h"
|
#include "cogl-gles2-wrapper.h"
|
||||||
@ -155,6 +156,16 @@ cogl_clear (const CoglColor *color, gulong buffers)
|
|||||||
|
|
||||||
glClear (gl_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");
|
COGL_NOTE (DRAW, "Clear end");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,10 +740,11 @@ cogl_end_gl (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CoglTextureUnit *
|
static CoglTextureUnit *
|
||||||
_cogl_texture_unit_new (void)
|
_cogl_texture_unit_new (int index_)
|
||||||
{
|
{
|
||||||
CoglTextureUnit *unit = g_new0 (CoglTextureUnit, 1);
|
CoglTextureUnit *unit = g_new0 (CoglTextureUnit, 1);
|
||||||
unit->matrix_stack = _cogl_matrix_stack_new ();
|
unit->matrix_stack = _cogl_matrix_stack_new ();
|
||||||
|
unit->index = index_;
|
||||||
return unit;
|
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.
|
/* 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 */
|
/* Note: see comment after for() loop above */
|
||||||
ctx->texture_units =
|
ctx->texture_units =
|
||||||
@ -787,6 +799,36 @@ _cogl_destroy_texture_units (void)
|
|||||||
g_list_free (ctx->texture_units);
|
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
|
void
|
||||||
cogl_push_matrix (void)
|
cogl_push_matrix (void)
|
||||||
{
|
{
|
||||||
|
@ -33,4 +33,4 @@ libclutter_win32_la_SOURCES = \
|
|||||||
|
|
||||||
CLEANFILES = clutter-win32-$(CLUTTER_API_VERSION).pc
|
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-event.h"
|
||||||
#include "../clutter-main.h"
|
#include "../clutter-main.h"
|
||||||
|
#include "../clutter-input-device.h"
|
||||||
#include "../clutter-debug.h"
|
#include "../clutter-debug.h"
|
||||||
#include "../clutter-private.h"
|
#include "../clutter-private.h"
|
||||||
#include "../clutter-version.h"
|
#include "../clutter-version.h"
|
||||||
@ -47,6 +48,8 @@ static ClutterBackendWin32 *backend_singleton = NULL;
|
|||||||
|
|
||||||
static gchar *clutter_vblank_name = NULL;
|
static gchar *clutter_vblank_name = NULL;
|
||||||
|
|
||||||
|
static HINSTANCE clutter_hinst = NULL;
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -62,11 +65,45 @@ clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
|||||||
static void
|
static void
|
||||||
clutter_backend_win32_init_events (ClutterBackend *backend)
|
clutter_backend_win32_init_events (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
|
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "initialising the event loop");
|
CLUTTER_NOTE (EVENT, "initialising the event loop");
|
||||||
|
|
||||||
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
|
||||||
|
"id", 0,
|
||||||
|
"name", "Core Pointer",
|
||||||
|
"device-type", CLUTTER_POINTER_DEVICE,
|
||||||
|
NULL);
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
backend_win32->core_pointer = device;
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
|
||||||
|
"id", 1,
|
||||||
|
"name", "Core Keyboard",
|
||||||
|
"device-type", CLUTTER_KEYBOARD_DEVICE,
|
||||||
|
NULL);
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
backend_win32->core_keyboard = device;
|
||||||
|
|
||||||
_clutter_backend_win32_events_init (backend);
|
_clutter_backend_win32_events_init (backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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[] =
|
static const GOptionEntry entries[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -353,6 +390,7 @@ clutter_backend_win32_init (ClutterBackendWin32 *backend_win32)
|
|||||||
|
|
||||||
backend_win32->gl_context = NULL;
|
backend_win32->gl_context = NULL;
|
||||||
backend_win32->no_event_retrieval = FALSE;
|
backend_win32->no_event_retrieval = FALSE;
|
||||||
|
backend_win32->invisible_cursor = NULL;
|
||||||
|
|
||||||
/* FIXME: get from GetSystemMetric? */
|
/* FIXME: get from GetSystemMetric? */
|
||||||
clutter_backend_set_double_click_time (backend, 250);
|
clutter_backend_set_double_click_time (backend, 250);
|
||||||
@ -370,3 +408,13 @@ _clutter_backend_impl_get_type (void)
|
|||||||
{
|
{
|
||||||
return clutter_backend_win32_get_type ();
|
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;
|
HGLRC gl_context;
|
||||||
gboolean no_event_retrieval;
|
gboolean no_event_retrieval;
|
||||||
|
|
||||||
|
HCURSOR invisible_cursor;
|
||||||
|
|
||||||
GSource *event_source;
|
GSource *event_source;
|
||||||
|
|
||||||
|
ClutterInputDevice *core_pointer;
|
||||||
|
ClutterInputDevice *core_keyboard;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendWin32Class
|
struct _ClutterBackendWin32Class
|
||||||
@ -68,6 +73,8 @@ clutter_backend_win32_add_options (ClutterBackend *backend,
|
|||||||
ClutterFeatureFlags
|
ClutterFeatureFlags
|
||||||
clutter_backend_win32_get_features (ClutterBackend *backend);
|
clutter_backend_win32_get_features (ClutterBackend *backend);
|
||||||
|
|
||||||
|
HCURSOR _clutter_backend_win32_get_invisible_cursor (ClutterBackend *backend);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_BACKEND_WIN32_H__ */
|
#endif /* __CLUTTER_BACKEND_WIN32_H__ */
|
||||||
|
@ -201,9 +201,13 @@ get_modifier_state (WPARAM wparam)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static inline void
|
||||||
make_button_event (const MSG *msg, ClutterEvent *event,
|
make_button_event (const MSG *msg,
|
||||||
int button, int click_count, gboolean release)
|
ClutterEvent *event,
|
||||||
|
int button,
|
||||||
|
int click_count,
|
||||||
|
gboolean release,
|
||||||
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
event->type = release ? CLUTTER_BUTTON_RELEASE : CLUTTER_BUTTON_PRESS;
|
event->type = release ? CLUTTER_BUTTON_RELEASE : CLUTTER_BUTTON_PRESS;
|
||||||
event->button.time = msg->time;
|
event->button.time = msg->time;
|
||||||
@ -212,6 +216,7 @@ make_button_event (const MSG *msg, ClutterEvent *event,
|
|||||||
event->button.modifier_state = get_modifier_state (msg->wParam);
|
event->button.modifier_state = get_modifier_state (msg->wParam);
|
||||||
event->button.button = button;
|
event->button.button = button;
|
||||||
event->button.click_count = click_count;
|
event->button.click_count = click_count;
|
||||||
|
event->button.device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -429,39 +434,39 @@ message_translate (ClutterBackend *backend,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDOWN:
|
case WM_LBUTTONDOWN:
|
||||||
make_button_event (msg, event, 1, 1, FALSE);
|
make_button_event (msg, event, 1, 1, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_MBUTTONDOWN:
|
case WM_MBUTTONDOWN:
|
||||||
make_button_event (msg, event, 2, 1, FALSE);
|
make_button_event (msg, event, 2, 1, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDOWN:
|
case WM_RBUTTONDOWN:
|
||||||
make_button_event (msg, event, 3, 1, FALSE);
|
make_button_event (msg, event, 3, 1, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
make_button_event (msg, event, 1, 1, TRUE);
|
make_button_event (msg, event, 1, 1, TRUE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_MBUTTONUP:
|
case WM_MBUTTONUP:
|
||||||
make_button_event (msg, event, 2, 1, TRUE);
|
make_button_event (msg, event, 2, 1, TRUE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONUP:
|
case WM_RBUTTONUP:
|
||||||
make_button_event (msg, event, 3, 1, TRUE);
|
make_button_event (msg, event, 3, 1, TRUE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDBLCLK:
|
case WM_LBUTTONDBLCLK:
|
||||||
make_button_event (msg, event, 1, 2, FALSE);
|
make_button_event (msg, event, 1, 2, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_MBUTTONDBLCLK:
|
case WM_MBUTTONDBLCLK:
|
||||||
make_button_event (msg, event, 2, 2, FALSE);
|
make_button_event (msg, event, 2, 2, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDBLCLK:
|
case WM_RBUTTONDBLCLK:
|
||||||
make_button_event (msg, event, 3, 2, FALSE);
|
make_button_event (msg, event, 3, 2, FALSE, backend_win32->core_pointer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_MOUSEWHEEL:
|
case WM_MOUSEWHEEL:
|
||||||
@ -469,8 +474,8 @@ message_translate (ClutterBackend *backend,
|
|||||||
|
|
||||||
event->type = CLUTTER_SCROLL;
|
event->type = CLUTTER_SCROLL;
|
||||||
event->scroll.time = msg->time;
|
event->scroll.time = msg->time;
|
||||||
event->scroll.modifier_state
|
event->scroll.modifier_state = get_modifier_state (LOWORD (msg->wParam));
|
||||||
= get_modifier_state (LOWORD (msg->wParam));
|
event->scroll.device = backend_win32->core_pointer;
|
||||||
|
|
||||||
/* conversion to window coordinates is required */
|
/* conversion to window coordinates is required */
|
||||||
{
|
{
|
||||||
@ -500,7 +505,9 @@ message_translate (ClutterBackend *backend,
|
|||||||
event->motion.x = GET_X_LPARAM (msg->lParam);
|
event->motion.x = GET_X_LPARAM (msg->lParam);
|
||||||
event->motion.y = GET_Y_LPARAM (msg->lParam);
|
event->motion.y = GET_Y_LPARAM (msg->lParam);
|
||||||
event->motion.modifier_state = get_modifier_state (msg->wParam);
|
event->motion.modifier_state = get_modifier_state (msg->wParam);
|
||||||
/* We need to start tracking when the mouse leaves the stage if
|
event->motion.device = backend_win32->core_pointer;
|
||||||
|
|
||||||
|
/* We need to start tracking when the mouse enters the stage if
|
||||||
we're not already */
|
we're not already */
|
||||||
if (!stage_win32->tracking_mouse)
|
if (!stage_win32->tracking_mouse)
|
||||||
{
|
{
|
||||||
@ -511,6 +518,9 @@ message_translate (ClutterBackend *backend,
|
|||||||
tmevent.hwndTrack = stage_win32->hwnd;
|
tmevent.hwndTrack = stage_win32->hwnd;
|
||||||
TrackMouseEvent (&tmevent);
|
TrackMouseEvent (&tmevent);
|
||||||
|
|
||||||
|
/* we entered the stage */
|
||||||
|
_clutter_input_device_set_stage (event->motion.device, stage);
|
||||||
|
|
||||||
stage_win32->tracking_mouse = TRUE;
|
stage_win32->tracking_mouse = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -520,6 +530,10 @@ message_translate (ClutterBackend *backend,
|
|||||||
event->crossing.time = msg->time;
|
event->crossing.time = msg->time;
|
||||||
event->crossing.x = msg->pt.x;
|
event->crossing.x = msg->pt.x;
|
||||||
event->crossing.y = msg->pt.y;
|
event->crossing.y = msg->pt.y;
|
||||||
|
event->crossing.device = backend_win32->core_pointer;
|
||||||
|
|
||||||
|
/* we left the stage */
|
||||||
|
_clutter_input_device_set_stage (event->crossing.device, NULL);
|
||||||
|
|
||||||
/* When we get a leave message the mouse tracking is
|
/* When we get a leave message the mouse tracking is
|
||||||
automatically cancelled so we'll need to start it again when
|
automatically cancelled so we'll need to start it again when
|
||||||
@ -604,6 +618,7 @@ message_translate (ClutterBackend *backend,
|
|||||||
event->key.time = msg->time;
|
event->key.time = msg->time;
|
||||||
event->key.modifier_state = get_key_modifier_state (key_states);
|
event->key.modifier_state = get_key_modifier_state (key_states);
|
||||||
event->key.hardware_keycode = scan_code;
|
event->key.hardware_keycode = scan_code;
|
||||||
|
event->key.device = backend_win32->core_keyboard;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -616,6 +631,20 @@ message_translate (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
/* ignore every other message */
|
/* ignore every other message */
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
|
@ -216,17 +216,51 @@ clutter_stage_win32_set_title (ClutterStageWindow *stage_window,
|
|||||||
SetWindowTextW (stage_win32->hwnd, stage_win32->wtitle);
|
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
|
static void
|
||||||
clutter_stage_win32_set_cursor_visible (ClutterStageWindow *stage_window,
|
clutter_stage_win32_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||||
gboolean cursor_visible)
|
gboolean cursor_visible)
|
||||||
{
|
{
|
||||||
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
|
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
|
||||||
|
|
||||||
if (stage_win32->is_cursor_visible != cursor_visible &&
|
if (stage_win32->is_cursor_visible != cursor_visible)
|
||||||
stage_win32->tracking_mouse)
|
{
|
||||||
ShowCursor (cursor_visible);
|
POINT cursor_pos;
|
||||||
|
RECT client_rect;
|
||||||
|
|
||||||
stage_win32->is_cursor_visible = cursor_visible;
|
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
|
static LONG
|
||||||
@ -442,7 +476,7 @@ clutter_stage_win32_realize (ClutterStageWindow *stage_window)
|
|||||||
win_xpos = stage_win32->fullscreen_rect.left;
|
win_xpos = stage_win32->fullscreen_rect.left;
|
||||||
win_ypos = stage_win32->fullscreen_rect.top;
|
win_ypos = stage_win32->fullscreen_rect.top;
|
||||||
win_width = stage_win32->fullscreen_rect.right - win_xpos;
|
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
|
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,
|
void _clutter_stage_win32_get_min_max_info (ClutterStageWin32 *stage_win32,
|
||||||
MINMAXINFO *min_max_info);
|
MINMAXINFO *min_max_info);
|
||||||
|
|
||||||
|
void _clutter_stage_win32_update_cursor (ClutterStageWin32 *stage_win32);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_STAGE_H__ */
|
#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.h \
|
||||||
clutter-backend-x11.c \
|
clutter-backend-x11.c \
|
||||||
clutter-event-x11.c \
|
clutter-event-x11.c \
|
||||||
|
clutter-input-device-x11.h \
|
||||||
|
clutter-input-device-x11.c \
|
||||||
clutter-stage-x11.h \
|
clutter-stage-x11.h \
|
||||||
clutter-stage-x11.c \
|
clutter-stage-x11.c \
|
||||||
clutter-x11-enum-types.h \
|
clutter-x11-enum-types.h \
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "clutter-backend-x11.h"
|
#include "clutter-backend-x11.h"
|
||||||
|
#include "clutter-input-device-x11.h"
|
||||||
#include "clutter-stage-x11.h"
|
#include "clutter-stage-x11.h"
|
||||||
#include "clutter-x11.h"
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
@ -46,31 +47,16 @@
|
|||||||
#include <X11/extensions/XInput.h>
|
#include <X11/extensions/XInput.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../clutter-event.h"
|
|
||||||
#include "../clutter-main.h"
|
|
||||||
#include "../clutter-debug.h"
|
|
||||||
#include "../clutter-private.h"
|
|
||||||
|
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
|
|
||||||
|
#include "../clutter-debug.h"
|
||||||
|
#include "../clutter-device-manager.h"
|
||||||
|
#include "../clutter-event.h"
|
||||||
|
#include "../clutter-main.h"
|
||||||
|
#include "../clutter-private.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
|
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
|
||||||
|
|
||||||
struct _ClutterX11XInputDevice
|
|
||||||
{
|
|
||||||
ClutterInputDevice device;
|
|
||||||
|
|
||||||
#ifdef HAVE_XINPUT
|
|
||||||
XDevice *xdevice;
|
|
||||||
XEventClass xevent_list[5]; /* MAX 5 event types */
|
|
||||||
int num_events;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef HAVE_XINPUT
|
|
||||||
void _clutter_x11_register_xinput ();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* atoms; remember to add the code that assigns the atom value to
|
/* atoms; remember to add the code that assigns the atom value to
|
||||||
* the member of the ClutterBackendX11 structure if you add an
|
* the member of the ClutterBackendX11 structure if you add an
|
||||||
* atom name here. do not change the order!
|
* atom name here. do not change the order!
|
||||||
@ -109,6 +95,129 @@ static gboolean clutter_synchronise = FALSE;
|
|||||||
static int TrappedErrorCode = 0;
|
static int TrappedErrorCode = 0;
|
||||||
static int (* old_error_handler) (Display *, XErrorEvent *);
|
static int (* old_error_handler) (Display *, XErrorEvent *);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_x11_register_input_devices (ClutterBackendX11 *backend)
|
||||||
|
{
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
XDeviceInfo *x_devices = NULL;
|
||||||
|
int res, opcode, event, error;
|
||||||
|
int i, n_devices;
|
||||||
|
#endif /* HAVE_XINPUT */
|
||||||
|
|
||||||
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
|
if (!clutter_enable_xinput)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "XInput support not enabled");
|
||||||
|
goto default_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
res = XQueryExtension (backend->xdpy, "XInputExtension",
|
||||||
|
&opcode,
|
||||||
|
&event,
|
||||||
|
&error);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "No XInput extension available");
|
||||||
|
goto default_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->xi_event_base = event;
|
||||||
|
|
||||||
|
x_devices = XListInputDevices (backend->xdpy, &n_devices);
|
||||||
|
if (n_devices == 0)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "No XInput devices found");
|
||||||
|
goto default_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n_devices; i++)
|
||||||
|
{
|
||||||
|
XDeviceInfo *info = x_devices + i;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND,
|
||||||
|
"Considering device %li with type %d, %d of %d",
|
||||||
|
info->id,
|
||||||
|
info->use,
|
||||||
|
i, n_devices);
|
||||||
|
|
||||||
|
/* we only want 'raw' devices, not virtual ones */
|
||||||
|
if (info->use == IsXExtensionPointer ||
|
||||||
|
/* info->use == IsXExtensionKeyboard || XInput1 is broken */
|
||||||
|
info->use == IsXExtensionDevice)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceType device_type;
|
||||||
|
gint n_events = 0;
|
||||||
|
|
||||||
|
switch (info->use)
|
||||||
|
{
|
||||||
|
case IsXExtensionPointer:
|
||||||
|
device_type = CLUTTER_POINTER_DEVICE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* XInput1 is broken for keyboards */
|
||||||
|
case IsXExtensionKeyboard:
|
||||||
|
device_type = CLUTTER_KEYBOARD_DEVICE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IsXExtensionDevice:
|
||||||
|
device_type = CLUTTER_EXTENSION_DEVICE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
|
||||||
|
"id", info->id,
|
||||||
|
"device-type", device_type,
|
||||||
|
"name", info->name,
|
||||||
|
NULL);
|
||||||
|
n_events = _clutter_input_device_x11_construct (device, backend);
|
||||||
|
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
|
||||||
|
if (info->use == IsXExtensionPointer && n_events > 0)
|
||||||
|
backend->have_xinput = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree (x_devices);
|
||||||
|
#endif /* HAVE_XINPUT */
|
||||||
|
|
||||||
|
default_device:
|
||||||
|
/* fallback code in case:
|
||||||
|
*
|
||||||
|
* - we do not have XInput support compiled in
|
||||||
|
* - we do not have XInput support enabled
|
||||||
|
* - we do not have the XInput extension
|
||||||
|
*
|
||||||
|
* we register two default devices, one for the pointer
|
||||||
|
* and one for the keyboard. this block must also be
|
||||||
|
* executed for the XInput support because XI does not
|
||||||
|
* cover core devices
|
||||||
|
*/
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
|
||||||
|
"id", 0,
|
||||||
|
"name", "Core Pointer",
|
||||||
|
"device-type", CLUTTER_POINTER_DEVICE,
|
||||||
|
"is-core", TRUE,
|
||||||
|
NULL);
|
||||||
|
CLUTTER_NOTE (BACKEND, "Added core pointer device");
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
backend->core_pointer = device;
|
||||||
|
|
||||||
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
|
||||||
|
"id", 1,
|
||||||
|
"name", "Core Keyboard",
|
||||||
|
"device-type", CLUTTER_KEYBOARD_DEVICE,
|
||||||
|
"is-core", TRUE,
|
||||||
|
NULL);
|
||||||
|
CLUTTER_NOTE (BACKEND, "Added core keyboard device");
|
||||||
|
_clutter_device_manager_add_device (manager, device);
|
||||||
|
backend->core_keyboard = device;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
clutter_backend_x11_pre_parse (ClutterBackend *backend,
|
clutter_backend_x11_pre_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -199,9 +308,8 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
|
|||||||
|
|
||||||
clutter_backend_set_resolution (backend, dpi);
|
clutter_backend_set_resolution (backend, dpi);
|
||||||
|
|
||||||
#ifdef HAVE_XINPUT
|
/* register input devices */
|
||||||
_clutter_x11_register_xinput ();
|
clutter_x11_register_input_devices (backend_x11);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (clutter_synchronise)
|
if (clutter_synchronise)
|
||||||
XSynchronize (backend_x11->xdpy, True);
|
XSynchronize (backend_x11->xdpy, True);
|
||||||
@ -644,239 +752,29 @@ clutter_x11_remove_filter (ClutterX11FilterFunc func,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_x11_register_xinput ()
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XINPUT
|
|
||||||
XDeviceInfo *xdevices = NULL;
|
|
||||||
XDeviceInfo *info = NULL;
|
|
||||||
|
|
||||||
XDevice *xdevice = NULL;
|
|
||||||
|
|
||||||
XInputClassInfo *xclass_info = NULL;
|
|
||||||
|
|
||||||
gint opcode, event, error;
|
|
||||||
gint res;
|
|
||||||
gint num_devices = 0;
|
|
||||||
gint num_events = 0;
|
|
||||||
gint i = 0, j = 0;
|
|
||||||
gboolean have_an_xpointer = FALSE;
|
|
||||||
|
|
||||||
ClutterBackendX11 *x11b;
|
|
||||||
ClutterX11XInputDevice *device = NULL;
|
|
||||||
|
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
GSList *input_devices = NULL;
|
|
||||||
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
|
||||||
g_critical ("X11 backend has not been initialised");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!clutter_enable_xinput)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (BACKEND, "Not enabling XInput");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
|
|
||||||
backend_singleton->have_xinput = FALSE;
|
|
||||||
|
|
||||||
/* is the XInput extension available? */
|
|
||||||
res = XQueryExtension (backend_singleton->xdpy, "XInputExtension",
|
|
||||||
&opcode, &event,
|
|
||||||
&error);
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (BACKEND, "X Input extension not available");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
x11b = backend_singleton;
|
|
||||||
|
|
||||||
xdevices = XListInputDevices (x11b->xdpy, &num_devices);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "%d XINPUT devices found", num_devices);
|
|
||||||
|
|
||||||
if (num_devices == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < num_devices; i++)
|
|
||||||
{
|
|
||||||
info = xdevices + i;
|
|
||||||
num_events = 0;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Considering %li with type %d",
|
|
||||||
info->id,
|
|
||||||
info->use);
|
|
||||||
|
|
||||||
/* Only want 'raw' devices themselves not virtual ones */
|
|
||||||
if (info->use == IsXExtensionPointer ||
|
|
||||||
/*info->use == IsXExtensionKeyboard || XInput 1.x is broken */
|
|
||||||
info->use == IsXExtensionDevice)
|
|
||||||
{
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
xdevice = XOpenDevice (backend_singleton->xdpy, info->id);
|
|
||||||
if (clutter_x11_untrap_x_errors () || xdevice == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Create the appropriate Clutter device */
|
|
||||||
device = g_slice_new0 (ClutterX11XInputDevice);
|
|
||||||
|
|
||||||
device->device.id = info->id;
|
|
||||||
|
|
||||||
switch (info->use)
|
|
||||||
{
|
|
||||||
case IsXExtensionPointer:
|
|
||||||
device->device.device_type = CLUTTER_POINTER_DEVICE;
|
|
||||||
have_an_xpointer = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* XInput 1.x is broken for keyboards: */
|
|
||||||
case IsXExtensionKeyboard:
|
|
||||||
device->device.type = CLUTTER_KEYBOARD_DEVICE;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case IsXExtensionDevice:
|
|
||||||
device->device.device_type = CLUTTER_EXTENSION_DEVICE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: some kind of general device_init() call should do below */
|
|
||||||
device->device.click_count = 0;
|
|
||||||
device->device.previous_time = 0;
|
|
||||||
device->device.previous_x = -1;
|
|
||||||
device->device.previous_y = -1;
|
|
||||||
device->device.previous_button_number = -1;
|
|
||||||
|
|
||||||
device->num_events = 0;
|
|
||||||
device->xdevice = xdevice;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Registering XINPUT device with XID: %li",
|
|
||||||
xdevice->device_id);
|
|
||||||
|
|
||||||
/* We must go through all the classes supported by this device and
|
|
||||||
* register the appropriate events we want. Each class only appears
|
|
||||||
* once. We need to store the types with the stage since they are
|
|
||||||
* created dynamically by the server. They are not device specific.
|
|
||||||
*/
|
|
||||||
for (j = 0; j < xdevice->num_classes; j++)
|
|
||||||
{
|
|
||||||
xclass_info = xdevice->classes + j;
|
|
||||||
|
|
||||||
switch (xclass_info->input_class)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
/* XInput 1.x is broken for keyboards: */
|
|
||||||
case KeyClass:
|
|
||||||
DeviceKeyPress (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
|
|
||||||
DeviceKeyRelease (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case ButtonClass:
|
|
||||||
DeviceButtonPress (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
|
|
||||||
DeviceButtonRelease (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ValuatorClass:
|
|
||||||
DeviceMotionNotify (xdevice,
|
|
||||||
x11b->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT],
|
|
||||||
device->xevent_list [num_events]);
|
|
||||||
num_events++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->use == IsXExtensionPointer && num_events > 0)
|
|
||||||
have_an_xpointer = TRUE;
|
|
||||||
|
|
||||||
device->num_events = num_events;
|
|
||||||
|
|
||||||
input_devices = g_slist_prepend (input_devices, device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree (xdevices);
|
|
||||||
|
|
||||||
if (!have_an_xpointer)
|
|
||||||
{
|
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
/* Something is likely wrong with Xinput setup so we basically
|
|
||||||
* abort here and fall back to lofi regular xinput.
|
|
||||||
*/
|
|
||||||
g_warning ("No usuable XInput pointing devices found");
|
|
||||||
|
|
||||||
for (l = input_devices; l != NULL; l = l->next)
|
|
||||||
g_slice_free (ClutterX11XInputDevice, l->data);
|
|
||||||
|
|
||||||
g_slist_free (input_devices);
|
|
||||||
context->input_devices = NULL;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store the list of input devices */
|
|
||||||
context->input_devices = g_slist_reverse (input_devices);
|
|
||||||
|
|
||||||
/* why yes, we are awesome */
|
|
||||||
backend_singleton->have_xinput = TRUE;
|
|
||||||
#endif /* HAVE_XINPUT */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_x11_unregister_xinput ()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_clutter_x11_select_events (Window xwin)
|
_clutter_x11_select_events (Window xwin)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XINPUT
|
#ifdef HAVE_XINPUT
|
||||||
GSList *list_it;
|
ClutterDeviceManager *manager;
|
||||||
ClutterX11XInputDevice *device = NULL;
|
const GSList *l;
|
||||||
|
|
||||||
ClutterMainContext *context;
|
if (G_UNLIKELY (backend_singleton == NULL))
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
{
|
||||||
g_critical ("X11 backend has not been initialised");
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (list_it = context->input_devices;
|
manager = clutter_device_manager_get_default ();
|
||||||
list_it != NULL;
|
|
||||||
list_it = list_it->next)
|
|
||||||
{
|
|
||||||
device = (ClutterX11XInputDevice *)list_it->data;
|
|
||||||
|
|
||||||
XSelectExtensionEvent (backend_singleton->xdpy,
|
for (l = clutter_device_manager_peek_devices (manager);
|
||||||
xwin,
|
l != NULL;
|
||||||
device->xevent_list,
|
l = l->next)
|
||||||
device->num_events);
|
{
|
||||||
|
ClutterInputDevice *device = l->data;
|
||||||
|
|
||||||
|
_clutter_input_device_x11_select_events (device, backend_singleton, xwin);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_XINPUT */
|
#endif /* HAVE_XINPUT */
|
||||||
}
|
}
|
||||||
@ -884,49 +782,34 @@ _clutter_x11_select_events (Window xwin)
|
|||||||
ClutterInputDevice *
|
ClutterInputDevice *
|
||||||
_clutter_x11_get_device_for_xid (XID id)
|
_clutter_x11_get_device_for_xid (XID id)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XINPUT
|
ClutterDeviceManager *manager;
|
||||||
ClutterMainContext *context;
|
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
if (!backend_singleton)
|
return clutter_device_manager_get_device (manager, (gint) id);
|
||||||
{
|
|
||||||
g_critical ("X11 backend has not been initialised");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (l = context->input_devices; l != NULL; l = l->next)
|
|
||||||
{
|
|
||||||
ClutterX11XInputDevice *device = l->data;
|
|
||||||
|
|
||||||
if (device->xdevice->device_id == id)
|
|
||||||
return (ClutterInputDevice *) device;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_XINPUT */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: This nasty little func needs moving elsewhere.. */
|
/**
|
||||||
|
* clutter_x11_get_input_devices:
|
||||||
|
*
|
||||||
|
* Retrieves a pointer to the list of input devices
|
||||||
|
*
|
||||||
|
* Deprecated: 1.2: Use clutter_device_manager_peek_devices() instead
|
||||||
|
*
|
||||||
|
* Since: 0.8
|
||||||
|
*
|
||||||
|
* Return value: a pointer to the internal list of input devices; the
|
||||||
|
* returned list is owned by Clutter and should not be modified or
|
||||||
|
* freed
|
||||||
|
*/
|
||||||
G_CONST_RETURN GSList *
|
G_CONST_RETURN GSList *
|
||||||
clutter_x11_get_input_devices (void)
|
clutter_x11_get_input_devices (void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XINPUT
|
ClutterDeviceManager *manager;
|
||||||
ClutterMainContext *context;
|
|
||||||
|
|
||||||
if (!backend_singleton)
|
manager = clutter_device_manager_get_default ();
|
||||||
{
|
|
||||||
g_critical ("X11 backend has not been initialised");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
return clutter_device_manager_peek_devices (manager);
|
||||||
|
|
||||||
return context->input_devices;
|
|
||||||
#else /* !HAVE_XINPUT */
|
|
||||||
return NULL;
|
|
||||||
#endif /* HAVE_XINPUT */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -943,7 +826,7 @@ gboolean
|
|||||||
clutter_x11_has_xinput (void)
|
clutter_x11_has_xinput (void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XINPUT
|
#ifdef HAVE_XINPUT
|
||||||
if (!backend_singleton)
|
if (backend_singleton == NULL)
|
||||||
{
|
{
|
||||||
g_critical ("X11 backend has not been initialised");
|
g_critical ("X11 backend has not been initialised");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -76,10 +76,14 @@ struct _ClutterBackendX11
|
|||||||
Atom atom_NET_WM_NAME;
|
Atom atom_NET_WM_NAME;
|
||||||
Atom atom_UTF8_STRING;
|
Atom atom_UTF8_STRING;
|
||||||
|
|
||||||
|
int xi_event_base;
|
||||||
int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
|
int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
|
||||||
gboolean have_xinput;
|
gboolean have_xinput;
|
||||||
|
|
||||||
Time last_event_time;
|
Time last_event_time;
|
||||||
|
|
||||||
|
ClutterInputDevice *core_pointer;
|
||||||
|
ClutterInputDevice *core_keyboard;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendX11Class
|
struct _ClutterBackendX11Class
|
||||||
@ -125,12 +129,6 @@ clutter_backend_x11_get_features (ClutterBackend *backend);
|
|||||||
XVisualInfo *
|
XVisualInfo *
|
||||||
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11);
|
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11);
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_x11_register_xinput (void);
|
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_x11_unregister_xinput (void);
|
|
||||||
|
|
||||||
ClutterInputDevice *
|
ClutterInputDevice *
|
||||||
_clutter_x11_get_device_for_xid (XID id);
|
_clutter_x11_get_device_for_xid (XID id);
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
/* Clutter.
|
/* Clutter.
|
||||||
* An OpenGL based 'interactive canvas' library.
|
* An OpenGL based 'interactive canvas' library.
|
||||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
*
|
||||||
* Copyright (C) 2006-2007 OpenedHand
|
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd
|
||||||
|
* Copyright (C) 2009, 2010 Intel Corp.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -17,6 +18,10 @@
|
|||||||
* License along with this library; if not, write to the
|
* License along with this library; if not, write to the
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authored by:
|
||||||
|
* Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -183,7 +188,6 @@ _clutter_backend_x11_events_init (ClutterBackend *backend)
|
|||||||
g_source_add_poll (source, &event_source->event_poll_fd);
|
g_source_add_poll (source, &event_source->event_poll_fd);
|
||||||
g_source_set_can_recurse (source, TRUE);
|
g_source_set_can_recurse (source, TRUE);
|
||||||
g_source_attach (source, NULL);
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -263,9 +267,10 @@ set_user_time (ClutterBackendX11 *backend_x11,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* See XInput keyboard comment below HAVE_XINPUT */
|
#ifdef HAVE_XINPUT
|
||||||
static void
|
static void
|
||||||
convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev, XEvent *xevent)
|
convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev,
|
||||||
|
XEvent *xevent)
|
||||||
{
|
{
|
||||||
xevent->xany.type = xevent->xkey.type = xkev->type;
|
xevent->xany.type = xevent->xkey.type = xkev->type;
|
||||||
xevent->xkey.serial = xkev->serial;
|
xevent->xkey.serial = xkev->serial;
|
||||||
@ -416,6 +421,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
ClutterStageWindow *impl;
|
ClutterStageWindow *impl;
|
||||||
gboolean res, not_yet_handled = FALSE;
|
gboolean res, not_yet_handled = FALSE;
|
||||||
Window xwindow, stage_xwindow;
|
Window xwindow, stage_xwindow;
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
@ -424,13 +431,12 @@ event_translate (ClutterBackend *backend,
|
|||||||
if (backend_x11->event_filters)
|
if (backend_x11->event_filters)
|
||||||
{
|
{
|
||||||
GSList *node;
|
GSList *node;
|
||||||
ClutterX11EventFilter *filter;
|
|
||||||
|
|
||||||
node = backend_x11->event_filters;
|
node = backend_x11->event_filters;
|
||||||
|
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
filter = node->data;
|
ClutterX11EventFilter *filter = node->data;
|
||||||
|
|
||||||
switch (filter->func (xevent, event, filter->data))
|
switch (filter->func (xevent, event, filter->data))
|
||||||
{
|
{
|
||||||
@ -448,16 +454,16 @@ event_translate (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Do further processing only on events for the stage window (the x11
|
||||||
* Do further processing only on events for the stage window
|
* filters might be getting events for other windows, so do not mess
|
||||||
* (the x11 filters might be getting events for other windows, so do not
|
* them about.
|
||||||
* mess them about.
|
|
||||||
*/
|
*/
|
||||||
stage = clutter_x11_get_stage_from_window (xwindow);
|
stage = clutter_x11_get_stage_from_window (xwindow);
|
||||||
|
|
||||||
if (stage == NULL)
|
if (stage == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
manager = clutter_device_manager_get_default ();
|
||||||
|
|
||||||
impl = _clutter_stage_get_window (stage);
|
impl = _clutter_stage_get_window (stage);
|
||||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||||
stage_xwindow = xwindow; /* clutter_x11_get_stage_window (stage); */
|
stage_xwindow = xwindow; /* clutter_x11_get_stage_window (stage); */
|
||||||
@ -621,6 +627,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
|
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
event->key.type = event->type = CLUTTER_KEY_PRESS;
|
event->key.type = event->type = CLUTTER_KEY_PRESS;
|
||||||
|
event->key.device = backend_x11->core_keyboard;
|
||||||
|
|
||||||
translate_key_event (backend, event, xevent);
|
translate_key_event (backend, event, xevent);
|
||||||
|
|
||||||
set_user_time (backend_x11, &xwindow, xevent->xkey.time);
|
set_user_time (backend_x11, &xwindow, xevent->xkey.time);
|
||||||
@ -654,6 +662,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
event->key.type = event->type = CLUTTER_KEY_RELEASE;
|
event->key.type = event->type = CLUTTER_KEY_RELEASE;
|
||||||
|
event->key.device = backend_x11->core_keyboard;
|
||||||
|
|
||||||
translate_key_event (backend, event, xevent);
|
translate_key_event (backend, event, xevent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -666,14 +676,11 @@ event_translate (ClutterBackend *backend,
|
|||||||
/* Input device event handling.. */
|
/* Input device event handling.. */
|
||||||
if (not_yet_handled)
|
if (not_yet_handled)
|
||||||
{
|
{
|
||||||
if (!clutter_x11_has_xinput ())
|
device = backend_x11->core_pointer;
|
||||||
{
|
|
||||||
/* Regular X event */
|
/* Regular X event */
|
||||||
switch (xevent->type)
|
switch (xevent->type)
|
||||||
{
|
{
|
||||||
/* KeyPress / KeyRelease should reside here if XInput
|
|
||||||
* worked properly
|
|
||||||
*/
|
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
switch (xevent->xbutton.button)
|
switch (xevent->xbutton.button)
|
||||||
{
|
{
|
||||||
@ -696,8 +703,9 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->scroll.x = xevent->xbutton.x;
|
event->scroll.x = xevent->xbutton.x;
|
||||||
event->scroll.y = xevent->xbutton.y;
|
event->scroll.y = xevent->xbutton.y;
|
||||||
event->scroll.modifier_state = xevent->xbutton.state;
|
event->scroll.modifier_state = xevent->xbutton.state;
|
||||||
|
event->scroll.device = device;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
event->button.type = event->type = CLUTTER_BUTTON_PRESS;
|
event->button.type = event->type = CLUTTER_BUTTON_PRESS;
|
||||||
event->button.time = xevent->xbutton.time;
|
event->button.time = xevent->xbutton.time;
|
||||||
@ -705,11 +713,13 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->button.y = xevent->xbutton.y;
|
event->button.y = xevent->xbutton.y;
|
||||||
event->button.modifier_state = xevent->xbutton.state;
|
event->button.modifier_state = xevent->xbutton.state;
|
||||||
event->button.button = xevent->xbutton.button;
|
event->button.button = xevent->xbutton.button;
|
||||||
|
event->button.device = device;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_user_time (backend_x11, &xwindow, event->button.time);
|
set_user_time (backend_x11, &xwindow, event->button.time);
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
@ -720,7 +730,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
xevent->xbutton.button == 7)
|
xevent->xbutton.button == 7)
|
||||||
{
|
{
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
||||||
@ -729,6 +739,9 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->button.y = xevent->xbutton.y;
|
event->button.y = xevent->xbutton.y;
|
||||||
event->button.modifier_state = xevent->xbutton.state;
|
event->button.modifier_state = xevent->xbutton.state;
|
||||||
event->button.button = xevent->xbutton.button;
|
event->button.button = xevent->xbutton.button;
|
||||||
|
event->button.device = device;
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MotionNotify:
|
case MotionNotify:
|
||||||
@ -737,9 +750,16 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->motion.x = xevent->xmotion.x;
|
event->motion.x = xevent->xmotion.x;
|
||||||
event->motion.y = xevent->xmotion.y;
|
event->motion.y = xevent->xmotion.y;
|
||||||
event->motion.modifier_state = xevent->xmotion.state;
|
event->motion.modifier_state = xevent->xmotion.state;
|
||||||
|
event->motion.device = device;
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EnterNotify:
|
case EnterNotify:
|
||||||
|
/* we know that we are entering the stage here */
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
CLUTTER_NOTE (EVENT, "Entering the stage");
|
||||||
|
|
||||||
/* Convert enter notifies to motion events because X
|
/* Convert enter notifies to motion events because X
|
||||||
doesn't emit the corresponding motion notify */
|
doesn't emit the corresponding motion notify */
|
||||||
event->motion.type = event->type = CLUTTER_MOTION;
|
event->motion.type = event->type = CLUTTER_MOTION;
|
||||||
@ -747,34 +767,70 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->motion.x = xevent->xcrossing.x;
|
event->motion.x = xevent->xcrossing.x;
|
||||||
event->motion.y = xevent->xcrossing.y;
|
event->motion.y = xevent->xcrossing.y;
|
||||||
event->motion.modifier_state = xevent->xcrossing.state;
|
event->motion.modifier_state = xevent->xcrossing.state;
|
||||||
|
event->motion.source = CLUTTER_ACTOR (stage);
|
||||||
|
event->motion.device = device;
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LeaveNotify:
|
case LeaveNotify:
|
||||||
|
if (device->stage == NULL)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"Discarding LeaveNotify for ButtonRelease "
|
||||||
|
"event off-stage");
|
||||||
|
res = FALSE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we know that we are leaving the stage here */
|
||||||
|
_clutter_input_device_set_stage (device, NULL);
|
||||||
|
CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)",
|
||||||
|
event->crossing.time);
|
||||||
|
|
||||||
event->crossing.type = event->type = CLUTTER_LEAVE;
|
event->crossing.type = event->type = CLUTTER_LEAVE;
|
||||||
event->crossing.time = xevent->xcrossing.time;
|
event->crossing.time = xevent->xcrossing.time;
|
||||||
event->crossing.x = xevent->xcrossing.x;
|
event->crossing.x = xevent->xcrossing.x;
|
||||||
event->crossing.y = xevent->xcrossing.y;
|
event->crossing.y = xevent->xcrossing.y;
|
||||||
|
event->crossing.source = CLUTTER_ACTOR (stage);
|
||||||
|
event->crossing.device = device;
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* ignore every other event */
|
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{ /* XInput fun.. Needs clean up. */
|
/* XInput fun...*/
|
||||||
|
if (!res && clutter_x11_has_xinput ())
|
||||||
|
{
|
||||||
#ifdef HAVE_XINPUT
|
#ifdef HAVE_XINPUT
|
||||||
int *ev_types = backend_x11->event_types;
|
int *ev_types = backend_x11->event_types;
|
||||||
|
int button_press, button_release;
|
||||||
|
int key_press, key_release;
|
||||||
|
int motion_notify;
|
||||||
|
|
||||||
|
button_press = ev_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
|
||||||
|
button_release = ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
|
||||||
|
motion_notify = ev_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT];
|
||||||
|
key_press = ev_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT];
|
||||||
|
key_release = ev_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT];
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type);
|
CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type);
|
||||||
|
|
||||||
if (xevent->type == ev_types [CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT])
|
if (xevent->type == button_press)
|
||||||
{
|
{
|
||||||
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent;
|
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent;
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "XINPUT Button press event for %li at %d, %d",
|
device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"XI ButtonPress for %li ('%s') at %d, %d",
|
||||||
xbev->deviceid,
|
xbev->deviceid,
|
||||||
|
device->device_name,
|
||||||
xbev->x,
|
xbev->x,
|
||||||
xbev->y);
|
xbev->y);
|
||||||
|
|
||||||
@ -799,7 +855,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->scroll.x = xbev->x;
|
event->scroll.x = xbev->x;
|
||||||
event->scroll.y = xbev->y;
|
event->scroll.y = xbev->y;
|
||||||
event->scroll.modifier_state = xbev->state;
|
event->scroll.modifier_state = xbev->state;
|
||||||
event->scroll.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
event->scroll.device = device;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -809,19 +865,24 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->button.y = xbev->y;
|
event->button.y = xbev->y;
|
||||||
event->button.modifier_state = xbev->state;
|
event->button.modifier_state = xbev->state;
|
||||||
event->button.button = xbev->button;
|
event->button.button = xbev->button;
|
||||||
event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
event->button.device = device;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_user_time (backend_x11, &xwindow, xbev->time);
|
set_user_time (backend_x11, &xwindow, xbev->time);
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
}
|
}
|
||||||
else if (xevent->type
|
else if (xevent->type == button_release)
|
||||||
== ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT])
|
|
||||||
{
|
{
|
||||||
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
|
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "XINPUT Button release event for %li at %d, %d",
|
device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT, "XI ButtonRelease for %li ('%s') at %d, %d",
|
||||||
xbev->deviceid,
|
xbev->deviceid,
|
||||||
|
device->device_name,
|
||||||
xbev->x,
|
xbev->x,
|
||||||
xbev->y);
|
xbev->y);
|
||||||
|
|
||||||
@ -831,7 +892,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
xbev->button == 6 ||
|
xbev->button == 6 ||
|
||||||
xbev->button == 7)
|
xbev->button == 7)
|
||||||
{
|
{
|
||||||
return FALSE;
|
res = FALSE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
||||||
@ -840,15 +902,20 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->button.y = xbev->y;
|
event->button.y = xbev->y;
|
||||||
event->button.modifier_state = xbev->state;
|
event->button.modifier_state = xbev->state;
|
||||||
event->button.button = xbev->button;
|
event->button.button = xbev->button;
|
||||||
event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
|
event->button.device = device;
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
}
|
}
|
||||||
else if (xevent->type
|
else if (xevent->type == motion_notify)
|
||||||
== ev_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT])
|
|
||||||
{
|
{
|
||||||
XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
|
XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
|
||||||
|
|
||||||
CLUTTER_NOTE(EVENT, "XINPUT Motion event for %li at %d, %d",
|
device = _clutter_x11_get_device_for_xid (xmev->deviceid);
|
||||||
|
_clutter_input_device_set_stage (device, stage);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT, "XI Motion for %li ('%s') at %d, %d",
|
||||||
xmev->deviceid,
|
xmev->deviceid,
|
||||||
|
device->device_name,
|
||||||
xmev->x,
|
xmev->x,
|
||||||
xmev->y);
|
xmev->y);
|
||||||
|
|
||||||
@ -857,39 +924,30 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->motion.x = xmev->x;
|
event->motion.x = xmev->x;
|
||||||
event->motion.y = xmev->y;
|
event->motion.y = xmev->y;
|
||||||
event->motion.modifier_state = xmev->state;
|
event->motion.modifier_state = xmev->state;
|
||||||
event->motion.device = _clutter_x11_get_device_for_xid (xmev->deviceid);
|
event->motion.device = device;
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
/* the Xinput handling of key presses/releases disabled for now since
|
|
||||||
* it makes keyrepeat, and key presses and releases outside the window
|
|
||||||
* not generate events even when the window has focus
|
|
||||||
*/
|
|
||||||
|
|
||||||
else if (xevent->type
|
res = TRUE;
|
||||||
== ev_types [CLUTTER_X11_XINPUT_KEY_PRESS_EVENT])
|
}
|
||||||
|
else if (xevent->type == key_press || xevent->type == key_release)
|
||||||
{
|
{
|
||||||
|
/* the XInput 1.x handling of key presses/releases is broken:
|
||||||
|
* it makes key repeat, key presses and releases outside the
|
||||||
|
* window not generate events even when the window has focus
|
||||||
|
*/
|
||||||
|
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *) xevent;
|
||||||
XEvent xevent_converted;
|
XEvent xevent_converted;
|
||||||
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *)xevent;
|
|
||||||
|
|
||||||
convert_xdevicekey_to_xkey (xkev, &xevent_converted);
|
convert_xdevicekey_to_xkey (xkev, &xevent_converted);
|
||||||
|
|
||||||
event->key.type = event->type = CLUTTER_KEY_PRESS;
|
event->key.type = event->type = (xevent->type == key_press)
|
||||||
|
? CLUTTER_KEY_PRESS
|
||||||
|
: CLUTTER_KEY_RELEASE;
|
||||||
|
|
||||||
translate_key_event (backend, event, &xevent_converted);
|
translate_key_event (backend, event, &xevent_converted);
|
||||||
|
|
||||||
|
if (xevent->type == key_press)
|
||||||
set_user_time (backend_x11, &xwindow, xkev->time);
|
set_user_time (backend_x11, &xwindow, xkev->time);
|
||||||
}
|
}
|
||||||
else if (xevent->type
|
|
||||||
== ev_types [CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT])
|
|
||||||
{
|
|
||||||
XEvent xevent_converted;
|
|
||||||
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *)xevent;
|
|
||||||
|
|
||||||
convert_xdevicekey_to_xkey (xkev, &xevent_converted);
|
|
||||||
|
|
||||||
event->key.type = event->type = CLUTTER_KEY_RELEASE;
|
|
||||||
translate_key_event (backend, event, &xevent_converted);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
#endif /* HAVE_XINPUT */
|
#endif /* HAVE_XINPUT */
|
||||||
{
|
{
|
||||||
@ -897,8 +955,8 @@ event_translate (ClutterBackend *backend,
|
|||||||
res = FALSE;
|
res = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
out:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
221
clutter/x11/clutter-input-device-x11.c
Normal file
221
clutter/x11/clutter-input-device-x11.c
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-input-device-x11.h"
|
||||||
|
#include "../clutter-debug.h"
|
||||||
|
#include "../clutter-private.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
#include <X11/extensions/XInput.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _ClutterInputDeviceClass ClutterInputDeviceX11Class;
|
||||||
|
|
||||||
|
/* a specific X11 input device */
|
||||||
|
struct _ClutterInputDeviceX11
|
||||||
|
{
|
||||||
|
ClutterInputDevice device;
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
XDevice *xdevice;
|
||||||
|
XEventClass xevent_list[5]; /* MAX 5 event types */
|
||||||
|
int num_events;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
guint is_core : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_IS_CORE
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterInputDeviceX11,
|
||||||
|
clutter_input_device_x11,
|
||||||
|
CLUTTER_TYPE_INPUT_DEVICE);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_x11_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceX11 *self = CLUTTER_INPUT_DEVICE_X11 (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_IS_CORE:
|
||||||
|
self->is_core = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_x11_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceX11 *self = CLUTTER_INPUT_DEVICE_X11 (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_IS_CORE:
|
||||||
|
g_value_set_boolean (value, self->is_core);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_x11_class_init (ClutterInputDeviceX11Class *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
gobject_class->set_property = clutter_input_device_x11_set_property;
|
||||||
|
gobject_class->get_property = clutter_input_device_x11_get_property;
|
||||||
|
|
||||||
|
pspec = g_param_spec_boolean ("is-core",
|
||||||
|
"Is Core",
|
||||||
|
"Whether the device is a core one",
|
||||||
|
FALSE,
|
||||||
|
CLUTTER_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_IS_CORE, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_x11_init (ClutterInputDeviceX11 *self)
|
||||||
|
{
|
||||||
|
self->is_core = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
_clutter_input_device_x11_construct (ClutterInputDevice *device,
|
||||||
|
ClutterBackendX11 *backend)
|
||||||
|
{
|
||||||
|
int n_events = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
ClutterInputDeviceX11 *device_x11;
|
||||||
|
XDevice *x_device = NULL;
|
||||||
|
gint device_id;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
|
||||||
|
device_id = clutter_input_device_get_device_id (device);
|
||||||
|
|
||||||
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
|
/* retrieve the X11 device */
|
||||||
|
x_device = XOpenDevice (backend->xdpy, device_id);
|
||||||
|
|
||||||
|
if (clutter_x11_untrap_x_errors () || x_device == NULL)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "Unable to open device %i", device_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_x11->xdevice = x_device;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND,
|
||||||
|
"Registering XINPUT device with XID: %li",
|
||||||
|
x_device->device_id);
|
||||||
|
|
||||||
|
/* We must go through all the classes supported by this device and
|
||||||
|
* register the appropriate events we want. Each class only appears
|
||||||
|
* once. We need to store the types with the stage since they are
|
||||||
|
* created dynamically by the server. They are not device specific.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < x_device->num_classes; i++)
|
||||||
|
{
|
||||||
|
XInputClassInfo *xclass_info = x_device->classes + i;
|
||||||
|
int *button_press, *button_release, *motion_notify;
|
||||||
|
int *key_press, *key_release;
|
||||||
|
|
||||||
|
button_press =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
|
||||||
|
button_release =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
|
||||||
|
motion_notify =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT];
|
||||||
|
|
||||||
|
key_press =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT];
|
||||||
|
key_release =
|
||||||
|
&backend->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT];
|
||||||
|
|
||||||
|
switch (xclass_info->input_class)
|
||||||
|
{
|
||||||
|
/* event though XInput 1.x is broken for keyboard-like devices
|
||||||
|
* it might still be useful to track them down; the core keyboard
|
||||||
|
* will handle the right events anyway
|
||||||
|
*/
|
||||||
|
case KeyClass:
|
||||||
|
DeviceKeyPress (x_device,
|
||||||
|
*key_press,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
|
||||||
|
DeviceKeyRelease (x_device,
|
||||||
|
*key_release,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ButtonClass:
|
||||||
|
DeviceButtonPress (x_device,
|
||||||
|
*button_press,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
|
||||||
|
DeviceButtonRelease (x_device,
|
||||||
|
*button_release,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ValuatorClass:
|
||||||
|
DeviceMotionNotify (x_device,
|
||||||
|
*motion_notify,
|
||||||
|
device_x11->xevent_list[n_events]);
|
||||||
|
n_events++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device_x11->num_events = n_events;
|
||||||
|
#endif /* HAVE_XINPUT */
|
||||||
|
|
||||||
|
return n_events;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_input_device_x11_select_events (ClutterInputDevice *device,
|
||||||
|
ClutterBackendX11 *backend_x11,
|
||||||
|
Window xwin)
|
||||||
|
{
|
||||||
|
#if HAVE_XINPUT
|
||||||
|
ClutterInputDeviceX11 *device_x11;
|
||||||
|
|
||||||
|
device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
|
||||||
|
|
||||||
|
if (device_x11->xdevice == None || device_x11->num_events == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XSelectExtensionEvent (backend_x11->xdpy, xwin,
|
||||||
|
device_x11->xevent_list,
|
||||||
|
device_x11->num_events);
|
||||||
|
#endif /* HAVE_XINPUT */
|
||||||
|
}
|
25
clutter/x11/clutter-input-device-x11.h
Normal file
25
clutter/x11/clutter-input-device-x11.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef __CLUTTER_INPUT_DEVICE_X11_H__
|
||||||
|
#define __CLUTTER_INPUT_DEVICE_X11_H__
|
||||||
|
|
||||||
|
#include <clutter/clutter-input-device.h>
|
||||||
|
#include "clutter-backend-x11.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_INPUT_DEVICE_X11 (clutter_input_device_x11_get_type ())
|
||||||
|
#define CLUTTER_INPUT_DEVICE_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_X11, ClutterInputDeviceX11))
|
||||||
|
#define CLUTTER_IS_INPUT_DEVICE_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_X11))
|
||||||
|
|
||||||
|
typedef struct _ClutterInputDeviceX11 ClutterInputDeviceX11;
|
||||||
|
|
||||||
|
GType clutter_input_device_x11_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
gint _clutter_input_device_x11_construct (ClutterInputDevice *device,
|
||||||
|
ClutterBackendX11 *backend);
|
||||||
|
void _clutter_input_device_x11_select_events (ClutterInputDevice *device,
|
||||||
|
ClutterBackendX11 *backend,
|
||||||
|
Window xwin);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_INPUT_DEVICE_X11_H__ */
|
@ -121,14 +121,16 @@ gboolean clutter_x11_has_event_retrieval (void);
|
|||||||
|
|
||||||
ClutterStage *clutter_x11_get_stage_from_window (Window win);
|
ClutterStage *clutter_x11_get_stage_from_window (Window win);
|
||||||
|
|
||||||
|
#ifndef CLUTTER_DISABLE_DEPRECATED
|
||||||
G_CONST_RETURN GSList* clutter_x11_get_input_devices (void);
|
G_CONST_RETURN GSList* clutter_x11_get_input_devices (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
void clutter_x11_enable_xinput (void);
|
void clutter_x11_enable_xinput (void);
|
||||||
gboolean clutter_x11_has_xinput (void);
|
gboolean clutter_x11_has_xinput (void);
|
||||||
|
|
||||||
gboolean clutter_x11_has_composite_extension (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);
|
gboolean clutter_x11_get_use_argb_visual (void);
|
||||||
|
|
||||||
Time clutter_x11_get_current_event_time (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
|
# - increase clutter_interface_version to the next odd number
|
||||||
m4_define([clutter_major_version], [1])
|
m4_define([clutter_major_version], [1])
|
||||||
m4_define([clutter_minor_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_define([clutter_release_status],
|
||||||
[m4_if(m4_eval(clutter_micro_version % 2), [1], [git],
|
[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_AUX_DIR([build])
|
||||||
AC_CONFIG_MACRO_DIR([build/autotools])
|
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_MAJOR_VERSION=clutter_major_version
|
||||||
CLUTTER_MINOR_VERSION=clutter_minor_version
|
CLUTTER_MINOR_VERSION=clutter_minor_version
|
||||||
@ -364,11 +364,18 @@ AS_CASE([$CLUTTER_WINSYS],
|
|||||||
WIN32_CFLAGS="-D_WIN32_WINNT=0x0500"
|
WIN32_CFLAGS="-D_WIN32_WINNT=0x0500"
|
||||||
WIN32_LIBS="-lopengl32 -lgdi32 -lwinmm"
|
WIN32_LIBS="-lopengl32 -lgdi32 -lwinmm"
|
||||||
CLUTTER_LT_LDFLAGS="$CLUTTER_LT_LDFLAGS -no-undefined"
|
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])]
|
[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
|
# 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])])
|
AS_IF([test "x$clutter_gl_header" = "x"], [AC_MSG_ERROR([Internal error: no GL header set])])
|
||||||
AC_CHECK_HEADERS([$clutter_gl_header],
|
AC_CHECK_HEADERS([$clutter_gl_header],
|
||||||
@ -689,6 +696,18 @@ AS_CASE([$enable_cogl_debug],
|
|||||||
|
|
||||||
AC_SUBST(COGL_DEBUG_CFLAGS)
|
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])
|
m4_define([profile_default], [no])
|
||||||
AC_ARG_ENABLE(profile,
|
AC_ARG_ENABLE(profile,
|
||||||
AC_HELP_STRING([--enable-profile=@<:@no/yes@:>@],
|
AC_HELP_STRING([--enable-profile=@<:@no/yes@:>@],
|
||||||
@ -698,22 +717,27 @@ AC_ARG_ENABLE(profile,
|
|||||||
|
|
||||||
AS_CASE([$enable_profile],
|
AS_CASE([$enable_profile],
|
||||||
|
|
||||||
[yes], [
|
[yes],
|
||||||
if test "x$GCC" = "xyes"; then
|
[
|
||||||
|
AS_IF([test "x$GCC" = "xyes"],
|
||||||
|
[
|
||||||
PKG_CHECK_MODULES([PROFILE_DEP], [uprof-0.2])
|
PKG_CHECK_MODULES([PROFILE_DEP], [uprof-0.2])
|
||||||
CLUTTER_PROFILE_CFLAGS=" -DCLUTTER_ENABLE_PROFILE -DCOGL_ENABLE_PROFILE $PROFILE_DEP_CFLAGS"
|
CLUTTER_PROFILE_CFLAGS=" -DCLUTTER_ENABLE_PROFILE -DCOGL_ENABLE_PROFILE $PROFILE_DEP_CFLAGS"
|
||||||
CLUTTER_PROFILE_LDFLAGS=" $PROFILE_DEP_LIBS"
|
CLUTTER_PROFILE_LDFLAGS=" $PROFILE_DEP_LIBS"
|
||||||
if test "x$enable_debug" = "xyes"; then
|
|
||||||
CLUTTER_PROFILE_CFLAGS+=" -DUPROF_DEBUG"
|
AS_IF([test "x$enable_debug" = "xyes"], [CLUTTER_PROFILE_CFLAGS+=" -DUPROF_DEBUG"])
|
||||||
fi
|
|
||||||
else
|
|
||||||
AC_MSG_ERROR([--enable-profile is currently only supported if using GCC])
|
|
||||||
fi
|
|
||||||
],
|
],
|
||||||
[no], [
|
[
|
||||||
|
AC_MSG_ERROR([--enable-profile is currently only supported if using GCC])
|
||||||
|
])
|
||||||
|
],
|
||||||
|
|
||||||
|
[no],
|
||||||
|
[
|
||||||
CLUTTER_PROFILE_CFLAGS=""
|
CLUTTER_PROFILE_CFLAGS=""
|
||||||
CLUTTER_PROFILE_LDFLAGS=""
|
CLUTTER_PROFILE_LDFLAGS=""
|
||||||
],
|
],
|
||||||
|
|
||||||
[*], [AC_MSG_ERROR([Invalid value for --enable-profile])]
|
[*], [AC_MSG_ERROR([Invalid value for --enable-profile])]
|
||||||
)
|
)
|
||||||
AM_CONDITIONAL(PROFILE, test "x$enable_profile" != "xno")
|
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_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_CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage"
|
||||||
GCOV_LDFLAGS="-lgcov"
|
GCOV_LDFLAGS="-lgcov"
|
||||||
]
|
],
|
||||||
|
[AC_MSG_RESULT([no])]
|
||||||
)
|
)
|
||||||
|
|
||||||
AM_CONDITIONAL([GCOV_ENABLED], [test "x$enable_gcov" = "xyes"])
|
AM_CONDITIONAL([GCOV_ENABLED], [test "x$enable_gcov" = "xyes"])
|
||||||
AC_SUBST([GCOV_CFLAGS])
|
AC_SUBST([GCOV_CFLAGS])
|
||||||
AC_SUBST([GCOV_LDFLAGS])
|
AC_SUBST([GCOV_LDFLAGS])
|
||||||
AC_MSG_RESULT([$enable_gcov])
|
|
||||||
|
|
||||||
dnl === Enable strict compiler flags ==========================================
|
dnl === Enable strict compiler flags ==========================================
|
||||||
|
|
||||||
@ -868,6 +897,7 @@ AC_CONFIG_FILES([
|
|||||||
Makefile
|
Makefile
|
||||||
build/Makefile
|
build/Makefile
|
||||||
build/autotools/Makefile
|
build/autotools/Makefile
|
||||||
|
build/mingw/Makefile
|
||||||
clutter/Makefile
|
clutter/Makefile
|
||||||
clutter/clutter-version.h
|
clutter/clutter-version.h
|
||||||
clutter/clutter-json.h
|
clutter/clutter-json.h
|
||||||
@ -945,7 +975,7 @@ echo " Build Additional Documentation: ${enable_docs} (Generate PDF: ${en
|
|||||||
echo ""
|
echo ""
|
||||||
echo " • Extra:"
|
echo " • Extra:"
|
||||||
echo " Build introspection data: ${enable_introspection}"
|
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
|
if test "x$have_json" = "xyes"; then
|
||||||
echo " JSON-GLib: system"
|
echo " JSON-GLib: system"
|
||||||
|
@ -57,7 +57,7 @@ Short explanation of the commit
|
|||||||
Longer explanation explaining exactly what's changed, whether any
|
Longer explanation explaining exactly what's changed, whether any
|
||||||
external or private interfaces changed, what bugs were fixed (with bug
|
external or private interfaces changed, what bugs were fixed (with bug
|
||||||
tracker reference if applicable) and so forth. Be concise but not too
|
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 ===
|
=== end example commit ===
|
||||||
|
|
||||||
Always add a brief description of the commit to the _first_ line of
|
Always add a brief description of the commit to the _first_ line of
|
||||||
|
@ -68,6 +68,7 @@ IGNORE_HFILES=\
|
|||||||
clutter-debug.h \
|
clutter-debug.h \
|
||||||
clutter-deprecated.h \
|
clutter-deprecated.h \
|
||||||
clutter-enum-types.h \
|
clutter-enum-types.h \
|
||||||
|
clutter-id-pool.h \
|
||||||
clutter-json.h \
|
clutter-json.h \
|
||||||
clutter-keysyms.h \
|
clutter-keysyms.h \
|
||||||
clutter-keysyms-table.h \
|
clutter-keysyms-table.h \
|
||||||
@ -75,7 +76,7 @@ IGNORE_HFILES=\
|
|||||||
clutter-master-clock.h \
|
clutter-master-clock.h \
|
||||||
clutter-model-private.h \
|
clutter-model-private.h \
|
||||||
clutter-private.h \
|
clutter-private.h \
|
||||||
clutter-id-pool.h \
|
clutter-profile.h \
|
||||||
clutter-script-private.h \
|
clutter-script-private.h \
|
||||||
clutter-stage-window.h \
|
clutter-stage-window.h \
|
||||||
clutter-timeout-interval.h \
|
clutter-timeout-interval.h \
|
||||||
|
@ -298,13 +298,12 @@ main (int argc, char *argv[])
|
|||||||
ClutterBehaviour *behave;
|
ClutterBehaviour *behave;
|
||||||
ClutterAlpha *alpha;
|
ClutterAlpha *alpha;
|
||||||
ClutterActor *stage, *actor;
|
ClutterActor *stage, *actor;
|
||||||
GdkPixbuf *pixbuf;
|
|
||||||
|
|
||||||
clutter_init (&argc, &argv);
|
clutter_init (&argc, &argv);
|
||||||
|
|
||||||
stage = clutter_stage_get_default ();
|
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);
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
|
||||||
|
|
||||||
/* set up the animation to be 4 seconds long */
|
/* 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
|
* alpha will take a reference on the timeline so we can safely
|
||||||
* release the reference we hold
|
* 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);
|
g_object_unref (timeline);
|
||||||
|
|
||||||
/* the behaviour will own the alpha by sinking its floating
|
/* 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
|
position and a new set of coordinates. The animation takes 200
|
||||||
milliseconds to complete and uses a linear progression.</para>
|
milliseconds to complete and uses a linear progression.</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
clutter_actor_animate (actor, CLUTTER_LINEAR, 200
|
clutter_actor_animate (actor, CLUTTER_LINEAR, 200,
|
||||||
"x", 200,
|
"x", 200.0f,
|
||||||
"y", 200,
|
"y", 200.0f,
|
||||||
NULL);
|
NULL);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</example>
|
</example>
|
||||||
|
@ -139,8 +139,11 @@
|
|||||||
<xi:include href="xml/clutter-main.xml"/>
|
<xi:include href="xml/clutter-main.xml"/>
|
||||||
<xi:include href="xml/clutter-shader.xml"/>
|
<xi:include href="xml/clutter-shader.xml"/>
|
||||||
<xi:include href="xml/clutter-stage-manager.xml"/>
|
<xi:include href="xml/clutter-stage-manager.xml"/>
|
||||||
|
<xi:include href="xml/clutter-input-device.xml"/>
|
||||||
|
<xi:include href="xml/clutter-device-manager.xml"/>
|
||||||
<xi:include href="xml/clutter-units.xml"/>
|
<xi:include href="xml/clutter-units.xml"/>
|
||||||
<xi:include href="xml/clutter-util.xml"/>
|
<xi:include href="xml/clutter-util.xml"/>
|
||||||
|
<xi:include href="xml/clutter-feature.xml"/>
|
||||||
<xi:include href="xml/clutter-version.xml"/>
|
<xi:include href="xml/clutter-version.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
@ -404,6 +404,7 @@ clutter_actor_create_pango_layout
|
|||||||
clutter_actor_is_in_clone_paint
|
clutter_actor_is_in_clone_paint
|
||||||
clutter_actor_set_text_direction
|
clutter_actor_set_text_direction
|
||||||
clutter_actor_get_text_direction
|
clutter_actor_get_text_direction
|
||||||
|
clutter_actor_has_pointer
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
ClutterActorBox
|
ClutterActorBox
|
||||||
@ -874,7 +875,7 @@ clutter_param_fixed_get_type
|
|||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>clutter-feature</FILE>
|
<FILE>clutter-feature</FILE>
|
||||||
<TITLE>GL Features</TITLE>
|
<TITLE>Features</TITLE>
|
||||||
ClutterFeatureFlags
|
ClutterFeatureFlags
|
||||||
clutter_feature_available
|
clutter_feature_available
|
||||||
clutter_feature_get_all
|
clutter_feature_get_all
|
||||||
@ -940,7 +941,6 @@ ClutterMotionEvent
|
|||||||
ClutterScrollEvent
|
ClutterScrollEvent
|
||||||
ClutterStageStateEvent
|
ClutterStageStateEvent
|
||||||
ClutterCrossingEvent
|
ClutterCrossingEvent
|
||||||
ClutterInputDevice
|
|
||||||
clutter_event_new
|
clutter_event_new
|
||||||
clutter_event_copy
|
clutter_event_copy
|
||||||
clutter_event_free
|
clutter_event_free
|
||||||
@ -977,13 +977,9 @@ clutter_event_get_related
|
|||||||
clutter_event_get_scroll_direction
|
clutter_event_get_scroll_direction
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
ClutterInputDeviceType
|
|
||||||
clutter_event_get_device
|
clutter_event_get_device
|
||||||
clutter_event_get_device_id
|
clutter_event_get_device_id
|
||||||
clutter_event_get_device_type
|
clutter_event_get_device_type
|
||||||
clutter_get_input_device_for_id
|
|
||||||
clutter_input_device_get_device_id
|
|
||||||
clutter_input_device_get_device_type
|
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
clutter_get_current_event_time
|
clutter_get_current_event_time
|
||||||
@ -996,6 +992,51 @@ ClutterAnyEvent
|
|||||||
clutter_event_get_type
|
clutter_event_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>clutter-input-device</FILE>
|
||||||
|
<TITLE>ClutterInputDevice</TITLE>
|
||||||
|
ClutterInputDeviceType
|
||||||
|
ClutterInputDevice
|
||||||
|
ClutterInputDeviceClass
|
||||||
|
clutter_input_device_get_device_id
|
||||||
|
clutter_input_device_get_device_type
|
||||||
|
clutter_input_device_get_device_name
|
||||||
|
clutter_input_device_get_device_coords
|
||||||
|
clutter_input_device_get_pointer_actor
|
||||||
|
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
CLUTTER_TYPE_INPUT_DEVICE
|
||||||
|
CLUTTER_INPUT_DEVICE
|
||||||
|
CLUTTER_INPUT_DEVICE_CLASS
|
||||||
|
CLUTTER_IS_INPUT_DEVICE
|
||||||
|
CLUTTER_IS_INPUT_DEVICE_CLASS
|
||||||
|
CLUTTER_INPUT_DEVICE_GET_CLASS
|
||||||
|
|
||||||
|
<SUBSECTION Private>
|
||||||
|
clutter_input_device_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>clutter-device-manager</FILE>
|
||||||
|
<TITLE>ClutterDeviceManager</TITLE>
|
||||||
|
ClutterDeviceManager
|
||||||
|
clutter_device_manager_get_default
|
||||||
|
clutter_device_manager_list_devices
|
||||||
|
clutter_device_manager_peek_devices
|
||||||
|
clutter_device_manager_get_device
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
|
clutter_get_input_device_for_id
|
||||||
|
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
CLUTTER_TYPE_DEVICE_MANAGER
|
||||||
|
CLUTTER_DEVICE_MANAGER
|
||||||
|
CLUTTER_IS_DEVICE_MANAGER
|
||||||
|
|
||||||
|
<SUBSECTION Private>
|
||||||
|
clutter_device_manager_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>clutter-main</FILE>
|
<FILE>clutter-main</FILE>
|
||||||
<TITLE>General</TITLE>
|
<TITLE>General</TITLE>
|
||||||
|
@ -40,3 +40,5 @@ clutter_fixed_layout_get_type
|
|||||||
clutter_bin_layout_get_type
|
clutter_bin_layout_get_type
|
||||||
clutter_flow_layout_get_type
|
clutter_flow_layout_get_type
|
||||||
clutter_box_layout_get_type
|
clutter_box_layout_get_type
|
||||||
|
clutter_input_device_get_type
|
||||||
|
clutter_device_manager_get_type
|
||||||
|
@ -59,14 +59,13 @@ to this OpenGL code:
|
|||||||
<programlisting>
|
<programlisting>
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
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_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_SRC0_RGB, GL_PREVIOUS);
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
|
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
|
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_COLOR);
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
|
glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_COLOR);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
</section>
|
</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
|
EXTRA_DIST = README
|
||||||
|
|
||||||
.PHONY: test conform
|
if BUILD_TESTS
|
||||||
test conform:
|
test conform:
|
||||||
$(MAKE) -C ./conform test
|
( cd ./conform && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$?
|
||||||
.PHONY: test-report full-report
|
|
||||||
test-report full-report:
|
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
|
# run make test as part of make check
|
||||||
check-local: test
|
check-local: test
|
||||||
|
@ -41,9 +41,9 @@ check_pixel (GLubyte *pixel, guint32 color)
|
|||||||
g_print (" expected = %x, %x, %x, %x\n",
|
g_print (" expected = %x, %x, %x, %x\n",
|
||||||
r, g, b, a);
|
r, g, b, a);
|
||||||
/* FIXME - allow for hardware in-precision */
|
/* FIXME - allow for hardware in-precision */
|
||||||
g_assert (pixel[RED] == r);
|
g_assert_cmpint (pixel[RED], ==, r);
|
||||||
g_assert (pixel[GREEN] == g);
|
g_assert_cmpint (pixel[GREEN], ==, g);
|
||||||
g_assert (pixel[BLUE] == b);
|
g_assert_cmpint (pixel[BLUE], ==, b);
|
||||||
|
|
||||||
/* FIXME
|
/* FIXME
|
||||||
* We ignore the alpha, since we don't know if our render target is
|
* 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;
|
TestState state;
|
||||||
guint idle_source;
|
guint idle_source;
|
||||||
|
gulong paint_handler;
|
||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
int ypos = 0;
|
int ypos = 0;
|
||||||
|
|
||||||
@ -236,12 +237,15 @@ test_texture_fbo (TestConformSimpleFixture *fixture,
|
|||||||
* will trigger redrawing. */
|
* will trigger redrawing. */
|
||||||
idle_source = g_idle_add (queue_redraw, state.stage);
|
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_actor_show_all (state.stage);
|
||||||
|
|
||||||
clutter_main ();
|
clutter_main ();
|
||||||
|
|
||||||
|
g_signal_handler_disconnect (state.stage, paint_handler);
|
||||||
|
|
||||||
g_source_remove (idle_source);
|
g_source_remove (idle_source);
|
||||||
|
|
||||||
/* Remove all of the actors from the stage */
|
/* Remove all of the actors from the stage */
|
||||||
|
@ -12,14 +12,21 @@
|
|||||||
typedef struct _TestMultiLayerMaterialState
|
typedef struct _TestMultiLayerMaterialState
|
||||||
{
|
{
|
||||||
ClutterActor *group;
|
ClutterActor *group;
|
||||||
CoglHandle material;
|
|
||||||
CoglHandle alpha_tex;
|
CoglHandle alpha_tex;
|
||||||
CoglHandle redhand_tex;
|
CoglHandle redhand_tex;
|
||||||
CoglHandle light_tex0;
|
|
||||||
gfloat *tex_coords;
|
gfloat *tex_coords;
|
||||||
|
|
||||||
CoglMatrix tex_matrix;
|
ClutterTimeline *timeline;
|
||||||
CoglMatrix rot_matrix;
|
|
||||||
|
CoglHandle material0;
|
||||||
|
CoglMatrix tex_matrix0;
|
||||||
|
CoglMatrix rot_matrix0;
|
||||||
|
CoglHandle light_tex0;
|
||||||
|
|
||||||
|
CoglHandle material1;
|
||||||
|
CoglMatrix tex_matrix1;
|
||||||
|
CoglMatrix rot_matrix1;
|
||||||
|
CoglHandle light_tex1;
|
||||||
|
|
||||||
} TestMultiLayerMaterialState;
|
} TestMultiLayerMaterialState;
|
||||||
|
|
||||||
@ -31,10 +38,15 @@ frame_cb (ClutterTimeline *timeline,
|
|||||||
{
|
{
|
||||||
TestMultiLayerMaterialState *state = data;
|
TestMultiLayerMaterialState *state = data;
|
||||||
|
|
||||||
cogl_matrix_multiply (&state->tex_matrix,
|
cogl_matrix_multiply (&state->tex_matrix0,
|
||||||
&state->tex_matrix,
|
&state->tex_matrix0,
|
||||||
&state->rot_matrix);
|
&state->rot_matrix0);
|
||||||
cogl_material_set_layer_matrix (state->material, 2, &state->tex_matrix);
|
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
|
static void
|
||||||
@ -42,18 +54,51 @@ material_rectangle_paint (ClutterActor *actor, gpointer data)
|
|||||||
{
|
{
|
||||||
TestMultiLayerMaterialState *state = data;
|
TestMultiLayerMaterialState *state = data;
|
||||||
|
|
||||||
cogl_set_source (state->material);
|
cogl_push_matrix ();
|
||||||
cogl_rectangle_with_multitexture_coords (0, 0, 200, 200,
|
|
||||||
|
cogl_translate (150, 15, 0);
|
||||||
|
|
||||||
|
cogl_set_source (state->material0);
|
||||||
|
cogl_rectangle_with_multitexture_coords (0, 0, 200, 213,
|
||||||
state->tex_coords,
|
state->tex_coords,
|
||||||
12);
|
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
|
G_MODULE_EXPORT int
|
||||||
test_cogl_multitexture_main (int argc, char *argv[])
|
test_cogl_multitexture_main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
ClutterTimeline *timeline;
|
|
||||||
ClutterBehaviour *r_behave;
|
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff };
|
ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff };
|
||||||
TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
|
TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
|
||||||
@ -113,55 +158,71 @@ test_cogl_multitexture_main (int argc, char *argv[])
|
|||||||
if (!state->light_tex0)
|
if (!state->light_tex0)
|
||||||
g_critical ("Failed to load light0.png: %s", error->message);
|
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);
|
g_strfreev (files);
|
||||||
|
|
||||||
state->material = cogl_material_new ();
|
state->material0 = cogl_material_new ();
|
||||||
cogl_material_set_layer (state->material, 0, state->alpha_tex);
|
cogl_material_set_layer (state->material0, 0, state->alpha_tex);
|
||||||
cogl_material_set_layer (state->material, 1, state->redhand_tex);
|
cogl_material_set_layer (state->material0, 1, state->redhand_tex);
|
||||||
cogl_material_set_layer (state->material, 2, state->light_tex0);
|
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;
|
state->tex_coords = tex_coords;
|
||||||
|
|
||||||
cogl_matrix_init_identity (&state->tex_matrix);
|
cogl_matrix_init_identity (&state->tex_matrix0);
|
||||||
cogl_matrix_init_identity (&state->rot_matrix);
|
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_translate (&state->rot_matrix0, 0.5, 0.5, 0);
|
||||||
cogl_matrix_rotate (&state->rot_matrix, 10.0, 0, 0, 1.0);
|
cogl_matrix_rotate (&state->rot_matrix0, 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_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_actor_set_anchor_point (state->group, 86, 125);
|
||||||
clutter_container_add_actor (CLUTTER_CONTAINER(stage),
|
clutter_container_add_actor (CLUTTER_CONTAINER(stage),
|
||||||
state->group);
|
state->group);
|
||||||
|
|
||||||
timeline = clutter_timeline_new (7692);
|
state->timeline = clutter_timeline_new (2812);
|
||||||
clutter_timeline_set_loop (timeline, TRUE);
|
|
||||||
|
|
||||||
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_actor_animate_with_timeline (state->group,
|
||||||
clutter_behaviour_rotate_new (clutter_alpha_new_full (timeline,
|
CLUTTER_LINEAR,
|
||||||
CLUTTER_LINEAR),
|
state->timeline,
|
||||||
CLUTTER_Y_AXIS,
|
"rotation-angle-y", 30.0,
|
||||||
CLUTTER_ROTATE_CW,
|
"signal-after::completed",
|
||||||
0.0, 360.0);
|
animation_completed_cb, state,
|
||||||
|
NULL);
|
||||||
/* Apply it to our actor */
|
|
||||||
clutter_behaviour_apply (r_behave, state->group);
|
|
||||||
|
|
||||||
/* start the timeline and thus the animations */
|
/* start the timeline and thus the animations */
|
||||||
clutter_timeline_start (timeline);
|
clutter_timeline_start (state->timeline);
|
||||||
|
|
||||||
clutter_actor_show_all (stage);
|
clutter_actor_show_all (stage);
|
||||||
|
|
||||||
clutter_main();
|
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->alpha_tex);
|
||||||
cogl_handle_unref (state->redhand_tex);
|
cogl_handle_unref (state->redhand_tex);
|
||||||
cogl_handle_unref (state->light_tex0);
|
cogl_handle_unref (state->light_tex0);
|
||||||
|
cogl_handle_unref (state->light_tex1);
|
||||||
g_free (state);
|
g_free (state);
|
||||||
|
|
||||||
g_object_unref (r_behave);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,31 @@ typedef struct {
|
|||||||
|
|
||||||
} TestDevicesApp;
|
} TestDevicesApp;
|
||||||
|
|
||||||
|
static const gchar *
|
||||||
|
device_type_name (ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceType d_type;
|
||||||
|
|
||||||
|
d_type = clutter_input_device_get_device_type (device);
|
||||||
|
switch (d_type)
|
||||||
|
{
|
||||||
|
case CLUTTER_POINTER_DEVICE:
|
||||||
|
return "Pointer";
|
||||||
|
|
||||||
|
case CLUTTER_KEYBOARD_DEVICE:
|
||||||
|
return "Keyboard";
|
||||||
|
|
||||||
|
case CLUTTER_EXTENSION_DEVICE:
|
||||||
|
return "Extension";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
g_warn_if_reached ();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
stage_motion_event_cb (ClutterActor *actor,
|
stage_motion_event_cb (ClutterActor *actor,
|
||||||
@ -24,6 +48,11 @@ stage_motion_event_cb (ClutterActor *actor,
|
|||||||
|
|
||||||
hand = g_hash_table_lookup (app->devices, device);
|
hand = g_hash_table_lookup (app->devices, device);
|
||||||
|
|
||||||
|
g_print ("Device: '%s' (id:%d, type:%s)\n",
|
||||||
|
clutter_input_device_get_device_name (device),
|
||||||
|
clutter_input_device_get_device_id (device),
|
||||||
|
device_type_name (device));
|
||||||
|
|
||||||
if (hand != NULL)
|
if (hand != NULL)
|
||||||
{
|
{
|
||||||
gfloat event_x, event_y;
|
gfloat event_x, event_y;
|
||||||
@ -43,6 +72,7 @@ test_devices_main (int argc, char **argv)
|
|||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
TestDevicesApp *app;
|
TestDevicesApp *app;
|
||||||
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
const GSList *stage_devices, *l;
|
const GSList *stage_devices, *l;
|
||||||
|
|
||||||
/* force enabling X11 support */
|
/* force enabling X11 support */
|
||||||
@ -63,10 +93,11 @@ test_devices_main (int argc, char **argv)
|
|||||||
|
|
||||||
clutter_actor_show_all (stage);
|
clutter_actor_show_all (stage);
|
||||||
|
|
||||||
stage_devices = clutter_x11_get_input_devices ();
|
manager = clutter_device_manager_get_default ();
|
||||||
|
stage_devices = clutter_device_manager_peek_devices (manager);
|
||||||
|
|
||||||
if (stage_devices == NULL)
|
if (stage_devices == NULL)
|
||||||
g_error ("No extended input devices found.");
|
g_error ("No input devices found.");
|
||||||
|
|
||||||
for (l = stage_devices; l != NULL; l = l->next)
|
for (l = stage_devices; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
@ -74,12 +105,15 @@ test_devices_main (int argc, char **argv)
|
|||||||
ClutterInputDeviceType device_type;
|
ClutterInputDeviceType device_type;
|
||||||
ClutterActor *hand = NULL;
|
ClutterActor *hand = NULL;
|
||||||
|
|
||||||
device_type = clutter_input_device_get_device_type (device);
|
g_print ("got a %s device '%s' with id %d...\n",
|
||||||
if (device_type == CLUTTER_POINTER_DEVICE)
|
device_type_name (device),
|
||||||
{
|
clutter_input_device_get_device_name (device),
|
||||||
g_print ("got a pointer device with id %d...\n",
|
|
||||||
clutter_input_device_get_device_id (device));
|
clutter_input_device_get_device_id (device));
|
||||||
|
|
||||||
|
device_type = clutter_input_device_get_device_type (device);
|
||||||
|
if (device_type == CLUTTER_POINTER_DEVICE ||
|
||||||
|
device_type == CLUTTER_EXTENSION_DEVICE)
|
||||||
|
{
|
||||||
hand = clutter_texture_new_from_file (TESTS_DATADIR
|
hand = clutter_texture_new_from_file (TESTS_DATADIR
|
||||||
G_DIR_SEPARATOR_S
|
G_DIR_SEPARATOR_S
|
||||||
"redhand.png",
|
"redhand.png",
|
||||||
|
@ -48,6 +48,8 @@ static gboolean recenter = FALSE;
|
|||||||
static ClutterActor *main_stage = NULL;
|
static ClutterActor *main_stage = NULL;
|
||||||
static ClutterActor *easing_mode_label = NULL;
|
static ClutterActor *easing_mode_label = NULL;
|
||||||
|
|
||||||
|
static ClutterAnimation *last_animation = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_animation_completed (ClutterAnimation *animation,
|
on_animation_completed (ClutterAnimation *animation,
|
||||||
ClutterActor *rectangle)
|
ClutterActor *rectangle)
|
||||||
@ -113,10 +115,12 @@ on_button_press (ClutterActor *actor,
|
|||||||
"y", event->y,
|
"y", event->y,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (recenter)
|
if (recenter && last_animation != animation)
|
||||||
g_signal_connect_after (animation, "completed",
|
g_signal_connect_after (animation, "completed",
|
||||||
G_CALLBACK (on_animation_completed),
|
G_CALLBACK (on_animation_completed),
|
||||||
rectangle);
|
rectangle);
|
||||||
|
|
||||||
|
last_animation = animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -27,6 +27,12 @@ get_event_type_name (const ClutterEvent *event)
|
|||||||
case CLUTTER_LEAVE:
|
case CLUTTER_LEAVE:
|
||||||
return "LEAVE";
|
return "LEAVE";
|
||||||
|
|
||||||
|
case CLUTTER_MOTION:
|
||||||
|
return "MOTION";
|
||||||
|
|
||||||
|
case CLUTTER_DELETE:
|
||||||
|
return "DELETE";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "EVENT";
|
return "EVENT";
|
||||||
}
|
}
|
||||||
@ -124,29 +130,36 @@ fill_keybuf (char *keybuf, ClutterKeyEvent *event)
|
|||||||
/* printable character, if any (ß, ∑) */
|
/* printable character, if any (ß, ∑) */
|
||||||
len = g_unichar_to_utf8 (event->unicode_value, utf8);
|
len = g_unichar_to_utf8 (event->unicode_value, utf8);
|
||||||
utf8[len] = '\0';
|
utf8[len] = '\0';
|
||||||
sprintf(keybuf, "'%s' ", utf8);
|
sprintf (keybuf, "'%s' ", utf8);
|
||||||
|
|
||||||
/* key combination (<Mod1>s, <Shift><Mod1>S, <Ctrl><Mod1>Delete) */
|
/* key combination (<Mod1>s, <Shift><Mod1>S, <Ctrl><Mod1>Delete) */
|
||||||
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval),
|
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval), utf8);
|
||||||
utf8);
|
|
||||||
utf8[len] = '\0';
|
utf8[len] = '\0';
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_SHIFT_MASK)
|
if (event->modifier_state & CLUTTER_SHIFT_MASK)
|
||||||
strcat (keybuf, "<Shift>");
|
strcat (keybuf, "<Shift>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_LOCK_MASK)
|
if (event->modifier_state & CLUTTER_LOCK_MASK)
|
||||||
strcat (keybuf, "<Lock>");
|
strcat (keybuf, "<Lock>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_CONTROL_MASK)
|
if (event->modifier_state & CLUTTER_CONTROL_MASK)
|
||||||
strcat (keybuf, "<Control>");
|
strcat (keybuf, "<Control>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD1_MASK)
|
if (event->modifier_state & CLUTTER_MOD1_MASK)
|
||||||
strcat (keybuf, "<Mod1>");
|
strcat (keybuf, "<Mod1>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD2_MASK)
|
if (event->modifier_state & CLUTTER_MOD2_MASK)
|
||||||
strcat (keybuf, "<Mod2>");
|
strcat (keybuf, "<Mod2>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD3_MASK)
|
if (event->modifier_state & CLUTTER_MOD3_MASK)
|
||||||
strcat (keybuf, "<Mod3>");
|
strcat (keybuf, "<Mod3>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD4_MASK)
|
if (event->modifier_state & CLUTTER_MOD4_MASK)
|
||||||
strcat (keybuf, "<Mod4>");
|
strcat (keybuf, "<Mod4>");
|
||||||
|
|
||||||
if (event->modifier_state & CLUTTER_MOD5_MASK)
|
if (event->modifier_state & CLUTTER_MOD5_MASK)
|
||||||
strcat (keybuf, "<Mod5>");
|
strcat (keybuf, "<Mod5>");
|
||||||
|
|
||||||
strcat (keybuf, utf8);
|
strcat (keybuf, utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,62 +169,83 @@ input_cb (ClutterActor *actor,
|
|||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
ClutterStage *stage = CLUTTER_STAGE (clutter_stage_get_default ());
|
ClutterStage *stage = CLUTTER_STAGE (clutter_stage_get_default ());
|
||||||
gchar keybuf[128], *source = (gchar*)data;
|
ClutterActor *source_actor = clutter_event_get_source (event);
|
||||||
|
gchar keybuf[128];
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case CLUTTER_KEY_PRESS:
|
case CLUTTER_KEY_PRESS:
|
||||||
fill_keybuf (keybuf, &event->key);
|
fill_keybuf (keybuf, &event->key);
|
||||||
printf ("[%s] KEY PRESS %s", source, keybuf);
|
printf ("[%s] KEY PRESS %s",
|
||||||
|
clutter_actor_get_name (source_actor),
|
||||||
|
keybuf);
|
||||||
break;
|
break;
|
||||||
case CLUTTER_KEY_RELEASE:
|
case CLUTTER_KEY_RELEASE:
|
||||||
fill_keybuf (keybuf, &event->key);
|
fill_keybuf (keybuf, &event->key);
|
||||||
printf ("[%s] KEY RELEASE %s", source, keybuf);
|
printf ("[%s] KEY RELEASE %s",
|
||||||
|
clutter_actor_get_name (source_actor),
|
||||||
|
keybuf);
|
||||||
break;
|
break;
|
||||||
case CLUTTER_MOTION:
|
case CLUTTER_MOTION:
|
||||||
g_print ("[%s] MOTION", source);
|
g_print ("[%s] MOTION",
|
||||||
|
clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_ENTER:
|
case CLUTTER_ENTER:
|
||||||
g_print ("[%s] ENTER", source);
|
g_print ("[%s] ENTER (from:%s)",
|
||||||
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_related (event) != NULL
|
||||||
|
? clutter_actor_get_name (clutter_event_get_related (event))
|
||||||
|
: "<out of stage>");
|
||||||
break;
|
break;
|
||||||
case CLUTTER_LEAVE:
|
case CLUTTER_LEAVE:
|
||||||
g_print ("[%s] LEAVE", source);
|
g_print ("[%s] LEAVE (to:%s)",
|
||||||
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_related (event) != NULL
|
||||||
|
? clutter_actor_get_name (clutter_event_get_related (event))
|
||||||
|
: "<out of stage>");
|
||||||
break;
|
break;
|
||||||
case CLUTTER_BUTTON_PRESS:
|
case CLUTTER_BUTTON_PRESS:
|
||||||
g_print ("[%s] BUTTON PRESS (click count:%i)",
|
g_print ("[%s] BUTTON PRESS (button:%i, click count:%i)",
|
||||||
source, event->button.click_count);
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_button (event),
|
||||||
|
clutter_event_get_click_count (event));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_BUTTON_RELEASE:
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
g_print ("[%s] BUTTON RELEASE (click count:%i)",
|
g_print ("[%s] BUTTON RELEASE (button:%i, click count:%i)",
|
||||||
source, event->button.click_count);
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_button (event),
|
||||||
|
clutter_event_get_click_count (event));
|
||||||
|
|
||||||
if (clutter_event_get_source (event) == CLUTTER_ACTOR (stage))
|
if (source_actor == CLUTTER_ACTOR (stage))
|
||||||
clutter_stage_set_key_focus (stage, NULL);
|
clutter_stage_set_key_focus (stage, NULL);
|
||||||
else if (clutter_event_get_source (event) == actor
|
else if (source_actor == actor &&
|
||||||
&& clutter_actor_get_parent (actor) == CLUTTER_ACTOR (stage))
|
clutter_actor_get_parent (actor) == CLUTTER_ACTOR (stage))
|
||||||
clutter_stage_set_key_focus (stage, actor);
|
clutter_stage_set_key_focus (stage, actor);
|
||||||
break;
|
break;
|
||||||
case CLUTTER_SCROLL:
|
case CLUTTER_SCROLL:
|
||||||
g_print ("[%s] BUTTON SCROLL (click count:%i)",
|
g_print ("[%s] BUTTON SCROLL (direction:%s)",
|
||||||
source, event->button.click_count);
|
clutter_actor_get_name (source_actor),
|
||||||
|
clutter_event_get_scroll_direction (event) == CLUTTER_SCROLL_UP
|
||||||
|
? "up"
|
||||||
|
: "down");
|
||||||
break;
|
break;
|
||||||
case CLUTTER_STAGE_STATE:
|
case CLUTTER_STAGE_STATE:
|
||||||
g_print ("[%s] STAGE STATE", source);
|
g_print ("[%s] STAGE STATE", clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_DESTROY_NOTIFY:
|
case CLUTTER_DESTROY_NOTIFY:
|
||||||
g_print ("[%s] DESTROY NOTIFY", source);
|
g_print ("[%s] DESTROY NOTIFY", clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_CLIENT_MESSAGE:
|
case CLUTTER_CLIENT_MESSAGE:
|
||||||
g_print ("[%s] CLIENT MESSAGE", source);
|
g_print ("[%s] CLIENT MESSAGE", clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_DELETE:
|
case CLUTTER_DELETE:
|
||||||
g_print ("[%s] DELETE", source);
|
g_print ("[%s] DELETE", clutter_actor_get_name (source_actor));
|
||||||
break;
|
break;
|
||||||
case CLUTTER_NOTHING:
|
case CLUTTER_NOTHING:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clutter_event_get_source (event) == actor)
|
if (source_actor == actor)
|
||||||
g_print (" *source*");
|
g_print (" *source*");
|
||||||
|
|
||||||
g_print ("\n");
|
g_print ("\n");
|
||||||
@ -234,8 +268,8 @@ test_events_main (int argc, char *argv[])
|
|||||||
|
|
||||||
|
|
||||||
stage = clutter_stage_get_default ();
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_actor_set_name (stage, "Stage");
|
||||||
g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage");
|
g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage");
|
||||||
|
|
||||||
g_signal_connect (stage, "fullscreen",
|
g_signal_connect (stage, "fullscreen",
|
||||||
G_CALLBACK (stage_state_cb), "fullscreen");
|
G_CALLBACK (stage_state_cb), "fullscreen");
|
||||||
g_signal_connect (stage, "unfullscreen",
|
g_signal_connect (stage, "unfullscreen",
|
||||||
@ -244,24 +278,21 @@ test_events_main (int argc, char *argv[])
|
|||||||
G_CALLBACK (stage_state_cb), "activate");
|
G_CALLBACK (stage_state_cb), "activate");
|
||||||
g_signal_connect (stage, "deactivate",
|
g_signal_connect (stage, "deactivate",
|
||||||
G_CALLBACK (stage_state_cb), "deactivate");
|
G_CALLBACK (stage_state_cb), "deactivate");
|
||||||
|
/*g_signal_connect (stage, "captured-event", G_CALLBACK (capture_cb), NULL);*/
|
||||||
g_signal_connect (stage, "captured-event", G_CALLBACK (capture_cb), NULL);
|
|
||||||
|
|
||||||
focus_box = clutter_rectangle_new_with_color (&ncol);
|
focus_box = clutter_rectangle_new_with_color (&ncol);
|
||||||
|
clutter_actor_set_name (focus_box, "Focus Box");
|
||||||
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
||||||
|
|
||||||
actor = clutter_rectangle_new_with_color (&rcol);
|
actor = clutter_rectangle_new_with_color (&rcol);
|
||||||
|
clutter_actor_set_name (actor, "Red Box");
|
||||||
clutter_actor_set_size (actor, 100, 100);
|
clutter_actor_set_size (actor, 100, 100);
|
||||||
clutter_actor_set_position (actor, 100, 100);
|
clutter_actor_set_position (actor, 100, 100);
|
||||||
|
|
||||||
clutter_actor_set_reactive (actor, TRUE);
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||||
|
|
||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "red box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "red box");
|
||||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
|
||||||
/* Toggle motion - enter/leave capture */
|
/* Toggle motion - enter/leave capture */
|
||||||
g_signal_connect (actor, "button-press-event",
|
g_signal_connect (actor, "button-press-event",
|
||||||
G_CALLBACK (red_button_cb), NULL);
|
G_CALLBACK (red_button_cb), NULL);
|
||||||
@ -269,27 +300,22 @@ test_events_main (int argc, char *argv[])
|
|||||||
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor);
|
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor);
|
||||||
|
|
||||||
actor = clutter_rectangle_new_with_color (&gcol);
|
actor = clutter_rectangle_new_with_color (&gcol);
|
||||||
|
clutter_actor_set_name (actor, "Green Box");
|
||||||
clutter_actor_set_size (actor, 100, 100);
|
clutter_actor_set_size (actor, 100, 100);
|
||||||
clutter_actor_set_position (actor, 250, 100);
|
clutter_actor_set_position (actor, 250, 100);
|
||||||
|
|
||||||
clutter_actor_set_reactive (actor, TRUE);
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||||
|
|
||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "green box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "green box");
|
||||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
|
||||||
g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL);
|
g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL);
|
||||||
|
|
||||||
actor = clutter_rectangle_new_with_color (&bcol);
|
actor = clutter_rectangle_new_with_color (&bcol);
|
||||||
|
clutter_actor_set_name (actor, "Blue Box");
|
||||||
clutter_actor_set_size (actor, 100, 100);
|
clutter_actor_set_size (actor, 100, 100);
|
||||||
clutter_actor_set_position (actor, 400, 100);
|
clutter_actor_set_position (actor, 400, 100);
|
||||||
|
|
||||||
clutter_actor_set_reactive (actor, TRUE);
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
||||||
|
|
||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
||||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
@ -299,20 +325,19 @@ test_events_main (int argc, char *argv[])
|
|||||||
|
|
||||||
/* non reactive */
|
/* non reactive */
|
||||||
actor = clutter_rectangle_new_with_color (&ncol);
|
actor = clutter_rectangle_new_with_color (&ncol);
|
||||||
|
clutter_actor_set_name (actor, "Black Box");
|
||||||
clutter_actor_set_size (actor, 400, 50);
|
clutter_actor_set_size (actor, 400, 50);
|
||||||
clutter_actor_set_position (actor, 100, 250);
|
clutter_actor_set_position (actor, 100, 250);
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
||||||
|
|
||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
||||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
|
||||||
g_signal_connect (stage, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (stage, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
|
||||||
/* non reactive group, with reactive child */
|
/* non reactive group, with reactive child */
|
||||||
actor = clutter_rectangle_new_with_color (&ycol);
|
actor = clutter_rectangle_new_with_color (&ycol);
|
||||||
|
clutter_actor_set_name (actor, "Yellow Box");
|
||||||
clutter_actor_set_size (actor, 100, 100);
|
clutter_actor_set_size (actor, 100, 100);
|
||||||
clutter_actor_set_reactive (actor, TRUE);
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user