stamp-enum-types
stamp-marshal
/ChangeLog*
+/clutter/clutter-config.h
/clutter/clutter-enum-types.[ch]
/clutter/clutter-marshal.[ch]
/clutter/clutter-version.h
DISTCLEANFILES =
-DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-maintainer-flags
+DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-maintainer-flags --enable-docs
# Extra clean files so that maintainer-clean removes *everything*
MAINTAINERCLEANFILES = \
+Clutter 1.6.2 2011-02-07
+===============================================================================
+
+ • List of changes since Clutter 1.6.0
+
+ » Fix building the Clutter Cookbook from the released tarballs.
+
+ » Set the input device field in ClutterEvent even when they
+ have been allocated by Clutter.
+
+ » Fix the color comparison when setting the layer combine constant.
+
+ » Fix memory corruption when removing the last reference on a
+ Cogl vertex buffer object.
+
+ » Fixes for the OSX backend.
+
+ • List of bugs fixed since Clutter 1.6.0
+
+ #2540 - coobook examples do not build from tarball
+ #2544 - Using vertex buffers causes memory corruption when you unref
+ the CoglHandle
+ #2545 - Broken event handling in OS X backend
+ #2549 - Fix lib locations in *.pc.in
+
+Many thanks to:
+
+ Neil Roberts, Viatcheslav Gachkaylo
+
+Clutter 1.6.0 2011-01-31
+===============================================================================
+
+ • List of changes since Clutter 1.5.14
+
+ » Remove more private symbols from the X11 backend.
+
+ » Add CLUTTER_BIND_POSITION and CLUTTER_BIND_SIZE values to the
+ ClutterBindCoordinate enumeration; these are short-hand values
+ for binding both X and Y, or width and height, instead of
+ requiring two ClutterBindConstraint instances.
+
+ » Clean up in the X11 backend to reduce indirection.
+
+ » Small clean ups in the Win32 backend.
+
+ » Make Shift+Backspace behave like Backspace in ClutterText.
+
+ » Emit the ::new-frame signal even on the first frame of
+ ClutterTimeline, to allow setting up the initial state of an
+ animation.
+
+ » Fix an invalid memory access in ClutterAnimator.
+
+ » Flush the per-framebuffer journal when switching between
+ framebuffers.
+
+ » Generalize updating GLES2 uniforms.
+
+ » Add debug code for tracing clipping in Cogl.
+
+ » Improve the OSX event loop, re-using the same implementation
+ as GDK. Also, provide simple, core-like device support.
+
+ • Bugs fixed since Clutter 1.5.14
+
+ #2490 - OS X backend event loop improved
+ #2530 - animator: Animator uses key after freeing it
+ #2534 - Incorrect description of function 'clutter_actor_pop_internal'
+ #2535 - Add recipe about creating a composite actor
+
+Many thanks to:
+
+ Neil Roberts, Robert Bragg, Elliot Smith, Rob Bradford,
+ Viatcheslav Gachkaylo
+
+Clutter 1.5.14 2011-01-24
+===============================================================================
+
+ • List of changes since Clutter 1.5.12
+
+ » Allow getting the state modifiers from a ClutterClickAction.
+
+ » Fix ClutterDragAction to never leave the event delivery in
+ an unwanted state.
+
+ » Optimize state changes for texture and data states.
+
+ » Enable VBO support in Cogl for GLES2.
+
+ » Fix compilation on GLES1.1.
+
+ » Documentation fixes.
+
+ » ClutterGLXTexturePixmap has been deprecated; its parent class
+ ClutterX11TexturePixmap and the low level CoglTexturePixmapX11
+ API provide access to the same features.
+
+ » Be more resilient against timelines controlling the state of
+ other timelines during the clock tick.
+
+ » Provide defines for the windowing platforms, to allow portable
+ applications to include the correct header and select the
+ correct API depending on the target.
+
+ » Introduce a fast path for cogl_read_pixels() that uses the journal
+ to determine the position of a single pixel on the stage; this
+ fast path gracefully degrades to the usual render-based approach,
+ and should speed up picking considerably in the case of opaque
+ quads batched together.
+
+ » Support XInput axis data on valuator devices, and introduce XInput2
+ support for event translation and device hotplugging. The support
+ for XI and XI2 must still be explicitly enabled by the developer,
+ but it is now compiled in by default. It can be disabled at compile
+ time by passing --disable-xinput to the configure script.
+
+ » Clean up the unintentionally leaked internal symbols in the X11
+ and GLX backends.
+
+ » Allow defining the contents of the rows of a ListModel using
+ ClutterScript. This completes the ability to fully define a
+ ClutterListModel inside a UI definition file.
+
+ • Bugs fixed since Clutter 1.5.12
+
+ #1422, key input handler for eglnative
+ #1456, Hinting mishandling
+ #1721, XInput2 support
+ #2268, EGL backend dependent on X11 headers
+ #2400, Don't enable GL_POINT_SPRITE on GLES
+ #2497, should not throw away a program when just the texture
+ object has changed
+ #2512, shader: Don't notify properties when finalizing shaders
+ #2513, script-parser: Also honor properties of type GType
+ #2516, [PATCH] Fails to compile with --with-gles=1.1
+ #2518, introspection: Add missing (out) annotations for get_color()
+ #2520, Add API to get modifier type in ClutterClickAction
+ #2522, ClutterDragAction might indefinitely disable motion events
+ #2524, It's possible to receive a new-frame signal after stopping
+ a timeline
+ #2526, model: Fix some GObject-Introspection annotations
+ #2527, model: Change the column argument type to gint for
+ clutter_model_set_sort
+ #2528, model: Add support to define rows in ClutterScript
+
+Many thanks to:
+
+ Robert Bragg, Neil Roberts, Bastian Winkler, Lucas Rocha, Adel Gadllah,
+ Chris Lord, Damien Lespiau
+
+Clutter 1.5.12 2011-01-11
+===============================================================================
+
+ • List of changes since Clutter 1.5.10
+
+ » Allow disabling the focus when showing a ClutterStage; this also
+ makes Clutter more compliant to the X11 window manager
+ specifications.
+
+ » Avoid state corruption in relayout cycles.
+
+ » Do not crash when destroying actors during CLUTTER_LEAVE events.
+
+ » Remove signal handlers when disposing constraints.
+
+ » Keep the pixel alignment for ClutterAlignConstraint.
+
+ » Do not release compiled ClutterShader during their finalization to
+ avoid a warning.
+
+ » Revert an ABI break on the ClutterContainer pre-requisites.
+
+ » Fix the name of the cogl_normal_in attribute.
+
+ » Do not assume CoglBitmaps are allocated to height * rowstride.
+
+ » Fix the core device list creation on X11.
+
+ » Avoid enabling blending in the Cogl journal, if possible.
+
+ » Documentation fixes.
+
+ » Build fixes for mixed autotools version environment.
+
+ » Improve the performance of getting the number of rows of a
+ ClutterListModel.
+
+ » Don't use obsolete API internally.
+
+ » Build fix for compiling EGL backend with OpenGL under X11.
+
+ » Parse GType object properties in ClutterScript.
+
+Many thanks to:
+
+ Neil Roberts, Johan Bilien, nobled, Adel Gadllah, Damien Lespiau,
+ Kristian Høgsberg, Nguyễn Thái Ngọc Duy, Tomeu Vizoso, Bastian Winkler
+
Clutter 1.5.10 2010-12-17
===============================================================================
Clutter currently requires:
- • GLib >= 2.26.0
- • JSON-GLib >= 0.12
- • Atk >= 1.17
- • Cairo >= 1.10
- • PangoCairo >= 1.20
- • OpenGL >= 1.3 or 1.2+multitexturing, OpenGL ES 1.1 or OpenGL ES 2.0
+ • GLib ≥ 2.26.0
+ • JSON-GLib ≥ 0.12
+ • Atk ≥ 1.17
+ • Cairo ≥ 1.10
+ • PangoCairo ≥ 1.20
+ • OpenGL ≥ 1.3 (or 1.2+multitexturing), OpenGL ES 1.1 or OpenGL ES 2.0
• GLX, SDL, WGL or an EGL Implementation
Clutter also has optional dependencies:
- • GDK-Pixbuf >= 2.0 (optional, see --with-imagebackend below)
+ • GDK-Pixbuf ≥ 2.0 (optional, see --with-imagebackend below)
On X11, Clutter depends on the following extensions
- • XComposite
+ • XComposite ≥ 0.4
• XDamage
• XExt
- • XFixes
- • XInput 1.x (if --enable-xinput is passed to configure)
+ • XFixes ≥ 3
+ • XInput 1.x or 2.x
• XKB
When running the OpenGL flavor, Clutter requires at least version 1.3
If you are building the API reference you will also need:
- • GTK-Doc >= 1.13
+ • GTK-Doc ≥ 1.13
If you are building the additional documentation you will also need:
If you are building the Introspection data you will also need:
- • GObject-Introspection >= 0.9.5
+ • GObject-Introspection ≥ 0.9.5
GObject-Introspection is available from:
If you want support for profiling Clutter you will also need:
- • UProf >= 0.3
+ • UProf ≥ 0.3
UProf is available from:
http://source.clutter-project.org/sources/clutter/
-The Clutter blog is at:
+The Clutter blog is available at:
http://www.clutter-project.org/blog/
no:
Disable support for COGL runtime debugging notes.
- --enable-maintainer-flags=[no/yes]
+ --enable-maintainer-flags=[no/yes/error]
Use strict compiler flags. This defaults to 'yes' for developers
- snapshots and to 'no' for stable releases.
+ snapshots and to 'no' for stable releases. If 'error' is used, then
+ -Werror will be enabled (if available).
--enable-gtk-doc
use gtk-doc to build API documentation (default=no). Requires gtk-doc
Select the Clutter backend: (default=glx)
glx:
- Fully featured GLX backend. Using Open GL.
+ Fully featured GLX backend.
+
+ opengl-egl-xlib:
+ EGL/Open GL backend for X11.
+
+ wayland:
+ EGL/Open GL backend for Wayland.
eglx:
- EGL/Open GL ES backend for EGL on X windows implementations
+ EGL/Open GL|ES backend for X11.
eglnative:
- EGL/Open GL ES backend on 'native windowing system' - i.e
+ EGL/Open GL|ES backend on 'native windowing system' - i.e
raw framebuffer. Expects the EGL implementation to provide
- a createNativeWindow() call. Also it optionally supports
- tslib for touchscreen events.
+ a createNativeWindow() call.
+
+ cex100:
+ EGL/Open GL|ES backend on Intel CE3100 and CE4100 platforms.
+ Requires libgdl.
osx:
OS X backend. (EXPERIMENTAL)
win32:
- Microsoft Windows(tm) WGL backend
+ Microsoft Windows(tm) WGL backend.
fruity:
- Apple iPod Touch(tm)/iPhone(tm) backend (EXPERIMENTAL)
+ Apple iPod Touch(tm)/iPhone(tm) backend. (EXPERIMENTAL)
--with-imagebackend=[gdk-pixbuf/quartz/internal]
Select the image loading backend used by COGL
gdk-pixbuf:
Depend on gdk-pixbuf-2.0 (default for the glx, eglx,
- eglnative, win32 flavours and recommended)
+ eglnative, win32 flavours and recommended).
quartz:
- Depend on CoreGraphics (default for the osx flavour)
+ Depend on CoreGraphics (default for the osx flavour).
internal:
Internal JPEG and PNG loader. Should only be used
git diff > clutter-patch.diff
-Or, better, commit locally and use `git format-patch` to generate a patch
+Or, better: commit locally and use `git format-patch` to generate a patch
containing authorship details, so that members of the Clutter development
team can credit your contribution properly.
both API are not integrated in the Clutter main loop, and are not used
internally any longer, so they are of relative use.
+• It it not necessary any more to provide implementations for the
+ ClutterActor::map() and ClutterActor::unmap() virtual functions, even
+ for composite actors not implementing the ClutterContainer interface.
+
+• ClutterTimeline now guarantees that the ::new-frame signal will be
+ emitted at the beginning of the timeline, as well as guaranteeing that
+ the ::completed signal will be emitted at the end of the timeline.
+
+• ClutterActor will check for the enabled property of ClutterActorMeta
+ instances (actions, constraints and effects), and will not invoke
+ ClutterActorMeta functions on disabled instances. This removes the
+ requirement for checking the property inside the ClutterActorMeta
+ sub-classes.
+
+• ClutterActorBox, ClutterGeometry and ClutterVertex install a progress
+ function for ClutterInterval, allowing the interpolation of properties
+ using them as storage types.
+
+• ClutterColor's clutter_color_from_string() function accepts CSS3 color
+ specifications.
+
+• The previously unused "axes" field in the ClutterButtonEvent,
+ ClutterScrollEvent and ClutterMotionEvent structures is now used on
+ the X11-based backends with XInput support.
+
+• ClutterListModel will honour the filter function when calling
+ clutter_model_get_iter_at_row().
+
+• ClutterClickAction does not use a pointer grab any longer, and uses
+ a capture on the stage instead.
+
+• On all platforms which allow it, ClutterStage will ask the windowing
+ system for an explicit key focus when showing the stage window. This
+ can be disabled using clutter_stage_set_accept_focus().
+
+Release Notes for Cogl 1.6
+-------------------------------------------------------------------------------
+
+• Cogl may internally optimise cogl_read_pixels when only a single
+ pixel is drawn and the entire scene is comprised of solid colour
+ rectangles. Instead of actually rendering the rectangles it will
+ compute the single pixel value in software. This effectively means
+ that Clutter can do software picking without any API changes.
+
+• Internally Cogl now has a GLSL backend as well as the ARBfp and
+ fixed function backends. By default, this backend has the lowest
+ priority but it can be explicitly enabled by setting the
+ COGL_DEBUG environment variable, e.g.:
+
+ export COGL_DEBUG=disable-fixed,disable-arbfp
+
+ for builds of Clutter with debug support enabled.
+
+• Cogl will internally now cache generated ARBfp programs so that it
+ should be able to reuse a previous program even if it was generated
+ for an unrelated CoglMaterial. This makes using one-shot materials
+ less expensive than before although it is still not recommended.
+
Release Notes for Clutter 1.4
-------------------------------------------------------------------------------
<!-- vim:set ts=2 expandtab: -->
<moduleset>
<repository type="git" name="git.freedesktop.org"
- href="git://anongit.freedesktop.org/git/"/>
+ href="git://anongit.freedesktop.org/"/>
<repository type="git" name="git.gnome.org"
href="git://git.gnome.org/"/>
<repository type="git" name="git.clutter-project.org"
<autotools id="wayland">
<branch repo="git.freedesktop.org"
- module="~krh/wayland" checkoutdir="wayland"/>
+ module="wayland" checkoutdir="wayland"/>
<dependencies>
<dep package="mesa"/>
</dependencies>
$(srcdir)/clutter-bezier.h \
$(srcdir)/clutter-debug.h \
$(srcdir)/clutter-device-manager-private.h \
+ $(srcdir)/clutter-event-translator.h \
$(srcdir)/clutter-id-pool.h \
$(srcdir)/clutter-keysyms-table.h \
$(srcdir)/clutter-master-clock.h \
# private source code; these should not be introspected
source_c_priv = \
+ $(srcdir)/clutter-event-translator.c \
$(srcdir)/clutter-id-pool.c \
$(srcdir)/clutter-profile.c \
$(srcdir)/clutter-timeout-interval.c \
clutter-marshal.h \
$(NULL)
+# config header
+DISTCLEANFILES += clutter-config.h
+EXTRA_DIST += clutter-config.h.in
+
# version header
DISTCLEANFILES += clutter-version.h
EXTRA_DIST += clutter-version.h.in
# X11 backend rules
x11_source_c = \
$(srcdir)/x11/clutter-backend-x11.c \
- $(srcdir)/x11/clutter-device-manager-x11.c \
+ $(srcdir)/x11/clutter-device-manager-core-x11.c \
$(srcdir)/x11/clutter-event-x11.c \
- $(srcdir)/x11/clutter-input-device-x11.c \
+ $(srcdir)/x11/clutter-input-device-core-x11.c \
$(srcdir)/x11/clutter-keymap-x11.c \
$(srcdir)/x11/clutter-stage-x11.c \
$(srcdir)/x11/clutter-x11-texture-pixmap.c \
x11_source_h_priv = \
$(srcdir)/x11/clutter-backend-x11.h \
- $(srcdir)/x11/clutter-device-manager-x11.h \
- $(srcdir)/x11/clutter-input-device-x11.h \
+ $(srcdir)/x11/clutter-device-manager-core-x11.h \
+ $(srcdir)/x11/clutter-input-device-core-x11.h \
$(srcdir)/x11/clutter-keymap-x11.h \
$(srcdir)/x11/clutter-settings-x11.h \
$(srcdir)/x11/clutter-stage-x11.h \
$(srcdir)/x11/xsettings/xsettings-common.h \
$(NULL)
+if BUILD_XI2
+x11_source_c += \
+ $(srcdir)/x11/clutter-device-manager-xi2.c \
+ $(srcdir)/x11/clutter-input-device-xi2.c \
+ $(NULL)
+
+x11_source_h_priv += \
+ $(srcdir)/x11/clutter-device-manager-xi2.h \
+ $(srcdir)/x11/clutter-input-device-xi2.h \
+ $(NULL)
+endif # BUILD_XI2
+
if SUPPORT_X11
backend_source_h += $(x11_source_h)
backend_source_c += $(x11_source_c)
# GLX backend rules
glx_source_c = \
$(srcdir)/glx/clutter-backend-glx.c \
- $(srcdir)/glx/clutter-event-glx.c \
$(srcdir)/glx/clutter-glx-texture-pixmap.c \
$(srcdir)/glx/clutter-stage-glx.c \
$(NULL)
glx_source_h_priv = \
$(srcdir)/glx/clutter-backend-glx.h \
- $(srcdir)/glx/clutter-event-glx.h \
$(srcdir)/glx/clutter-stage-glx.h \
$(NULL)
osx_source_h_priv = \
$(srcdir)/osx/clutter-backend-osx.h \
+ $(srcdir)/osx/clutter-event-loop-osx.h \
$(srcdir)/osx/clutter-stage-osx.h \
+ $(srcdir)/osx/clutter-device-manager-osx.h \
$(NULL)
-osx_source_c_priv = $(srcdir)/osx/clutter-event-osx.c
+osx_source_c_priv = \
+ $(srcdir)/osx/clutter-event-loop-osx.c \
+ $(srcdir)/osx/clutter-event-osx.c \
+ $(srcdir)/osx/clutter-device-manager-osx.c \
+ $(NULL)
if SUPPORT_OSX
# we need to tell the compiler that part of our code base is
clutter_include_HEADERS = $(source_h) $(top_srcdir)/clutter/clutter.h
nodist_clutter_include_HEADERS = \
+ $(top_builddir)/clutter/clutter-config.h \
$(top_builddir)/clutter/clutter-version.h \
$(built_source_h)
*
* Return value: added action id, or -1 if failure
*
- * Since: 1.6
- *
* Rename to: cally_actor_add_action
+ *
+ * Since: 1.6
*/
guint
cally_actor_add_action_full (CallyActor *cally_actor,
Name: Cally
Description: Clutter Accessibility Implementation Library
Version: @VERSION@
-Libs: -L${libdir} -lclutter-${winsys}-${apiversion}
+Libs: -L${libdir} -lclutter-${soname_infix}-${apiversion}
Cflags: -I${includedir}/clutter-${apiversion}
Requires: atk clutter-1.0
ClutterCallback callback,
gpointer data);
-void _clutter_actor_set_opacity_parent (ClutterActor *self,
- ClutterActor *parent);
+void _clutter_actor_set_opacity_override (ClutterActor *self,
+ gint opacity);
+void _clutter_actor_set_in_clone_paint (ClutterActor *self,
+ gboolean is_in_clone_paint);
void _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
gboolean enable);
#include "clutter-action.h"
#include "clutter-actor-meta-private.h"
#include "clutter-animatable.h"
+#include "clutter-behaviour.h"
#include "clutter-constraint.h"
#include "clutter-container.h"
#include "clutter-debug.h"
#include "clutter-stage-private.h"
#include "clutter-units.h"
-#undef CLUTTER_DISABLE_DEPRECATED
-#include "clutter-behaviour.h"
-
typedef struct _ShaderData ShaderData;
typedef struct _AnchorCoord AnchorCoord;
guint propagated_one_redraw : 1;
guint paint_volume_valid : 1;
guint last_paint_box_valid : 1;
+ guint in_clone_paint : 1;
gfloat clip[4];
gfloat z;
guint8 opacity;
+ gint opacity_override;
ClutterActor *parent_actor;
GList *children;
PangoContext *pango_context;
- ClutterActor *opacity_parent;
-
ClutterTextDirection text_direction;
gint internal_child;
if (context->pick_mode == CLUTTER_PICK_NONE &&
/* ignore top-levels, since they might be transparent */
!CLUTTER_ACTOR_IS_TOPLEVEL (self) &&
- /* If the actor is being painted from a clone then check the
- clone's opacity instead */
- (priv->opacity_parent ? priv->opacity_parent->priv : priv)->opacity == 0)
+ /* Use the override opacity if its been set */
+ ((priv->opacity_override >= 0) ?
+ priv->opacity_override : priv->opacity) == 0)
{
priv->propagated_one_redraw = FALSE;
return;
/**
* ClutterActor::destroy:
- * @actor: the object which received the signal
+ * @actor: the #ClutterActor which emitted the signal
+ *
+ * The ::destroy signal notifies that all references held on the
+ * actor which emitted it should be released.
*
- * The ::destroy signal is emitted when an actor is destroyed,
- * either by direct invocation of clutter_actor_destroy() or
- * when the #ClutterGroup that contains the actor is destroyed.
+ * The ::destroy signal should be used by all holders of a reference
+ * on @actor.
+ *
+ * This signal might result in the finalization of the #ClutterActor
+ * if all references are released.
+ *
+ * Composite actors and actors implementing the #ClutterContainer
+ * interface should override the default implementation of the
+ * class handler of this signal and call clutter_actor_destroy() on
+ * their children. When overriding the default class handler, it is
+ * required to chain up to the parent's implementation.
*
* Since: 0.2
*/
priv->cached_width_age = 1;
priv->cached_height_age = 1;
- priv->opacity_parent = NULL;
+ priv->opacity_override = -1;
priv->enable_model_view_transform = TRUE;
/* Initialize an empty paint box to start with */
if (CLUTTER_ACTOR_IS_TOPLEVEL (self))
return 255;
- if (priv->opacity_parent != NULL)
- return clutter_actor_get_paint_opacity_internal (priv->opacity_parent);
+ if (priv->opacity_override >= 0)
+ return priv->opacity_override;
parent = priv->parent_actor;
*
* Removes the parent of @self.
*
- * This function should not be used in applications. It should be called by
- * implementations of container actors, to dissociate a child from the
- * container.
+ * This function should not be used in applications.
+ *
+ * This function should only be called by implementations of the
+ * #ClutterContainer interface, or by composite actors that do
+ * not implicitly create their children.
*
* Since: 0.1.1
*/
return layout;
}
-/* Allows overriding the parent traversed when querying an actors paint
- * opacity. Used by ClutterClone. */
+/* Allows overriding the calculated paint opacity. Used by ClutterClone and
+ * ClutterOffscreenEffect.
+ */
void
-_clutter_actor_set_opacity_parent (ClutterActor *self,
- ClutterActor *parent)
+_clutter_actor_set_opacity_override (ClutterActor *self,
+ gint opacity)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
- self->priv->opacity_parent = parent;
+ self->priv->opacity_override = opacity;
}
/* Allows you to disable applying the actors model view transform during
_clutter_actor_apply_modelview_transform (self, matrix);
}
+void
+_clutter_actor_set_in_clone_paint (ClutterActor *self,
+ gboolean is_in_clone_paint)
+{
+ g_return_if_fail (CLUTTER_IS_ACTOR (self));
+ self->priv->in_clone_paint = is_in_clone_paint;
+}
+
/**
* clutter_actor_is_in_clone_paint:
* @self: a #ClutterActor
gboolean
clutter_actor_is_in_clone_paint (ClutterActor *self)
{
- ClutterActorPrivate *priv;
-
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
- /* XXX - keep in sync with the overrides set by ClutterClone:
- *
- * - opacity_parent != NULL
- * - enable_model_view_transform == FALSE
- */
-
- priv = self->priv;
-
- return priv->opacity_parent != NULL &&
- !priv->enable_model_view_transform;
+ return self->priv->in_clone_paint;
}
static void
* clutter_actor_pop_internal:
* @self: a #ClutterActor
*
- * Disables the effects of clutter_actor_pop_internal()
+ * Disables the effects of clutter_actor_push_internal()
*
* Since: 1.2
*/
void (* parent_set) (ClutterActor *actor,
ClutterActor *old_parent);
- void (* destroy) (ClutterActor *actor);
+ void (* destroy) (ClutterActor *self);
void (* pick) (ClutterActor *actor,
const ClutterColor *color);
void (* key_focus_in) (ClutterActor *actor);
void (* key_focus_out) (ClutterActor *actor);
- void (* queue_relayout) (ClutterActor *actor);
+ void (* queue_relayout) (ClutterActor *self);
/* accessibility support */
AtkObject * (* get_accessible) (ClutterActor *self);
#include "clutter-enum-types.h"
#include "clutter-private.h"
+#include <math.h>
+
#define CLUTTER_ALIGN_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraintClass))
#define CLUTTER_IS_ALIGN_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ALIGN_CONSTRAINT))
#define CLUTTER_ALIGN_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraintClass))
-typedef struct _ClutterAlignConstraintClass ClutterAlignConstraintClass;
-
struct _ClutterAlignConstraint
{
ClutterConstraint parent_instance;
actor_width = clutter_actor_box_get_width (allocation);
allocation->x1 = ((source_width - actor_width) * align->factor)
+ source_x;
+ allocation->x1 = floorf (allocation->x1 + 0.5);
allocation->x2 = allocation->x1 + actor_width;
break;
actor_height = clutter_actor_box_get_height (allocation);
allocation->y1 = ((source_height - actor_height) * align->factor)
+ source_y;
+ allocation->x1 = floorf (allocation->x1 + 0.5);
allocation->y2 = allocation->y1 + actor_height;
break;
*
* Since: 1.4
*/
-typedef struct _ClutterAlignConstraint ClutterAlignConstraint;
+typedef struct _ClutterAlignConstraint ClutterAlignConstraint;
+typedef struct _ClutterAlignConstraintClass ClutterAlignConstraintClass;
/**
* ClutterAlignAxis:
static void
timeline_new_frame_cb (ClutterTimeline *timeline,
- guint current_frame_num,
+ guint msecs,
ClutterAlpha *alpha)
{
ClutterAlphaPrivate *priv = alpha->priv;
ClutterAnimatorKey *prev_key = NULL;
key->is_inert = is_inert;
- clutter_animator_key_free (key);
/* FIXME: non performant since we reiterate the list many times */
next_key->ease_in = key->ease_in;
}
}
+
+ clutter_animator_key_free (key);
priv->score = g_list_remove (priv->score, key);
goto again;
}
#define __CLUTTER_BACKEND_PRIVATE_H__
#include <clutter/clutter-backend.h>
+#include "clutter-event-translator.h"
#define CLUTTER_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND, ClutterBackendClass))
#define CLUTTER_IS_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND))
G_BEGIN_DECLS
typedef struct _ClutterBackendPrivate ClutterBackendPrivate;
-typedef struct _ClutterBackendClass ClutterBackendClass;
struct _ClutterBackend
{
void (* free_event_data) (ClutterBackend *backend,
ClutterEvent *event);
+ gboolean (* translate_event) (ClutterBackend *backend,
+ gpointer native,
+ ClutterEvent *event);
+
/* signals */
void (* resolution_changed) (ClutterBackend *backend);
void (* font_changed) (ClutterBackend *backend);
gint32 _clutter_backend_get_units_serial (ClutterBackend *backend);
+gboolean _clutter_backend_translate_event (ClutterBackend *backend,
+ gpointer native,
+ ClutterEvent *event);
+
+void _clutter_backend_add_event_translator (ClutterBackend *backend,
+ ClutterEventTranslator *translator);
+void _clutter_backend_remove_event_translator (ClutterBackend *backend,
+ ClutterEventTranslator *translator);
+
+
G_END_DECLS
#endif /* __CLUTTER_BACKEND_PRIVATE_H__ */
gfloat units_per_em;
gint32 units_serial;
+
+ GList *event_translators;
};
enum
static void
clutter_backend_dispose (GObject *gobject)
{
- ClutterMainContext *clutter_context;
+ ClutterBackendPrivate *priv = CLUTTER_BACKEND (gobject)->priv;
- clutter_context = _clutter_context_get_default ();
+ /* clear the events still in the queue of the main context */
+ _clutter_clear_events_queue ();
- if (clutter_context && clutter_context->events_queue)
+ /* remove all event translators */
+ if (priv->event_translators != NULL)
{
- g_queue_foreach (clutter_context->events_queue,
- (GFunc) clutter_event_free,
- NULL);
- g_queue_free (clutter_context->events_queue);
- clutter_context->events_queue = NULL;
+ g_list_free (priv->event_translators);
+ priv->event_translators = NULL;
}
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
}
static void
+clutter_backend_real_redraw (ClutterBackend *backend,
+ ClutterStage *stage)
+{
+ ClutterStageWindow *impl;
+
+ if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
+ return;
+
+ impl = _clutter_stage_get_window (stage);
+ if (impl == NULL)
+ return;
+
+ _clutter_stage_window_redraw (impl);
+}
+
+static gboolean
+clutter_backend_real_translate_event (ClutterBackend *backend,
+ gpointer native,
+ ClutterEvent *event)
+{
+ ClutterBackendPrivate *priv = backend->priv;
+ GList *l;
+
+ for (l = priv->event_translators;
+ l != NULL;
+ l = l->next)
+ {
+ ClutterEventTranslator *translator = l->data;
+ ClutterTranslateReturn retval;
+
+ retval = _clutter_event_translator_translate_event (translator,
+ native,
+ event);
+
+ if (retval == CLUTTER_TRANSLATE_QUEUE)
+ return TRUE;
+
+ if (retval == CLUTTER_TRANSLATE_REMOVE)
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+static void
clutter_backend_class_init (ClutterBackendClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
klass->resolution_changed = clutter_backend_real_resolution_changed;
klass->font_changed = clutter_backend_real_font_changed;
+ klass->translate_event = clutter_backend_real_translate_event;
+ klass->redraw = clutter_backend_real_redraw;
}
static void
_clutter_backend_redraw (ClutterBackend *backend,
ClutterStage *stage)
{
- ClutterBackendClass *klass;
CLUTTER_STATIC_COUNTER (redraw_counter,
"_clutter_backend_redraw counter",
"Increments for each _clutter_backend_redraw call",
CLUTTER_COUNTER_INC (_clutter_uprof_context, redraw_counter);
CLUTTER_TIMER_START (_clutter_uprof_context, redraw_timer);
- klass = CLUTTER_BACKEND_GET_CLASS (backend);
- if (G_LIKELY (klass->redraw))
- klass->redraw (backend, stage);
+ CLUTTER_BACKEND_GET_CLASS (backend)->redraw (backend, stage);
CLUTTER_TIMER_STOP (_clutter_uprof_context, redraw_timer);
}
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
g_return_if_fail (clutter_context != NULL);
- clutter_context->events_queue = g_queue_new ();
-
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (klass->init_events)
klass->init_events (backend);
return backend->priv->units_serial;
}
+
+gboolean
+_clutter_backend_translate_event (ClutterBackend *backend,
+ gpointer native,
+ ClutterEvent *event)
+{
+ g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE);
+
+ return CLUTTER_BACKEND_GET_CLASS (backend)->translate_event (backend,
+ native,
+ event);
+}
+
+void
+_clutter_backend_add_event_translator (ClutterBackend *backend,
+ ClutterEventTranslator *translator)
+{
+ ClutterBackendPrivate *priv = backend->priv;
+
+ if (g_list_find (priv->event_translators, translator) != NULL)
+ return;
+
+ priv->event_translators =
+ g_list_prepend (priv->event_translators, translator);
+}
+
+void
+_clutter_backend_remove_event_translator (ClutterBackend *backend,
+ ClutterEventTranslator *translator)
+{
+ ClutterBackendPrivate *priv = backend->priv;
+
+ if (g_list_find (priv->event_translators, translator) == NULL)
+ return;
+
+ priv->event_translators =
+ g_list_remove (priv->event_translators, translator);
+}
#define CLUTTER_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND, ClutterBackend))
#define CLUTTER_IS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND))
+/**
+ * ClutterBackend:
+ *
+ * <structname>ClutterBackend</structname> is an opaque structure whose
+ * members cannot be directly accessed.
+ *
+ * Since: 0.4
+ */
typedef struct _ClutterBackend ClutterBackend;
+typedef struct _ClutterBackendClass ClutterBackendClass;
GType clutter_backend_get_type (void) G_GNUC_CONST;
#include "config.h"
#endif
-#undef CLUTTER_DISABLE_DEPRECATED
#include "clutter-behaviour-depth.h"
#include "clutter-enum-types.h"
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
#define CLUTTER_TYPE_BEHAVIOUR_DEPTH (clutter_behaviour_depth_get_type ())
#define CLUTTER_BEHAVIOUR_DEPTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR_DEPTH, ClutterBehaviourDepth))
#include <math.h>
#include <stdlib.h>
-#undef CLUTTER_DISABLE_DEPRECATED
#include "clutter-behaviour-ellipse.h"
#include "clutter-debug.h"
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
#define CLUTTER_TYPE_BEHAVIOUR_ELLIPSE (clutter_behaviour_ellipse_get_type ())
#include <math.h>
-#undef CLUTTER_DISABLE_DEPRECATED
#include "clutter-behaviour-opacity.h"
#include "clutter-private.h"
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
#define CLUTTER_TYPE_BEHAVIOUR_OPACITY (clutter_behaviour_opacity_get_type ())
#include "config.h"
#endif
-#undef CLUTTER_DISABLE_DEPRECATED
#include "clutter-behaviour-path.h"
#include "clutter-bezier.h"
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
#define CLUTTER_TYPE_BEHAVIOUR_PATH (clutter_behaviour_path_get_type ())
#include "config.h"
#endif
-#undef CLUTTER_DISABLE_DEPRECATED
#include "clutter-behaviour-rotate.h"
#include <math.h>
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
#define CLUTTER_TYPE_BEHAVIOUR_ROTATE (clutter_behaviour_rotate_get_type ())
#define CLUTTER_BEHAVIOUR_ROTATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR_ROTATE, ClutterBehaviourRotate))
#include <math.h>
-#undef CLUTTER_DISABLE_DEPRECATED
#include "clutter-behaviour-scale.h"
#include "clutter-debug.h"
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
#define CLUTTER_TYPE_BEHAVIOUR_SCALE (clutter_behaviour_scale_get_type ())
#define CLUTTER_BEHAVIOUR_SCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScale))
#include "config.h"
#endif
-#undef CLUTTER_DISABLE_DEPRECATED
#include "clutter-behaviour.h"
#include "clutter-debug.h"
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
#define CLUTTER_TYPE_BEHAVIOUR clutter_behaviour_get_type()
gboolean clutter_behaviour_is_applied (ClutterBehaviour *behave,
ClutterActor *actor);
-#endif /* CLUTTER_DISABLE_DEPRECATED */
+#endif /* !CLUTTER_DISABLE_DEPRECATED || CLUTTER_COMPILATION */
G_END_DECLS
#define CLUTTER_IS_BIND_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BIND_CONSTRAINT))
#define CLUTTER_BIND_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraintClass))
-typedef struct _ClutterBindConstraintClass ClutterBindConstraintClass;
-
struct _ClutterBindConstraint
{
ClutterConstraint parent_instance;
allocation->y2 = allocation->y1 + actor_height;
break;
+ case CLUTTER_BIND_POSITION:
+ allocation->x1 = source_position.x + bind->offset;
+ allocation->y1 = source_position.y + bind->offset;
+ allocation->x2 = allocation->x1 + actor_width;
+ allocation->y2 = allocation->y1 + actor_height;
+ break;
+
case CLUTTER_BIND_WIDTH:
allocation->x2 = allocation->x1 + source_width + bind->offset;
break;
allocation->y2 = allocation->y1 + source_height + bind->offset;
break;
+ case CLUTTER_BIND_SIZE:
+ allocation->x2 = allocation->x1 + source_width + bind->offset;
+ allocation->y2 = allocation->y1 + source_height + bind->offset;
+ break;
+
default:
g_assert_not_reached ();
break;
*
* Since: 1.4
*/
-typedef struct _ClutterBindConstraint ClutterBindConstraint;
+typedef struct _ClutterBindConstraint ClutterBindConstraint;
+typedef struct _ClutterBindConstraintClass ClutterBindConstraintClass;
/**
* ClutterBindCoordinate:
* @CLUTTER_BIND_Y: Bind the Y coordinate
* @CLUTTER_BIND_WIDTH: Bind the width
* @CLUTTER_BIND_HEIGHT: Bidng the height
+ * @CLUTTER_BIND_POSITION: Equivalent to to %CLUTTER_BIND_X and
+ * %CLUTTER_BIND_Y
+ * @CLUTTER_BIND_SIZE: Equivalent to %CLUTTER_BIND_WIDTH and
+ * %CLUTTER_BIND_HEIGHT
*
* Specifies which property should be used in a binding
*
CLUTTER_BIND_X,
CLUTTER_BIND_Y,
CLUTTER_BIND_WIDTH,
- CLUTTER_BIND_HEIGHT
+ CLUTTER_BIND_HEIGHT,
+ CLUTTER_BIND_POSITION,
+ CLUTTER_BIND_SIZE
} ClutterBindCoordinate;
GType clutter_bind_constraint_get_type (void) G_GNUC_CONST;
CLUTTER_HYPER_MASK | \
CLUTTER_META_MASK) | CLUTTER_RELEASE_MASK)
-typedef struct _ClutterBindingPoolClass ClutterBindingPoolClass;
typedef struct _ClutterBindingEntry ClutterBindingEntry;
static GSList *clutter_binding_pools = NULL;
* Since: 1.0
*/
typedef struct _ClutterBindingPool ClutterBindingPool;
+typedef struct _ClutterBindingPoolClass ClutterBindingPoolClass;
/**
* ClutterBindingActionFunc:
#define BLUR_PADDING 2
-typedef struct _ClutterBlurEffectClass ClutterBlurEffectClass;
-
/* FIXME - lame shader; we should really have a decoupled
* horizontal/vertical two pass shader for the gaussian blur
*/
* Since: 1.4
*/
typedef struct _ClutterBlurEffect ClutterBlurEffect;
+typedef struct _ClutterBlurEffectClass ClutterBlurEffectClass;
GType clutter_blur_effect_get_type (void) G_GNUC_CONST;
gulong capture_id;
guint press_button;
+ ClutterModifierType modifier_state;
guint is_held : 1;
guint is_pressed : 1;
priv->is_held = TRUE;
priv->press_button = clutter_event_get_button (event);
+ priv->modifier_state = clutter_event_get_state (event);
if (priv->stage == NULL)
priv->stage = clutter_actor_get_stage (actor);
{
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
+ ClutterModifierType modifier_state;
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
if (!clutter_actor_contains (actor, clutter_event_get_source (event)))
return FALSE;
+ /* exclude any button-mask so that we can compare
+ * the press and release states properly */
+ modifier_state = clutter_event_get_state (event) &
+ ~(CLUTTER_BUTTON1_MASK |
+ CLUTTER_BUTTON2_MASK |
+ CLUTTER_BUTTON3_MASK |
+ CLUTTER_BUTTON4_MASK |
+ CLUTTER_BUTTON5_MASK);
+
+ /* if press and release states don't match we
+ * simply ignore modifier keys. i.e. modifier keys
+ * are expected to be pressed throughout the whole
+ * click */
+ if (modifier_state != priv->modifier_state)
+ priv->modifier_state = 0;
+
click_action_set_pressed (action, FALSE);
g_signal_emit (action, click_signals[CLICKED], 0, actor);
break;
return action->priv->press_button;
}
+
+/**
+ * clutter_click_action_get_state:
+ * @action: a #ClutterClickAction
+ *
+ * Retrieves the modifier state of the click action.
+ *
+ * Return value: the modifier state parameter, or 0
+ *
+ * Since: 1.6
+ */
+ClutterModifierType
+clutter_click_action_get_state (ClutterClickAction *action)
+{
+ g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
+
+ return action->priv->modifier_state;
+}
#define __CLUTTER_CLICK_ACTION_H__
#include <clutter/clutter-action.h>
+#include <clutter/clutter-event.h>
G_BEGIN_DECLS
ClutterAction *clutter_click_action_new (void);
-guint clutter_click_action_get_button (ClutterClickAction *action);
-void clutter_click_action_release (ClutterClickAction *action);
+guint clutter_click_action_get_button (ClutterClickAction *action);
+ClutterModifierType clutter_click_action_get_state (ClutterClickAction *action);
+void clutter_click_action_release (ClutterClickAction *action);
G_END_DECLS
: "unknown");
/* The final bits of magic:
- * - We need to make sure that when the clone-source actor's paint
- * method calls clutter_actor_get_paint_opacity, it traverses to
- * us and our parent not it's real parent.
+ * - We need to override the paint opacity of the actor with our own
+ * opacity.
+ * - We need to inform the actor that it's in a clone paint (for the function
+ * clutter_actor_is_in_clone_paint())
* - We need to stop clutter_actor_paint applying the model view matrix of
* the clone source actor.
*/
- _clutter_actor_set_opacity_parent (priv->clone_source, self);
+ _clutter_actor_set_in_clone_paint (priv->clone_source, TRUE);
+ _clutter_actor_set_opacity_override (priv->clone_source,
+ clutter_actor_get_paint_opacity (self));
_clutter_actor_set_enable_model_view_transform (priv->clone_source, FALSE);
if (!CLUTTER_ACTOR_IS_MAPPED (priv->clone_source))
_clutter_actor_set_enable_paint_unmapped (priv->clone_source, FALSE);
_clutter_actor_set_enable_model_view_transform (priv->clone_source, TRUE);
- _clutter_actor_set_opacity_parent (priv->clone_source, NULL);
+ _clutter_actor_set_opacity_override (priv->clone_source, -1);
+ _clutter_actor_set_in_clone_paint (priv->clone_source, FALSE);
}
gboolean
* Return value: a pointer to a static color; the returned pointer
* is owned by Clutter and it should never be modified or freed
*
- * Since: 1.4
+ * Since: 1.6
*/
G_CONST_RETURN ClutterColor *
clutter_color_get_static (ClutterStaticColor color)
*
* Named colors, for accessing global colors defined by Clutter
*
- * Since: 1.4
+ * Since: 1.6
*/
typedef enum { /*< prefix=CLUTTER_COLOR >*/
/* CGA/EGA-like palette */
#include "clutter-offscreen-effect.h"
#include "clutter-private.h"
-typedef struct _ClutterColorizeEffectClass ClutterColorizeEffectClass;
-
struct _ClutterColorizeEffect
{
ClutterOffscreenEffect parent_instance;
*
* SinceL 1.4
*/
-typedef struct _ClutterColorizeEffect ClutterColorizeEffect;
+typedef struct _ClutterColorizeEffect ClutterColorizeEffect;
+typedef struct _ClutterColorizeEffectClass ClutterColorizeEffectClass;
GType clutter_colorize_effect_get_type (void) G_GNUC_CONST;
--- /dev/null
+#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <clutter/clutter.h> can be included directly."
+#endif
+
+#ifndef __CLUTTER_CONFIG_H__
+#define __CLUTTER_CONFIG_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+@CLUTTER_CONFIG_DEFINES@
+
+G_END_DECLS
+
+#endif /* __CLUTTER_CONFIG_H__ */
typedef ClutterContainerIface ClutterContainerInterface;
-G_DEFINE_INTERFACE (ClutterContainer, clutter_container, CLUTTER_TYPE_ACTOR);
+G_DEFINE_INTERFACE (ClutterContainer, clutter_container, G_TYPE_OBJECT);
static void
clutter_container_default_init (ClutterContainerInterface *iface)
ClutterActor *actor);
void (* child_notify) (ClutterContainer *container,
- ClutterActor *actor,
+ ClutterActor *child,
GParamSpec *pspec);
};
CLUTTER_DEBUG_MULTISTAGE = 1 << 13,
CLUTTER_DEBUG_ANIMATION = 1 << 14,
CLUTTER_DEBUG_LAYOUT = 1 << 15,
- CLUTTER_DEBUG_PICK = 1 << 16
+ CLUTTER_DEBUG_PICK = 1 << 16,
+ CLUTTER_DEBUG_EVENTLOOP = 1 << 17
} ClutterDebugFlag;
typedef enum {
#include "clutter-offscreen-effect.h"
#include "clutter-private.h"
-typedef struct _ClutterDesaturateEffectClass ClutterDesaturateEffectClass;
-
struct _ClutterDesaturateEffect
{
ClutterOffscreenEffect parent_instance;
* Since: 1.4
*/
typedef struct _ClutterDesaturateEffect ClutterDesaturateEffect;
+typedef struct _ClutterDesaturateEffectClass ClutterDesaturateEffectClass;
GType clutter_desaturate_effect_get_type (void) G_GNUC_CONST;
#ifndef __CLUTTER_DEVICE_MANAGER_PRIVATE_H__
#define __CLUTTER_DEVICE_MANAGER_PRIVATE_H__
+#include <clutter/clutter-backend.h>
#include <clutter/clutter-device-manager.h>
#include <clutter/clutter-event.h>
G_BEGIN_DECLS
+typedef struct _ClutterAxisInfo
+{
+ ClutterInputAxis axis;
+
+ gdouble min_axis;
+ gdouble max_axis;
+
+ gdouble min_value;
+ gdouble max_value;
+
+ gdouble resolution;
+} ClutterAxisInfo;
+
+typedef struct _ClutterKeyInfo
+{
+ guint keyval;
+ ClutterModifierType modifiers;
+} ClutterKeyInfo;
+
struct _ClutterInputDevice
{
GObject parent_instance;
gint id;
ClutterInputDeviceType device_type;
+ ClutterInputMode device_mode;
gchar *device_name;
+ ClutterDeviceManager *device_manager;
+
+ ClutterBackend *backend;
+
+ /* the associated device */
+ ClutterInputDevice *associated;
+
+ GList *slaves;
+
/* the actor underneath the pointer */
ClutterActor *cursor_actor;
guint32 previous_time;
gint previous_button_number;
ClutterModifierType previous_state;
+
+ GArray *axes;
+
+ guint n_keys;
+ GArray *keys;
+
+ guint has_cursor : 1;
+ guint is_enabled : 1;
+};
+
+struct _ClutterInputDeviceClass
+{
+ GObjectClass parent_class;
+
+ void (* select_stage_events) (ClutterInputDevice *device,
+ ClutterStage *stage,
+ gint event_mask);
};
/* 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);
+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);
+void _clutter_device_manager_select_stage_events (ClutterDeviceManager *device_manager,
+ ClutterStage *stage,
+ gint event_mask);
+ClutterBackend *_clutter_device_manager_get_backend (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);
+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,
+ gboolean emit_crossing);
+ClutterActor * _clutter_input_device_update (ClutterInputDevice *device,
+ gboolean emit_crossing);
+void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
+ guint n_keys);
+guint _clutter_input_device_add_axis (ClutterInputDevice *device,
+ ClutterInputAxis axis,
+ gdouble min_value,
+ gdouble max_value,
+ gdouble resolution);
+void _clutter_input_device_reset_axes (ClutterInputDevice *device);
+
+void _clutter_input_device_set_associated_device (ClutterInputDevice *device,
+ ClutterInputDevice *associated);
+void _clutter_input_device_add_slave (ClutterInputDevice *master,
+ ClutterInputDevice *slave);
+void _clutter_input_device_remove_slave (ClutterInputDevice *master,
+ ClutterInputDevice *slave);
+
+void _clutter_input_device_select_stage_events (ClutterInputDevice *device,
+ ClutterStage *stage,
+ gint event_flags);
+
+gboolean _clutter_input_device_translate_axis (ClutterInputDevice *device,
+ guint index_,
+ gdouble value,
+ gdouble *axis_value);
G_END_DECLS
return manager_class->get_core_device (device_manager, device_type);
}
+void
+_clutter_device_manager_select_stage_events (ClutterDeviceManager *device_manager,
+ ClutterStage *stage,
+ gint event_flags)
+{
+ ClutterDeviceManagerClass *manager_class;
+ const GSList *devices, *d;
+
+ g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
+
+ manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
+ devices = manager_class->get_devices (device_manager);
+
+ for (d = devices; d != NULL; d = d->next)
+ {
+ ClutterInputDevice *device = d->data;
+
+ _clutter_input_device_select_stage_events (device, stage, event_flags);
+ }
+}
+
/*
* _clutter_device_manager_add_device:
* @device_manager: a #ClutterDeviceManager
if (device->stage == NULL)
continue;
- _clutter_input_device_update (device);
+ _clutter_input_device_update (device, TRUE);
}
}
+
+ClutterBackend *
+_clutter_device_manager_get_backend (ClutterDeviceManager *manager)
+{
+ g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (manager), NULL);
+
+ return manager->priv->backend;
+}
#define __CLUTTER_DEVICE_MANAGER_H__
#include <clutter/clutter-input-device.h>
+#include <clutter/clutter-stage.h>
G_BEGIN_DECLS
{
ClutterDragActionPrivate *priv = action->priv;
- priv->motion_events_enabled = clutter_get_motion_events_enabled ();
clutter_set_motion_events_enabled (FALSE);
g_signal_emit (action, drag_signals[DRAG_BEGIN], 0,
&priv->transformed_press_x,
&priv->transformed_press_y);
+ priv->motion_events_enabled = clutter_get_motion_events_enabled ();
+
if (priv->x_drag_threshold == 0 || priv->y_drag_threshold == 0)
emit_drag_begin (action, actor, event);
else
--- /dev/null
+#include "config.h"
+
+#include "clutter-event-translator.h"
+
+#include "clutter-backend.h"
+#include "clutter-private.h"
+
+#define clutter_event_translator_get_type _clutter_event_translator_get_type
+
+typedef ClutterEventTranslatorIface ClutterEventTranslatorInterface;
+
+G_DEFINE_INTERFACE (ClutterEventTranslator, clutter_event_translator, G_TYPE_OBJECT);
+
+static ClutterTranslateReturn
+default_translate_event (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *event)
+{
+ return CLUTTER_TRANSLATE_CONTINUE;
+}
+
+static void
+clutter_event_translator_default_init (ClutterEventTranslatorIface *iface)
+{
+ iface->translate_event = default_translate_event;
+}
+
+ClutterTranslateReturn
+_clutter_event_translator_translate_event (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *translated)
+{
+ ClutterEventTranslatorIface *iface;
+
+ iface = CLUTTER_EVENT_TRANSLATOR_GET_IFACE (translator);
+
+ return iface->translate_event (translator, native, translated);
+}
--- /dev/null
+#ifndef __CLUTTER_EVENT_TRANSLATOR_H__
+#define __CLUTTER_EVENT_TRANSLATOR_H__
+
+#include <glib-object.h>
+#include <clutter/clutter-event.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_EVENT_TRANSLATOR (_clutter_event_translator_get_type ())
+#define CLUTTER_EVENT_TRANSLATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_EVENT_TRANSLATOR, ClutterEventTranslator))
+#define CLUTTER_IS_EVENT_TRANSLATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_EVENT_TRANSLATOR))
+#define CLUTTER_EVENT_TRANSLATOR_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_EVENT_TRANSLATOR, ClutterEventTranslatorIface))
+
+typedef struct _ClutterEventTranslator ClutterEventTranslator;
+typedef struct _ClutterEventTranslatorIface ClutterEventTranslatorIface;
+
+typedef enum {
+ CLUTTER_TRANSLATE_CONTINUE,
+ CLUTTER_TRANSLATE_REMOVE,
+ CLUTTER_TRANSLATE_QUEUE
+} ClutterTranslateReturn;
+
+struct _ClutterEventTranslatorIface
+{
+ GTypeInterface g_iface;
+
+ ClutterTranslateReturn (* translate_event) (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *translated);
+};
+
+GType _clutter_event_translator_get_type (void) G_GNUC_CONST;
+
+ClutterTranslateReturn _clutter_event_translator_translate_event (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *translated);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_EVENT_TRANSLATOR_H__ */
typedef struct _ClutterEventPrivate {
ClutterEvent base;
+ ClutterInputDevice *device;
+ ClutterInputDevice *source_device;
+
gpointer platform_data;
} ClutterEventPrivate;
{
ClutterInputDevice *device = NULL;
- g_return_val_if_fail (event != NULL, -1);
-
- switch (event->type)
- {
- case CLUTTER_NOTHING:
- case CLUTTER_STAGE_STATE:
- case CLUTTER_DESTROY_NOTIFY:
- case CLUTTER_CLIENT_MESSAGE:
- case CLUTTER_DELETE:
- case CLUTTER_ENTER:
- case CLUTTER_LEAVE:
- break;
- case CLUTTER_BUTTON_PRESS:
- case CLUTTER_BUTTON_RELEASE:
- device = event->button.device;
- break;
- case CLUTTER_MOTION:
- device = event->motion.device;
- break;
- case CLUTTER_SCROLL:
- device = event->scroll.device;
- break;
- case CLUTTER_KEY_PRESS:
- case CLUTTER_KEY_RELEASE:
- device = event->scroll.device;
- break;
- }
+ g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
+ device = clutter_event_get_device (event);
if (device != NULL)
return clutter_input_device_get_device_id (device);
- else
- return -1;
+
+ return -1;
}
/**
g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
+ device = clutter_event_get_device (event);
+ if (device != NULL)
+ return clutter_input_device_get_device_type (device);
+
+ return CLUTTER_POINTER_DEVICE;
+}
+
+/**
+ * clutter_event_set_device:
+ * @event: a #ClutterEvent
+ * @device: a #ClutterInputDevice
+ *
+ * Sets the device for @event.
+ *
+ * Since: 1.6
+ */
+void
+clutter_event_set_device (ClutterEvent *event,
+ ClutterInputDevice *device)
+{
+ g_return_if_fail (event != NULL);
+ g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
+
+ if (is_event_allocated (event))
+ {
+ ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
+
+ real_event->device = device;
+ }
+
switch (event->type)
{
case CLUTTER_NOTHING:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
- device = event->button.device;
+ event->button.device = device;
break;
case CLUTTER_MOTION:
- device = event->motion.device;
+ event->motion.device = device;
break;
case CLUTTER_SCROLL:
- device = event->scroll.device;
+ event->scroll.device = device;
break;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
- device = event->scroll.device;
+ event->key.device = device;
break;
}
-
- if (device != NULL)
- return clutter_input_device_get_device_type (device);
- else
- return CLUTTER_POINTER_DEVICE;
}
/**
g_return_val_if_fail (event != NULL, NULL);
+ if (is_event_allocated (event))
+ {
+ ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
+
+ if (real_event->device != NULL)
+ return real_event->device;
+ }
+
switch (event->type)
{
case CLUTTER_NOTHING:
clutter_event_copy (const ClutterEvent *event)
{
ClutterEvent *new_event;
+ ClutterEventPrivate *new_real_event;
+ ClutterInputDevice *device;
+ gint n_axes = 0;
g_return_val_if_fail (event != NULL, NULL);
new_event = clutter_event_new (CLUTTER_NOTHING);
+ new_real_event = (ClutterEventPrivate *) new_event;
+
*new_event = *event;
if (is_event_allocated (event))
+ {
+ ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
+
+ new_real_event->device = real_event->device;
+ new_real_event->source_device = real_event->source_device;
+ }
+
+ device = clutter_event_get_device (event);
+ if (device != NULL)
+ n_axes = clutter_input_device_get_n_axes (device);
+
+ switch (event->type)
+ {
+ case CLUTTER_BUTTON_PRESS:
+ case CLUTTER_BUTTON_RELEASE:
+ if (event->button.axes != NULL)
+ new_event->button.axes = g_memdup (event->button.axes,
+ sizeof (gdouble) * n_axes);
+ break;
+
+ case CLUTTER_SCROLL:
+ if (event->scroll.axes != NULL)
+ new_event->scroll.axes = g_memdup (event->scroll.axes,
+ sizeof (gdouble) * n_axes);
+ break;
+
+ case CLUTTER_MOTION:
+ if (event->motion.axes != NULL)
+ new_event->motion.axes = g_memdup (event->motion.axes,
+ sizeof (gdouble) * n_axes);
+ break;
+
+ default:
+ break;
+ }
+
+ if (is_event_allocated (event))
_clutter_backend_copy_event_data (clutter_get_default_backend (),
event,
new_event);
{
_clutter_backend_free_event_data (clutter_get_default_backend (), event);
+ switch (event->type)
+ {
+ case CLUTTER_BUTTON_PRESS:
+ case CLUTTER_BUTTON_RELEASE:
+ g_free (event->button.axes);
+ break;
+
+ case CLUTTER_MOTION:
+ g_free (event->motion.axes);
+ break;
+
+ case CLUTTER_SCROLL:
+ g_free (event->scroll.axes);
+ break;
+
+ default:
+ break;
+ }
+
g_hash_table_remove (all_events, event);
g_slice_free (ClutterEventPrivate, (ClutterEventPrivate *) event);
}
{
ClutterMainContext *context = _clutter_context_get_default ();
- if (!context->events_queue)
+ if (context->events_queue == NULL)
return NULL;
if (g_queue_is_empty (context->events_queue))
return g_queue_peek_tail (context->events_queue);
}
+void
+_clutter_event_push (const ClutterEvent *event,
+ gboolean do_copy)
+{
+ ClutterMainContext *context = _clutter_context_get_default ();
+ ClutterInputDevice *device;
+
+ g_assert (context != NULL);
+
+ if (context->events_queue == NULL)
+ context->events_queue = g_queue_new ();
+
+ /* disabled devices don't propagate events */
+ device = clutter_event_get_device (event);
+ if (device != NULL)
+ {
+ if (!clutter_input_device_get_enabled (device))
+ return;
+ }
+
+ if (do_copy)
+ {
+ ClutterEvent *copy;
+
+ copy = clutter_event_copy (event);
+ copy->any.flags |= CLUTTER_EVENT_FLAG_SYNTHETIC;
+
+ event = copy;
+ }
+
+ g_queue_push_head (context->events_queue, (gpointer) event);
+}
+
/**
* clutter_event_put:
* @event: a #ClutterEvent
void
clutter_event_put (const ClutterEvent *event)
{
- ClutterMainContext *context = _clutter_context_get_default ();
- ClutterEvent *event_copy;
-
- /* FIXME: check queue is valid */
- g_return_if_fail (context != NULL);
-
- event_copy = clutter_event_copy (event);
- event_copy->any.flags |= CLUTTER_EVENT_FLAG_SYNTHETIC;
-
- g_queue_push_head (context->events_queue, event_copy);
+ _clutter_event_push (event, TRUE);
}
/**
g_return_val_if_fail (context != NULL, FALSE);
- if (!context->events_queue)
+ if (context->events_queue == NULL)
return FALSE;
return g_queue_is_empty (context->events_queue) == FALSE;
return context->current_event;
}
+
+/**
+ * clutter_event_get_source_device:
+ * @event: a #ClutterEvent
+ *
+ * Retrieves the hardware device that originated the event.
+ *
+ * If you need the virtual device, use clutter_event_get_device().
+ *
+ * If no hardware device originated this event, this function will
+ * return the same device as clutter_event_get_device().
+ *
+ * Return value: (transfer none): a pointer to a #ClutterInputDevice
+ * or %NULL
+ *
+ * Since: 1.6
+ */
+ClutterInputDevice *
+clutter_event_get_source_device (const ClutterEvent *event)
+{
+ ClutterEventPrivate *real_event;
+
+ if (!is_event_allocated (event))
+ return NULL;
+
+ real_event = (ClutterEventPrivate *) event;
+
+ if (real_event->source_device != NULL)
+ return real_event->source_device;
+
+ return clutter_event_get_device (event);
+}
+
+void
+_clutter_event_set_device (ClutterEvent *event,
+ ClutterInputDevice *device)
+{
+ switch (event->type)
+ {
+ case CLUTTER_NOTHING:
+ case CLUTTER_STAGE_STATE:
+ case CLUTTER_DESTROY_NOTIFY:
+ case CLUTTER_CLIENT_MESSAGE:
+ case CLUTTER_DELETE:
+ case CLUTTER_ENTER:
+ case CLUTTER_LEAVE:
+ break;
+
+ case CLUTTER_BUTTON_PRESS:
+ case CLUTTER_BUTTON_RELEASE:
+ event->button.device = device;
+ break;
+
+ case CLUTTER_MOTION:
+ event->motion.device = device;
+ break;
+
+ case CLUTTER_SCROLL:
+ event->scroll.device = device;
+ break;
+
+ case CLUTTER_KEY_PRESS:
+ case CLUTTER_KEY_RELEASE:
+ event->key.device = device;
+ break;
+ }
+}
+
+/*< private >
+ * clutter_event_set_source_device:
+ * @event: a #ClutterEvent
+ * @device: a #ClutterInputDevice
+ *
+ * Sets the source #ClutterInputDevice for @event.
+ *
+ * The #ClutterEvent must have been created using clutter_event_new().
+ *
+ * Since: 1.6
+ */
+void
+_clutter_event_set_source_device (ClutterEvent *event,
+ ClutterInputDevice *device)
+{
+ ClutterEventPrivate *real_event;
+
+ if (!is_event_allocated (event))
+ return;
+
+ real_event = (ClutterEventPrivate *) event;
+ real_event->source_device = device;
+}
+
+/**
+ * clutter_event_get_axes:
+ * @event: a #ClutterEvent
+ * @n_axes: (out): return location for the number of axes returned
+ *
+ * Retrieves the array of axes values attached to the event.
+ *
+ * Return value: (transfer none): an array of axis values
+ *
+ * Since: 1.6
+ */
+gdouble *
+clutter_event_get_axes (const ClutterEvent *event,
+ guint *n_axes)
+{
+ gdouble *retval = NULL;
+ guint len = 0;
+
+ switch (event->type)
+ {
+ case CLUTTER_NOTHING:
+ case CLUTTER_STAGE_STATE:
+ case CLUTTER_DESTROY_NOTIFY:
+ case CLUTTER_CLIENT_MESSAGE:
+ case CLUTTER_DELETE:
+ case CLUTTER_ENTER:
+ case CLUTTER_LEAVE:
+ case CLUTTER_KEY_PRESS:
+ case CLUTTER_KEY_RELEASE:
+ break;
+
+ case CLUTTER_SCROLL:
+ retval = event->scroll.axes;
+ break;
+
+ case CLUTTER_BUTTON_PRESS:
+ case CLUTTER_BUTTON_RELEASE:
+ retval = event->button.axes;
+ break;
+
+ case CLUTTER_MOTION:
+ retval = event->motion.axes;
+ break;
+ }
+
+ if (retval != NULL)
+ {
+ ClutterInputDevice *device;
+
+ device = clutter_event_get_device (event);
+ if (device != NULL)
+ len = clutter_input_device_get_n_axes (device);
+ else
+ retval = NULL;
+ }
+
+ if (n_axes)
+ *n_axes = len;
+
+ return retval;
+}
G_BEGIN_DECLS
/**
- * ClutterModifierType:
- * @CLUTTER_SHIFT_MASK: Mask applied by the Shift key
- * @CLUTTER_LOCK_MASK: Mask applied by the Caps Lock key
- * @CLUTTER_CONTROL_MASK: Mask applied by the Control key
- * @CLUTTER_MOD1_MASK: Mask applied by the first Mod key
- * @CLUTTER_MOD2_MASK: Mask applied by the second Mod key
- * @CLUTTER_MOD3_MASK: Mask applied by the third Mod key
- * @CLUTTER_MOD4_MASK: Mask applied by the fourth Mod key
- * @CLUTTER_MOD5_MASK: Mask applied by the fifth Mod key
- * @CLUTTER_BUTTON1_MASK: Mask applied by the first pointer button
- * @CLUTTER_BUTTON2_MASK: Mask applied by the second pointer button
- * @CLUTTER_BUTTON3_MASK: Mask applied by the third pointer button
- * @CLUTTER_BUTTON4_MASK: Mask applied by the fourth pointer button
- * @CLUTTER_BUTTON5_MASK: Mask applied by the fifth pointer button
- * @CLUTTER_SUPER_MASK: Mask applied by the Super key
- * @CLUTTER_HYPER_MASK: Mask applied by the Hyper key
- * @CLUTTER_META_MASK: Mask applied by the Meta key
- * @CLUTTER_RELEASE_MASK: Mask applied during release
- * @CLUTTER_MODIFIER_MASK: A mask covering all modifier types
- *
- * Masks applied to a #ClutterEvent by modifiers.
- *
- * Since: 0.4
- */
-typedef enum {
- CLUTTER_SHIFT_MASK = 1 << 0,
- CLUTTER_LOCK_MASK = 1 << 1,
- CLUTTER_CONTROL_MASK = 1 << 2,
- CLUTTER_MOD1_MASK = 1 << 3,
- CLUTTER_MOD2_MASK = 1 << 4,
- CLUTTER_MOD3_MASK = 1 << 5,
- CLUTTER_MOD4_MASK = 1 << 6,
- CLUTTER_MOD5_MASK = 1 << 7,
- CLUTTER_BUTTON1_MASK = 1 << 8,
- CLUTTER_BUTTON2_MASK = 1 << 9,
- CLUTTER_BUTTON3_MASK = 1 << 10,
- CLUTTER_BUTTON4_MASK = 1 << 11,
- CLUTTER_BUTTON5_MASK = 1 << 12,
-
- /* bits 15 to 25 are currently unused; bit 29 is used internally */
-
- CLUTTER_SUPER_MASK = 1 << 26,
- CLUTTER_HYPER_MASK = 1 << 27,
- CLUTTER_META_MASK = 1 << 28,
-
- CLUTTER_RELEASE_MASK = 1 << 30,
-
- CLUTTER_MODIFIER_MASK = 0x5c001fff
-} ClutterModifierType;
-
-/**
* ClutterEventFlags:
* @CLUTTER_EVENT_NONE: No flag set
* @CLUTTER_EVENT_FLAG_SYNTHETIC: Synthetic event
gint clutter_event_get_device_id (const ClutterEvent *event);
ClutterInputDeviceType clutter_event_get_device_type (const ClutterEvent *event);
ClutterInputDevice * clutter_event_get_device (const ClutterEvent *event);
+ClutterInputDevice * clutter_event_get_source_device (const ClutterEvent *event);
ClutterActor * clutter_event_get_source (const ClutterEvent *event);
ClutterStage * clutter_event_get_stage (const ClutterEvent *event);
void clutter_event_get_coords (const ClutterEvent *event,
gfloat *x,
gfloat *y);
+gdouble * clutter_event_get_axes (const ClutterEvent *event,
+ guint *n_axes);
guint clutter_event_get_key_symbol (const ClutterEvent *event);
guint16 clutter_event_get_key_code (const ClutterEvent *event);
ClutterScrollDirection clutter_event_get_scroll_direction (const ClutterEvent *event);
+void clutter_event_set_device (ClutterEvent *event,
+ ClutterInputDevice *device);
+
guint32 clutter_keysym_to_unicode (guint keyval);
guint32 clutter_get_current_event_time (void);
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
guint clutter_frame_source_add (guint fps,
GSourceFunc func,
*
* An OpenGL based 'interactive canvas' library.
*
- * Copyright (C) 2009 Intel Corp.
+ * Copyright © 2009, 2010, 2011 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "config.h"
#endif
+#include "clutter-input-device.h"
+
#include "clutter-actor-private.h"
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
#include "clutter-enum-types.h"
-#include "clutter-input-device.h"
+#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
{
PROP_0,
+ PROP_BACKEND,
+
PROP_ID,
- PROP_DEVICE_TYPE,
PROP_NAME,
+ PROP_DEVICE_TYPE,
+ PROP_DEVICE_MANAGER,
+ PROP_DEVICE_MODE,
+
+ PROP_HAS_CURSOR,
+ PROP_ENABLED,
+
+ PROP_N_AXES,
+
PROP_LAST
};
-static GParamSpec *obj_props[PROP_LAST];
+static GParamSpec *obj_props[PROP_LAST] = { NULL, };
G_DEFINE_TYPE (ClutterInputDevice, clutter_input_device, G_TYPE_OBJECT);
static void
+clutter_input_device_dispose (GObject *gobject)
+{
+ ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (gobject);
+
+ g_free (device->device_name);
+
+ if (device->device_mode == CLUTTER_INPUT_MODE_SLAVE)
+ _clutter_input_device_remove_slave (device->associated, device);
+
+ if (device->associated != NULL)
+ {
+ _clutter_input_device_set_associated_device (device->associated, NULL);
+ g_object_unref (device->associated);
+ device->associated = NULL;
+ }
+
+ if (device->axes != NULL)
+ {
+ g_array_free (device->axes, TRUE);
+ device->axes = NULL;
+ }
+
+ if (device->keys != NULL)
+ {
+ g_array_free (device->keys, TRUE);
+ device->keys = NULL;
+ }
+
+ G_OBJECT_CLASS (clutter_input_device_parent_class)->dispose (gobject);
+}
+
+static void
clutter_input_device_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
self->device_type = g_value_get_enum (value);
break;
+ case PROP_DEVICE_MANAGER:
+ self->device_manager = g_value_get_object (value);
+ break;
+
+ case PROP_DEVICE_MODE:
+ self->device_mode = g_value_get_enum (value);
+ break;
+
+ case PROP_BACKEND:
+ self->backend = g_value_get_object (value);
+ break;
+
case PROP_NAME:
- self->device_name = g_strdup (g_value_get_string (value));
+ self->device_name = g_value_dup_string (value);
+ break;
+
+ case PROP_HAS_CURSOR:
+ self->has_cursor = g_value_get_boolean (value);
+ break;
+
+ case PROP_ENABLED:
+ clutter_input_device_set_enabled (self, g_value_get_boolean (value));
break;
default:
g_value_set_enum (value, self->device_type);
break;
+ case PROP_DEVICE_MANAGER:
+ g_value_set_object (value, self->device_manager);
+ break;
+
+ case PROP_DEVICE_MODE:
+ g_value_set_enum (value, self->device_mode);
+ break;
+
+ case PROP_BACKEND:
+ g_value_set_object (value, self->backend);
+ break;
+
case PROP_NAME:
g_value_set_string (value, self->device_name);
break;
+ case PROP_HAS_CURSOR:
+ g_value_set_boolean (value, self->has_cursor);
+ break;
+
+ case PROP_N_AXES:
+ g_value_set_uint (value, clutter_input_device_get_n_axes (self));
+ break;
+
+ case PROP_ENABLED:
+ g_value_set_boolean (value, self->is_enabled);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
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:
*
* Since: 1.2
*/
- pspec = g_param_spec_int ("id",
- P_("Id"),
- P_("Unique identifier of the device"),
- -1, G_MAXINT,
- 0,
- CLUTTER_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- obj_props[PROP_ID] = pspec;
- g_object_class_install_property (gobject_class, PROP_ID, pspec);
+ obj_props[PROP_ID] =
+ g_param_spec_int ("id",
+ P_("Id"),
+ P_("Unique identifier of the device"),
+ -1, G_MAXINT,
+ 0,
+ CLUTTER_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
/**
* ClutterInputDevice:name:
*
* Since: 1.2
*/
- pspec = g_param_spec_string ("name",
- P_("Name"),
- P_("The name of the device"),
- NULL,
- CLUTTER_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- obj_props[PROP_NAME] = pspec;
- g_object_class_install_property (gobject_class, PROP_NAME, pspec);
+ obj_props[PROP_NAME] =
+ g_param_spec_string ("name",
+ P_("Name"),
+ P_("The name of the device"),
+ NULL,
+ CLUTTER_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
/**
* ClutterInputDevice:device-type:
*
* Since: 1.2
*/
- pspec = g_param_spec_enum ("device-type",
- P_("Device Type"),
- P_("The type of the device"),
- CLUTTER_TYPE_INPUT_DEVICE_TYPE,
- CLUTTER_POINTER_DEVICE,
- CLUTTER_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- obj_props[PROP_DEVICE_TYPE] = pspec;
- g_object_class_install_property (gobject_class, PROP_DEVICE_TYPE, pspec);
+ obj_props[PROP_DEVICE_TYPE] =
+ g_param_spec_enum ("device-type",
+ P_("Device Type"),
+ P_("The type of the device"),
+ CLUTTER_TYPE_INPUT_DEVICE_TYPE,
+ CLUTTER_POINTER_DEVICE,
+ CLUTTER_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+
+ /**
+ * ClutterInputDevice:device-manager:
+ *
+ * The #ClutterDeviceManager instance which owns the device
+ *
+ * Since: 1.6
+ */
+ obj_props[PROP_DEVICE_MANAGER] =
+ g_param_spec_object ("device-manager",
+ P_("Device Manager"),
+ P_("The device manager instance"),
+ CLUTTER_TYPE_DEVICE_MANAGER,
+ CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ /**
+ * ClutterInputDevice:mode:
+ *
+ * The mode of the device.
+ *
+ * Since: 1.6
+ */
+ obj_props[PROP_DEVICE_MODE] =
+ g_param_spec_enum ("device-mode",
+ P_("Device Mode"),
+ P_("The mode of the device"),
+ CLUTTER_TYPE_INPUT_MODE,
+ CLUTTER_INPUT_MODE_FLOATING,
+ CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ /**
+ * ClutterInputDevice:has-cursor:
+ *
+ * Whether the device has an on screen cursor following its movement.
+ *
+ * Since: 1.6
+ */
+ obj_props[PROP_HAS_CURSOR] =
+ g_param_spec_boolean ("has-cursor",
+ P_("Has Cursor"),
+ P_("Whether the device has a cursor"),
+ FALSE,
+ CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ /**
+ * ClutterInputDevice:enabled:
+ *
+ * Whether the device is enabled.
+ *
+ * A device with the #ClutterInputDevice:device-mode property set
+ * to %CLUTTER_INPUT_MODE_MASTER cannot be disabled.
+ *
+ * A device must be enabled in order to receive events from it.
+ *
+ * Since: 1.6
+ */
+ obj_props[PROP_ENABLED] =
+ g_param_spec_boolean ("enabled",
+ P_("Enabled"),
+ P_("Whether the device is enabled"),
+ FALSE,
+ CLUTTER_PARAM_READWRITE);
+
+ /**
+ * ClutterInputDevice:n-axes:
+ *
+ * The number of axes of the device.
+ *
+ * Since: 1.6
+ */
+ obj_props[PROP_N_AXES] =
+ g_param_spec_uint ("n-axes",
+ P_("Number of Axes"),
+ P_("The number of axes on the device"),
+ 0, G_MAXUINT,
+ 0,
+ CLUTTER_PARAM_READABLE);
+
+ /**
+ * ClutterInputDevice:backend:
+ *
+ * The #ClutterBackend that created the device.
+ *
+ * Since: 1.6
+ */
+ obj_props[PROP_BACKEND] =
+ g_param_spec_object ("backend",
+ P_("Backend"),
+ P_("The backend instance"),
+ CLUTTER_TYPE_BACKEND,
+ CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ gobject_class->dispose = clutter_input_device_dispose;
+ gobject_class->set_property = clutter_input_device_set_property;
+ gobject_class->get_property = clutter_input_device_get_property;
+ g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
}
static void
self->current_state = self->previous_state = 0;
}
-/*
- * _clutter_input_device_set_coords:
+/*< private >
+ * clutter_input_device_set_coords:
* @device: a #ClutterInputDevice
* @x: X coordinate of the device
* @y: Y coordinate of the device
device->current_y = y;
}
-/*
- * _clutter_input_device_set_state:
+/*< private >
+ * clutter_input_device_set_state:
* @device: a #ClutterInputDevice
* @state: a bitmask of modifiers
*
device->current_state = state;
}
-/*
- * _clutter_input_device_set_time:
+/*< private >
+ * clutter_input_device_set_time:
* @device: a #ClutterInputDevice
* @time_: the time
*
device->current_time = time_;
}
-/*
- * cursor_weak_unref:
- *
- * #ClutterInputDevice keeps a weak reference on the actor
+/* #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
*/
device->cursor_actor = NULL;
}
-/*
- * _clutter_input_device_set_stage:
+/*< private >
+ * clutter_input_device_set_stage:
* @device: a #ClutterInputDevice
* @stage: a #ClutterStage or %NULL
*
_clutter_input_device_set_stage (ClutterInputDevice *device,
ClutterStage *stage)
{
- ClutterStage *old_stage;
-
- g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
+ if (device->stage == stage)
+ return;
- old_stage = device->stage;
device->stage = stage;
- /* if we left the stage then we also need to unset the
- * cursor actor (and update its :has-pointer property)
+ /* we leave the ->cursor_actor in place in order to check
+ * if we left the stage without crossing it again; this way
+ * we can emit a leave event on the cursor actor right before
+ * we emit the leave event on the stage.
*/
- if (device->stage == NULL &&
- device->cursor_actor != NULL &&
- device->cursor_actor != CLUTTER_ACTOR (old_stage))
- {
- ClutterEvent cev;
-
- cev.crossing.type = CLUTTER_LEAVE;
- cev.crossing.time = device->current_time;
- cev.crossing.flags = 0;
- cev.crossing.stage = old_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 = device->stage != NULL
- ? CLUTTER_ACTOR (device->stage)
- : CLUTTER_ACTOR (old_stage);
-
- _clutter_stage_queue_event (old_stage, &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;
}
-/*
- * _clutter_input_device_set_actor:
+/*< private >
+ * clutter_input_device_set_actor:
* @device: a #ClutterInputDevice
* @actor: a #ClutterActor
+ * @emit_crossing: %TRUE to emit crossing events
*
* Sets the actor under the pointer coordinates of @device
*
*/
void
_clutter_input_device_set_actor (ClutterInputDevice *device,
- ClutterActor *actor)
+ ClutterActor *actor,
+ gboolean emit_crossing)
{
ClutterActor *old_actor;
- ClutterEvent cev;
- g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
-
- if (actor == device->cursor_actor)
+ if (device->cursor_actor == 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);
+ if (emit_crossing)
+ {
+ ClutterEvent *event;
+
+ event = clutter_event_new (CLUTTER_LEAVE);
+ event->crossing.time = device->current_time;
+ event->crossing.flags = 0;
+ event->crossing.stage = device->stage;
+ event->crossing.source = device->cursor_actor;
+ event->crossing.x = device->current_x;
+ event->crossing.y = device->current_y;
+ event->crossing.related = actor;
+ clutter_event_set_device (event, device);
+
+ /* 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
+ * ourselves
+ */
+ _clutter_process_event (event);
+
+ clutter_event_free (event);
+ }
/* processing the event might have destroyed the actor */
if (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.x = device->current_x;
- cev.crossing.y = device->current_y;
- cev.crossing.device = device;
-
- CLUTTER_NOTE (EVENT, "Device '%s' entering '%s' at %d, %d",
- device->device_name,
- clutter_actor_get_name (actor) != NULL
- ? clutter_actor_get_name (actor)
- : G_OBJECT_TYPE_NAME (actor),
- device->current_x,
- device->current_y);
-
- /* if there is an actor overlapping the Stage boundary and we
- * don't do this check then we'll emit an ENTER event only on
- * the actor instead of emitting it on the Stage *and* the
- * actor
- */
- if (old_actor == NULL && actor != CLUTTER_ACTOR (device->stage))
+ if (emit_crossing)
{
- cev.crossing.source = CLUTTER_ACTOR (device->stage);
- cev.crossing.related = NULL;
-
- CLUTTER_NOTE (EVENT, "Adding Crossing[Enter] event for Stage");
-
- _clutter_process_event (&cev);
-
- cev.crossing.source = actor;
- cev.crossing.related = CLUTTER_ACTOR (device->stage);
- }
- else
- {
- cev.crossing.source = actor;
- cev.crossing.related = old_actor;
+ ClutterEvent *event;
+
+ event = clutter_event_new (CLUTTER_ENTER);
+ event->crossing.time = device->current_time;
+ event->crossing.flags = 0;
+ event->crossing.stage = device->stage;
+ event->crossing.x = device->current_x;
+ event->crossing.y = device->current_y;
+ event->crossing.source = actor;
+ event->crossing.related = old_actor;
+ clutter_event_set_device (event, device);
+
+ /* see above */
+ _clutter_process_event (event);
+
+ clutter_event_free (event);
}
-
- /* 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),
}
/**
+ * clutter_input_device_set_enabled:
+ * @device: a #ClutterInputDevice
+ * @enabled: %TRUE to enable the @device
+ *
+ * Enables or disables a #ClutterInputDevice.
+ *
+ * Only devices with a #ClutterInputDevice:device-mode property set
+ * to %CLUTTER_INPUT_MODE_SLAVE or %CLUTTER_INPUT_MODE_FLOATING can
+ * be disabled.
+ *
+ * Since: 1.6
+ */
+void
+clutter_input_device_set_enabled (ClutterInputDevice *device,
+ gboolean enabled)
+{
+ g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
+
+ enabled = !!enabled;
+
+ if (!enabled && device->device_mode == CLUTTER_INPUT_MODE_MASTER)
+ return;
+
+ if (device->is_enabled == enabled)
+ return;
+
+ device->is_enabled = enabled;
+
+ g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_ENABLED]);
+}
+
+/**
+ * clutter_input_device_get_enabled:
+ * @device: a #ClutterInputDevice
+ *
+ * Retrieves whether @device is enabled.
+ *
+ * Return value: %TRUE if the device is enabled
+ *
+ * Since: 1.6
+ */
+gboolean
+clutter_input_device_get_enabled (ClutterInputDevice *device)
+{
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
+
+ return device->is_enabled;
+}
+
+/**
* clutter_input_device_get_device_coords:
* @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
* @x: (out): return location for the X coordinate
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;
* Since: 1.2
*/
ClutterActor *
-_clutter_input_device_update (ClutterInputDevice *device)
+_clutter_input_device_update (ClutterInputDevice *device,
+ gboolean emit_crossing)
{
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);
+ if (device->device_type == CLUTTER_KEYBOARD_DEVICE)
+ return NULL;
stage = device->stage;
if (G_UNLIKELY (stage == NULL))
if (new_cursor_actor == old_cursor_actor)
return old_cursor_actor;
- _clutter_input_device_set_actor (device, new_cursor_actor);
+ _clutter_input_device_set_actor (device, new_cursor_actor, emit_crossing);
return device->cursor_actor;
}
}
/**
+ * clutter_input_device_get_has_cursor:
+ * @device: a #ClutterInputDevice
+ *
+ * Retrieves whether @device has a pointer that follows the
+ * device motion.
+ *
+ * Return value: %TRUE if the device has a cursor
+ *
+ * Since: 1.6
+ */
+gboolean
+clutter_input_device_get_has_cursor (ClutterInputDevice *device)
+{
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
+
+ return device->has_cursor;
+}
+
+/**
+ * clutter_input_device_get_device_mode:
+ * @device: a #ClutterInputDevice
+ *
+ * Retrieves the #ClutterInputMode of @device.
+ *
+ * Return value: the device mode
+ *
+ * Since: 1.6
+ */
+ClutterInputMode
+clutter_input_device_get_device_mode (ClutterInputDevice *device)
+{
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
+ CLUTTER_INPUT_MODE_FLOATING);
+
+ return device->device_mode;
+}
+
+/**
* clutter_input_device_update_from_event:
* @device: a #ClutterInputDevice
* @event: a #ClutterEvent
if (update_stage)
_clutter_input_device_set_stage (device, event_stage);
}
+
+/*< private >
+ * clutter_input_device_reset_axes:
+ * @device: a #ClutterInputDevice
+ *
+ * Resets the axes on @device
+ */
+void
+_clutter_input_device_reset_axes (ClutterInputDevice *device)
+{
+ if (device->axes != NULL)
+ {
+ g_array_free (device->axes, TRUE);
+ device->axes = NULL;
+
+ g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_N_AXES]);
+ }
+}
+
+/*< private >
+ * clutter_input_device_add_axis:
+ * @device: a #ClutterInputDevice
+ * @axis: the axis type
+ * @minimum: the minimum axis value
+ * @maximum: the maximum axis value
+ * @resolution: the axis resolution
+ *
+ * Adds an axis of type @axis on @device.
+ */
+guint
+_clutter_input_device_add_axis (ClutterInputDevice *device,
+ ClutterInputAxis axis,
+ gdouble minimum,
+ gdouble maximum,
+ gdouble resolution)
+{
+ ClutterAxisInfo info;
+ guint pos;
+
+ if (device->axes == NULL)
+ device->axes = g_array_new (FALSE, TRUE, sizeof (ClutterAxisInfo));
+
+ info.axis = axis;
+ info.min_value = minimum;
+ info.max_value = maximum;
+ info.resolution = resolution;
+
+ switch (axis)
+ {
+ case CLUTTER_INPUT_AXIS_X:
+ case CLUTTER_INPUT_AXIS_Y:
+ info.min_axis = 0;
+ info.max_axis = 0;
+ break;
+
+ case CLUTTER_INPUT_AXIS_XTILT:
+ case CLUTTER_INPUT_AXIS_YTILT:
+ info.min_axis = -1;
+ info.max_axis = 1;
+ break;
+
+ default:
+ info.min_axis = 0;
+ info.max_axis = 1;
+ break;
+ }
+
+ device->axes = g_array_append_val (device->axes, info);
+ pos = device->axes->len - 1;
+
+ g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_N_AXES]);
+
+ return pos;
+}
+
+/*< private >
+ * clutter_input_translate_axis:
+ * @device: a #ClutterInputDevice
+ * @index_: the index of the axis
+ * @gint: the absolute value of the axis
+ * @axis_value: (out): the translated value of the axis
+ *
+ * Performs a conversion from the absolute value of the axis
+ * to a relative value.
+ *
+ * The axis at @index_ must not be %CLUTTER_INPUT_AXIS_X or
+ * %CLUTTER_INPUT_AXIS_Y.
+ *
+ * Return value: %TRUE if the conversion was successful
+ */
+gboolean
+_clutter_input_device_translate_axis (ClutterInputDevice *device,
+ guint index_,
+ gdouble value,
+ gdouble *axis_value)
+{
+ ClutterAxisInfo *info;
+ gdouble width;
+ gdouble real_value;
+
+ if (device->axes == NULL || index_ >= device->axes->len)
+ return FALSE;
+
+ info = &g_array_index (device->axes, ClutterAxisInfo, index_);
+
+ if (info->axis == CLUTTER_INPUT_AXIS_X ||
+ info->axis == CLUTTER_INPUT_AXIS_Y)
+ return FALSE;
+
+ width = info->max_value - info->min_value;
+ real_value = (info->max_axis * (value - info->min_value)
+ + info->min_axis * (info->max_value - value))
+ / width;
+
+ if (axis_value)
+ *axis_value = real_value;
+
+ return TRUE;
+}
+
+/**
+ * clutter_input_device_get_axis:
+ * @device: a #ClutterInputDevice
+ * @index_: the index of the axis
+ *
+ * Retrieves the type of axis on @device at the given index.
+ *
+ * Return value: the axis type
+ *
+ * Since: 1.6
+ */
+ClutterInputAxis
+clutter_input_device_get_axis (ClutterInputDevice *device,
+ guint index_)
+{
+ ClutterAxisInfo *info;
+
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
+ CLUTTER_INPUT_AXIS_IGNORE);
+
+ if (device->axes == NULL)
+ return CLUTTER_INPUT_AXIS_IGNORE;
+
+ if (index_ >= device->axes->len)
+ return CLUTTER_INPUT_AXIS_IGNORE;
+
+ info = &g_array_index (device->axes, ClutterAxisInfo, index_);
+
+ return info->axis;
+}
+
+/**
+ * clutter_input_device_get_axis_value:
+ * @device: a #ClutterInputDevice
+ * @axes: (array): an array of axes values, typically
+ * coming from clutter_event_get_axes()
+ * @axis: the axis to extract
+ * @value: (out): return location for the axis value
+ *
+ * Extracts the value of the given @axis of a #ClutterInputDevice from
+ * an array of axis values.
+ *
+ * An example of typical usage for this function is:
+ *
+ * |[
+ * ClutterInputDevice *device = clutter_event_get_device (event);
+ * gdouble *axes = clutter_event_get_axes (event, NULL);
+ * gdouble pressure_value = 0;
+ *
+ * clutter_input_device_get_axis_value (device, axes,
+ * CLUTTER_INPUT_AXIS_PRESSURE,
+ * &pressure_value);
+ * ]|
+ *
+ * Return value: %TRUE if the value was set, and %FALSE otherwise
+ *
+ * Since: 1.6
+ */
+gboolean
+clutter_input_device_get_axis_value (ClutterInputDevice *device,
+ gdouble *axes,
+ ClutterInputAxis axis,
+ gdouble *value)
+{
+ gint i;
+
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
+ g_return_val_if_fail (device->axes != NULL, FALSE);
+
+ for (i = 0; i < device->axes->len; i++)
+ {
+ ClutterAxisInfo *info;
+
+ info = &g_array_index (device->axes, ClutterAxisInfo, i);
+
+ if (info->axis == axis)
+ {
+ if (value)
+ *value = axes[i];
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * clutter_input_device_get_n_axes:
+ * @device: a #ClutterInputDevice
+ *
+ * Retrieves the number of axes available on @device.
+ *
+ * Return value: the number of axes on the device
+ *
+ * Since: 1.6
+ */
+guint
+clutter_input_device_get_n_axes (ClutterInputDevice *device)
+{
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0);
+
+ if (device->axes != NULL)
+ return device->axes->len;
+
+ return 0;
+}
+
+/*< private >
+ * clutter_input_device_set_n_keys:
+ * @device: a #ClutterInputDevice
+ * @n_keys: the number of keys of the device
+ *
+ * Initializes the keys of @device.
+ *
+ * Call clutter_input_device_set_key() on each key to set the keyval
+ * and modifiers.
+ */
+void
+_clutter_input_device_set_n_keys (ClutterInputDevice *device,
+ guint n_keys)
+{
+ if (device->keys != NULL)
+ g_array_free (device->keys, TRUE);
+
+ device->n_keys = n_keys;
+ device->keys = g_array_sized_new (FALSE, TRUE,
+ sizeof (ClutterKeyInfo),
+ n_keys);
+}
+
+/**
+ * clutter_input_device_get_n_keys:
+ * @device: a #ClutterInputDevice
+ *
+ * Retrieves the number of keys registered for @device.
+ *
+ * Return value: the number of registered keys
+ *
+ * Since: 1.6
+ */
+guint
+clutter_input_device_get_n_keys (ClutterInputDevice *device)
+{
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0);
+
+ return device->n_keys;
+}
+
+/**
+ * clutter_input_device_set_key:
+ * @device: a #ClutterInputDevice
+ * @index_: the index of the key
+ * @keyval: the keyval
+ * @modifiers: a bitmask of modifiers
+ *
+ * Sets the keyval and modifiers at the given @index_ for @device.
+ *
+ * Clutter will use the keyval and modifiers set when filling out
+ * an event coming from the same input device.
+ *
+ * Since: 1.6
+ */
+void
+clutter_input_device_set_key (ClutterInputDevice *device,
+ guint index_,
+ guint keyval,
+ ClutterModifierType modifiers)
+{
+ ClutterKeyInfo *key_info;
+
+ g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
+ g_return_if_fail (index_ < device->n_keys);
+
+ key_info = &g_array_index (device->keys, ClutterKeyInfo, index_);
+ key_info->keyval = keyval;
+ key_info->modifiers = modifiers;
+}
+
+/**
+ * clutter_input_device_get_key:
+ * @device: a #ClutterInputDevice
+ * @index_: the index of the key
+ * @keyval: (out): return location for the keyval at @index_
+ * @modifiers: (out): return location for the modifiers at @index_
+ *
+ * Retrieves the key set using clutter_input_device_set_key()
+ *
+ * Return value: %TRUE if a key was set at the given index
+ *
+ * Since: 1.6
+ */
+gboolean
+clutter_input_device_get_key (ClutterInputDevice *device,
+ guint index_,
+ guint *keyval,
+ ClutterModifierType *modifiers)
+{
+ ClutterKeyInfo *key_info;
+
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
+
+ if (device->keys == NULL)
+ return FALSE;
+
+ if (index_ > device->keys->len)
+ return FALSE;
+
+ key_info = &g_array_index (device->keys, ClutterKeyInfo, index_);
+
+ if (!key_info->keyval && !key_info->modifiers)
+ return FALSE;
+
+ if (keyval)
+ *keyval = key_info->keyval;
+
+ if (modifiers)
+ *modifiers = key_info->modifiers;
+
+ return TRUE;
+}
+
+/*< private >
+ * clutter_input_device_add_slave:
+ * @master: a #ClutterInputDevice
+ * @slave: a #ClutterInputDevice
+ *
+ * Adds @slave to the list of slave devices of @master
+ *
+ * This function does not increase the reference count of either @master
+ * or @slave.
+ */
+void
+_clutter_input_device_add_slave (ClutterInputDevice *master,
+ ClutterInputDevice *slave)
+{
+ if (g_list_find (master->slaves, slave) == NULL)
+ master->slaves = g_list_prepend (master->slaves, slave);
+}
+
+/*< private >
+ * clutter_input_device_remove_slave:
+ * @master: a #ClutterInputDevice
+ * @slave: a #ClutterInputDevice
+ *
+ * Removes @slave from the list of slave devices of @master.
+ *
+ * This function does not decrease the reference count of either @master
+ * or @slave.
+ */
+void
+_clutter_input_device_remove_slave (ClutterInputDevice *master,
+ ClutterInputDevice *slave)
+{
+ if (g_list_find (master->slaves, slave) != NULL)
+ master->slaves = g_list_remove (master->slaves, slave);
+}
+
+/**
+ * clutter_input_device_get_slave_devices:
+ * @device: a #ClutterInputDevice
+ *
+ * Retrieves the slave devices attached to @device.
+ *
+ * Return value: (transfer container) (element-type Clutter.InputDevice): a
+ * list of #ClutterInputDevice, or %NULL. The contents of the list are
+ * owned by the device. Use g_list_free() when done
+ *
+ * Since: 1.6
+ */
+GList *
+clutter_input_device_get_slave_devices (ClutterInputDevice *device)
+{
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
+
+ return g_list_copy (device->slaves);
+}
+
+/*< internal >
+ * clutter_input_device_set_associated_device:
+ * @device: a #ClutterInputDevice
+ * @associated: (allow-none): a #ClutterInputDevice, or %NULL
+ *
+ * Sets the associated device for @device.
+ *
+ * This function keeps a reference on the associated device.
+ */
+void
+_clutter_input_device_set_associated_device (ClutterInputDevice *device,
+ ClutterInputDevice *associated)
+{
+ if (device->associated == associated)
+ return;
+
+ if (device->associated != NULL)
+ g_object_unref (device->associated);
+
+ device->associated = associated;
+ if (device->associated != NULL)
+ g_object_ref (device->associated);
+
+ CLUTTER_NOTE (MISC, "Associating device '%s' to device '%s'",
+ clutter_input_device_get_device_name (device),
+ device->associated != NULL
+ ? clutter_input_device_get_device_name (device->associated)
+ : "(none)");
+
+ if (device->device_mode != CLUTTER_INPUT_MODE_MASTER)
+ {
+ if (device->associated != NULL)
+ device->device_mode = CLUTTER_INPUT_MODE_SLAVE;
+ else
+ device->device_mode = CLUTTER_INPUT_MODE_FLOATING;
+
+ g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_DEVICE_MODE]);
+ }
+}
+
+/**
+ * clutter_input_device_get_associated_device:
+ * @device: a #ClutterInputDevice
+ *
+ * Retrieves a pointer to the #ClutterInputDevice that has been
+ * associated to @device.
+ *
+ * If the #ClutterInputDevice:device-mode property of @device is
+ * set to %CLUTTER_INPUT_MODE_MASTER, this function will return
+ * %NULL.
+ *
+ * Return value: (transfer none): a #ClutterInputDevice, or %NULL
+ *
+ * Since: 1.6
+ */
+ClutterInputDevice *
+clutter_input_device_get_associated_device (ClutterInputDevice *device)
+{
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
+
+ return device->associated;
+}
+
+/*< internal >
+ * clutter_input_device_select_stage_events:
+ * @device: a #ClutterInputDevice
+ * @stage: the #ClutterStage to select events on
+ * @event_mask: platform-specific mask of events
+ *
+ * Selects input device events on @stage.
+ *
+ * The implementation of this function depends on the backend used.
+ */
+void
+_clutter_input_device_select_stage_events (ClutterInputDevice *device,
+ ClutterStage *stage,
+ gint event_mask)
+{
+ ClutterInputDeviceClass *device_class;
+
+ device_class = CLUTTER_INPUT_DEVICE_GET_CLASS (device);
+ if (device_class->select_stage_events != NULL)
+ device_class->select_stage_events (device, stage, event_mask);
+}
*
* An OpenGL based 'interactive canvas' library.
*
- * Copyright (C) 2009 Intel Corp.
+ * Copyright © 2009, 2010, 2011 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* @CLUTTER_TABLET_DEVICE: A tablet device
* @CLUTTER_TOUCHPAD_DEVICE: A touchpad device
* @CLUTTER_TOUCHSCREEN_DEVICE: A touch screen device
+ * @CLUTTER_PEN_DEVICE: A pen device
+ * @CLUTTER_ERASER_DEVICE: An eraser device
+ * @CLUTTER_CURSOR_DEVICE: A cursor device
* @CLUTTER_N_DEVICE_TYPES: The number of device types
*
* The types of input devices available.
CLUTTER_TABLET_DEVICE,
CLUTTER_TOUCHPAD_DEVICE,
CLUTTER_TOUCHSCREEN_DEVICE,
+ CLUTTER_PEN_DEVICE,
+ CLUTTER_ERASER_DEVICE,
+ CLUTTER_CURSOR_DEVICE,
CLUTTER_N_DEVICE_TYPES
} ClutterInputDeviceType;
/**
- * ClutterInputDeviceClass:
+ * ClutterInputMode:
+ * @CLUTTER_INPUT_MODE_MASTER: A master, virtual device
+ * @CLUTTER_INPUT_MODE_SLAVE: A slave, physical device, attached to
+ * a master device
+ * @CLUTTER_INPUT_MODE_FLOATING: A slave, physical device, not attached
+ * to a master device
*
- * The #ClutterInputDeviceClass structure contains only private
- * data and should not be accessed directly
+ * The mode for input devices available.
*
- * Since: 1.2
+ * Since: 1.6
*/
-struct _ClutterInputDeviceClass
-{
- /*< private >*/
- GObjectClass parent_class;
-};
+typedef enum {
+ CLUTTER_INPUT_MODE_MASTER,
+ CLUTTER_INPUT_MODE_SLAVE,
+ CLUTTER_INPUT_MODE_FLOATING
+} ClutterInputMode;
+
+/**
+ * ClutterInputAxis:
+ * @CLUTTER_INPUT_AXIS_IGNORE: Unused axis
+ * @CLUTTER_INPUT_AXIS_X: The position on the X axis
+ * @CLUTTER_INPUT_AXIS_Y: The position of the Y axis
+ * @CLUTTER_INPUT_AXIS_PRESSURE: The pressure information
+ * @CLUTTER_INPUT_AXIS_XTILT: The tilt on the X axis
+ * @CLUTTER_INPUT_AXIS_YTILT: The tile on the Y axis
+ * @CLUTTER_INPUT_AXIS_WHEEL: A wheel
+ *
+ * The type of axes Clutter recognizes on a #ClutterInputDevice
+ *
+ * Since: 1.6
+ */
+typedef enum {
+ CLUTTER_INPUT_AXIS_IGNORE,
+ CLUTTER_INPUT_AXIS_X,
+ CLUTTER_INPUT_AXIS_Y,
+ CLUTTER_INPUT_AXIS_PRESSURE,
+ CLUTTER_INPUT_AXIS_XTILT,
+ CLUTTER_INPUT_AXIS_YTILT,
+ CLUTTER_INPUT_AXIS_WHEEL
+} ClutterInputAxis;
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);
-ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device);
-G_CONST_RETURN gchar * clutter_input_device_get_device_name (ClutterInputDevice *device);
-
-void clutter_input_device_update_from_event (ClutterInputDevice *device,
- ClutterEvent *event,
- gboolean update_stage);
+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);
+ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device);
+G_CONST_RETURN gchar * clutter_input_device_get_device_name (ClutterInputDevice *device);
+ClutterInputMode clutter_input_device_get_device_mode (ClutterInputDevice *device);
+gboolean clutter_input_device_get_has_cursor (ClutterInputDevice *device);
+void clutter_input_device_set_enabled (ClutterInputDevice *device,
+ gboolean enabled);
+gboolean clutter_input_device_get_enabled (ClutterInputDevice *device);
+
+guint clutter_input_device_get_n_axes (ClutterInputDevice *device);
+ClutterInputAxis clutter_input_device_get_axis (ClutterInputDevice *device,
+ guint index_);
+gboolean clutter_input_device_get_axis_value (ClutterInputDevice *device,
+ gdouble *axes,
+ ClutterInputAxis axis,
+ gdouble *value);
+
+guint clutter_input_device_get_n_keys (ClutterInputDevice *device);
+void clutter_input_device_set_key (ClutterInputDevice *device,
+ guint index_,
+ guint keyval,
+ ClutterModifierType modifiers);
+gboolean clutter_input_device_get_key (ClutterInputDevice *device,
+ guint index_,
+ guint *keyval,
+ ClutterModifierType *modifiers);
+
+ClutterInputDevice * clutter_input_device_get_associated_device (ClutterInputDevice *device);
+GList * clutter_input_device_get_slave_devices (ClutterInputDevice *device);
+
+void clutter_input_device_update_from_event (ClutterInputDevice *device,
+ ClutterEvent *event,
+ gboolean update_stage);
G_END_DECLS
&sort_closure);
}
+static guint
+clutter_list_model_get_n_rows (ClutterModel *model)
+{
+ ClutterListModel *list_model = CLUTTER_LIST_MODEL (model);
+
+ /* short-circuit in case we don't have a filter in place */
+ if (!clutter_model_get_filter_set (model))
+ return g_sequence_get_length (list_model->priv->sequence);
+
+ return CLUTTER_MODEL_CLASS (clutter_list_model_parent_class)->get_n_rows (model);
+}
+
static void
clutter_list_model_row_removed (ClutterModel *model,
ClutterModelIter *iter)
model_class->insert_row = clutter_list_model_insert_row;
model_class->remove_row = clutter_list_model_remove_row;
model_class->resort = clutter_list_model_resort;
+ model_class->get_n_rows = clutter_list_model_get_n_rows;
model_class->row_removed = clutter_list_model_row_removed;
}
return context->motion_events_per_actor;
}
-guint _clutter_pix_to_id (guchar pixel[4]);
+static inline ClutterActor *
+_clutter_actor_get_by_id (guint32 id)
+{
+ ClutterMainContext *context = _clutter_context_get_default ();
+
+ g_assert (context->id_pool != NULL);
+
+ return clutter_id_pool_lookup (context->id_pool, id);
+}
void
_clutter_id_to_color (guint id, ClutterColor *col)
}
id = _clutter_pixel_to_id (pixel);
- actor = clutter_get_actor_by_gid (id);
+ actor = _clutter_actor_get_by_id (id);
goto result;
}
else
_clutter_stage_set_pick_buffer_valid (stage, TRUE, mode);
- /* Make sure Cogl flushes any batched geometry to the GPU driver */
- cogl_flush ();
-
/* Read the color of the screen co-ords pixel. RGBA_8888_PRE is used
even though we don't care about the alpha component because under
GLES this is the only format that is guaranteed to work so Cogl
}
id = _clutter_pixel_to_id (pixel);
- actor = clutter_get_actor_by_gid (id);
+ actor = _clutter_actor_get_by_id (id);
result:
/* reentrancy check */
if (lock != FALSE)
{
- g_warning ("Tried emitting event during event delivery, bailing out.n");
+ g_warning ("Tried emitting event during event delivery, bailing out.");
return;
}
gfloat x,
gfloat y)
{
+ gfloat width, height;
+
+ clutter_actor_get_size (stage, &width, &height);
+
return (x < 0 ||
y < 0 ||
- x >= clutter_actor_get_width (stage) ||
- y >= clutter_actor_get_height (stage));
+ x >= width ||
+ y >= height);
}
/**
* clutter_do_event
* @event: a #ClutterEvent.
*
- * Processes an event. This function should never be called by applications.
+ * Processes an event.
+ *
+ * The @event must be a valid #ClutterEvent and have a #ClutterStage
+ * associated to it.
+ *
+ * This function is only useful when embedding Clutter inside another
+ * toolkit, and it should never be called by applications.
*
* Since: 0.4
*/
void
clutter_do_event (ClutterEvent *event)
{
- if (!event->any.stage)
+ /* we need the stage for the event */
+ if (event->any.stage == NULL)
+ {
+ g_warning ("%s: Event does not have a stage: discarding.", G_STRFUNC);
+ return;
+ }
+
+ /* stages in destruction do not process events */
+ if (CLUTTER_ACTOR_IN_DESTRUCTION (event->any.stage))
return;
/* Instead of processing events when received, we queue them up to
event->any.source = stage;
break;
- case CLUTTER_LEAVE:
- case CLUTTER_ENTER:
- emit_pointer_event (event, device);
- break;
-
- case CLUTTER_DESTROY_NOTIFY:
- case CLUTTER_DELETE:
- event->any.source = stage;
- /* the stage did not handle the event, so we just quit */
- clutter_stage_event (CLUTTER_STAGE (stage), event);
- break;
-
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
{
}
break;
+ case CLUTTER_ENTER:
+ /* if we're entering from outside the stage we need
+ * to check whether the pointer is actually on another
+ * actor, and emit an additional pointer event
+ */
+ if (event->any.source == stage &&
+ event->crossing.related == NULL)
+ {
+ ClutterActor *actor = NULL;
+
+ emit_pointer_event (event, device);
+
+ actor = _clutter_input_device_update (device, FALSE);
+ if (actor != stage)
+ {
+ ClutterEvent *crossing;
+
+ /* we emit the exact same event on the actor */
+ crossing = clutter_event_copy (event);
+ crossing->crossing.related = stage;
+ crossing->crossing.source = actor;
+
+ emit_pointer_event (crossing, device);
+ clutter_event_free (crossing);
+ }
+ }
+ else
+ emit_pointer_event (event, device);
+ break;
+
+ case CLUTTER_LEAVE:
+ /* same as CLUTTER_ENTER above: when leaving the stage
+ * we need to also emit a CLUTTER_LEAVE event on the
+ * actor currently underneath the device, unless it's the
+ * stage
+ */
+ if (event->any.source == stage &&
+ event->crossing.related == NULL &&
+ device->cursor_actor != stage)
+ {
+ ClutterEvent *crossing;
+
+ crossing = clutter_event_copy (event);
+ crossing->crossing.related = stage;
+ crossing->crossing.source = device->cursor_actor;
+
+ emit_pointer_event (crossing, device);
+ clutter_event_free (crossing);
+ }
+ emit_pointer_event (event, device);
+ break;
+
+ case CLUTTER_DESTROY_NOTIFY:
+ case CLUTTER_DELETE:
+ event->any.source = stage;
+ /* the stage did not handle the event, so we just quit */
+ clutter_stage_event (CLUTTER_STAGE (stage), event);
+ break;
+
case CLUTTER_MOTION:
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
* and the event is not a synthetic event with source set.
* get the actor underneath
*/
if (device != NULL)
- actor = _clutter_input_device_update (device);
+ actor = _clutter_input_device_update (device, TRUE);
else
{
CLUTTER_NOTE (EVENT, "No device found: picking");
actor = event->any.source;
}
- /* FIXME: for an optimisation should check if there are
- * actually any reactive actors and avoid the pick all together
- * (signalling just the stage). Should be big help for gles.
- */
-
CLUTTER_NOTE (EVENT,
"Reactive event received at %.2f, %.2f - actor: %p",
x, y,
context->current_event = NULL;
}
-
/**
* clutter_get_actor_by_gid:
* @id: a #ClutterActor ID.
*
* Since: 0.6
*/
-ClutterActor*
+ClutterActor *
clutter_get_actor_by_gid (guint32 id)
{
- ClutterMainContext *context;
-
- context = _clutter_context_get_default ();
-
- g_return_val_if_fail (context != NULL, NULL);
-
- return CLUTTER_ACTOR (clutter_id_pool_lookup (context->id_pool, id));
+ return _clutter_actor_get_by_id (id);
}
void
{
return clutter_text_direction;
}
+
+/*< private >
+ * clutter_clear_events_queue:
+ *
+ * Clears the events queue stored in the main context.
+ */
+void
+_clutter_clear_events_queue (void)
+{
+ ClutterMainContext *context = _clutter_context_get_default ();
+
+ if (context->events_queue != NULL)
+ {
+ g_queue_foreach (context->events_queue,
+ (GFunc) clutter_event_free,
+ NULL);
+ g_queue_free (context->events_queue);
+ context->events_queue = NULL;
+ }
+}
+
+void
+_clutter_clear_events_queue_for_stage (ClutterStage *stage)
+{
+ ClutterMainContext *context = _clutter_context_get_default ();
+ GList *l, *next;
+
+ if (context->events_queue == NULL)
+ return;
+
+ /* Remove any pending events for this stage from the event queue */
+ for (l = context->events_queue->head; l; l = next)
+ {
+ ClutterEvent *event = l->data;
+
+ next = l->next;
+
+ if (event->any.stage == stage)
+ {
+ g_queue_delete_link (context->events_queue, l);
+ clutter_event_free (event);
+ }
+ }
+}
VOID:OBJECT
VOID:OBJECT,FLOAT,FLOAT
VOID:OBJECT,FLOAT,FLOAT,FLAGS
+VOID:OBJECT,INT
VOID:OBJECT,PARAM
VOID:OBJECT,POINTER
VOID:OBJECT,UINT
* <refsect2 id="ClutterModel-script">
* <title>ClutterModel custom properties for #ClutterScript</title>
* <para>#ClutterModel defines a custom property "columns" for #ClutterScript
- * which allows defining the column names and types.</para>
- * <example id="ClutterModel-script-column-example">
- * <title>Example of the "columns" custom property</title>
+ * which allows defining the column names and types. It also defines a custom
+ * "rows" property which allows filling the #ClutterModel with some
+ * data.</para>
+ * <example id="ClutterModel-script-example">
+ * <title>Example of the "columns" and "rows" custom properties</title>
* <para>The definition below will create a #ClutterListModel with three
* columns: the first one with name "Name" and containing strings; the
* second one with name "Score" and containing integers; the third one with
- * name "Icon" and containing #ClutterTexture<!-- -->s.</para>
+ * name "Icon" and containing #ClutterTexture<!-- -->s. The model is filled
+ * with three rows. A row can be defined either with an array that holds
+ * all columns of a row, or an object that holds "column-name" :
+ * "column-value" pairs.
+ * </para>
* <programlisting>
* {
* "type" : "ClutterListModel",
* [ "Name", "gchararray" ],
* [ "Score", "gint" ],
* [ "Icon", "ClutterTexture" ]
+ * ],
+ * "rows" : [
+ * [ "Team 1", 42, { "type" : "ClutterTexture", "filename" : "team1.png" } ],
+ * [ "Team 2", 23, "team2-icon-script-id" ],
+ * { "Name" : "Team 3", "Icon" : "team3-icon-script-id" }
* ]
* }
* </programlisting>
#include "clutter-private.h"
#include "clutter-debug.h"
#include "clutter-scriptable.h"
+#include "clutter-script-private.h"
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
return priv->n_columns;
}
+static guint
+clutter_model_real_get_n_rows (ClutterModel *model)
+{
+ ClutterModelIter *iter;
+ guint row_count;
+
+ g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0);
+
+ iter = clutter_model_get_first_iter (model);
+ if (iter == NULL)
+ return 0;
+
+ row_count = 0;
+ while (!clutter_model_iter_is_last (iter))
+ {
+ if (clutter_model_filter_iter (model, iter))
+ row_count += 1;
+
+ iter = clutter_model_iter_next (iter);
+ }
+
+ g_object_unref (iter);
+
+ return row_count;
+}
+
static void
clutter_model_finalize (GObject *object)
{
klass->get_column_name = clutter_model_real_get_column_name;
klass->get_column_type = clutter_model_real_get_column_type;
klass->get_n_columns = clutter_model_real_get_n_columns;
+ klass->get_n_rows = clutter_model_real_get_n_rows;
/**
* ClutterModel:filter-set:
const gchar *name,
JsonNode *node)
{
- GSList *columns = NULL;
- GList *elements, *l;
-
- if (strcmp (name, "columns") != 0)
- return FALSE;
+ if (strcmp (name, "columns") == 0)
+ {
+ GSList *columns = NULL;
+ GList *elements, *l;
- if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
- return FALSE;
+ if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
+ return FALSE;
- elements = json_array_get_elements (json_node_get_array (node));
+ elements = json_array_get_elements (json_node_get_array (node));
- for (l = elements; l != NULL; l = l->next)
- {
- JsonNode *child_node = l->data;
- JsonArray *array = json_node_get_array (child_node);
- ColumnInfo *cinfo;
- const gchar *column_name;
- const gchar *type_name;
-
- if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY ||
- json_array_get_length (array) != 2)
+ for (l = elements; l != NULL; l = l->next)
{
- g_warning ("A column must be an array of "
- "[\"column-name\", \"GType-name\"] pairs");
- return FALSE;
+ JsonNode *child_node = l->data;
+ JsonArray *array = json_node_get_array (child_node);
+ ColumnInfo *cinfo;
+ const gchar *column_name;
+ const gchar *type_name;
+
+ if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY ||
+ json_array_get_length (array) != 2)
+ {
+ g_warning ("A column must be an array of "
+ "[\"column-name\", \"GType-name\"] pairs");
+ return FALSE;
+ }
+
+ column_name = json_array_get_string_element (array, 0);
+ type_name = json_array_get_string_element (array, 1);
+
+ cinfo = g_slice_new0 (ColumnInfo);
+ cinfo->name = g_strdup (column_name);
+ cinfo->type = clutter_script_get_type_from_name (script, type_name);
+
+ columns = g_slist_prepend (columns, cinfo);
}
- column_name = json_array_get_string_element (array, 0);
- type_name = json_array_get_string_element (array, 1);
+ g_list_free (elements);
- cinfo = g_slice_new0 (ColumnInfo);
- cinfo->name = g_strdup (column_name);
- cinfo->type = clutter_script_get_type_from_name (script, type_name);
+ g_value_init (value, G_TYPE_POINTER);
+ g_value_set_pointer (value, g_slist_reverse (columns));
- columns = g_slist_prepend (columns, cinfo);
+ return TRUE;
}
+ else if (strcmp (name, "rows") == 0)
+ {
+ GSList *rows = NULL;
+ GList *elements, *l;
- g_list_free (elements);
+ if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
+ return FALSE;
+
+ /*
+ * at this point we have no information about the column types, so
+ * we just copy the json elements and resolve them in the
+ * set_custom_property method
+ */
+ elements = json_array_get_elements (json_node_get_array (node));
+ for (l = elements; l != NULL; l = l->next)
+ rows = g_slist_prepend (rows, json_node_copy (l->data));
+ g_list_free (elements);
- g_value_init (value, G_TYPE_POINTER);
- g_value_set_pointer (value, g_slist_reverse (columns));
+ g_value_init (value, G_TYPE_POINTER);
+ g_value_set_pointer (value, g_slist_reverse (rows));
- return TRUE;
+ return TRUE;
+ }
+ return FALSE;
}
static void
g_slist_free (columns);
}
+ else if (strcmp (name, "rows") == 0)
+ {
+ ClutterModel *model = CLUTTER_MODEL (scriptable);
+ GSList *rows, *l;
+ guint n_columns, row = 0;
+
+ rows = g_value_get_pointer (value);
+ n_columns = clutter_model_get_n_columns (model);
+
+ for (l = rows; l; l = l->next)
+ {
+ JsonNode *node = l->data;
+ guint *columns, i, n_values = 0;
+ GValueArray *values;
+
+ if (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY)
+ {
+ JsonArray *array = json_node_get_array (node);
+ if (json_array_get_length (array) != n_columns)
+ {
+ g_warning ("Row %d contains the wrong count of columns",
+ g_slist_position (rows, l) + 1);
+ row++;
+ continue;
+ }
+
+ n_values = n_columns;
+ columns = g_new (guint, n_values);
+ values = g_value_array_new (n_values);
+
+ for (i = 0; i < n_values; i++)
+ {
+ GType column_type;
+ const gchar *column_name;
+ GValue v = { 0, };
+
+ column_type = clutter_model_get_column_type (model, i);
+ column_name = clutter_model_get_column_name (model, i);
+ columns[i] = i;
+ g_value_init (&v, column_type);
+ clutter_script_parse_node (script, &v, column_name,
+ json_array_get_element (array, i),
+ NULL);
+ g_value_array_append (values, &v);
+ g_value_unset (&v);
+ }
+ }
+ else if (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT)
+ {
+ JsonObject *object = json_node_get_object (node);
+ GList *members, *m;
+ guint column = 0;
+
+ n_values = json_object_get_size (object);
+ columns = g_new (guint, n_values);
+ values = g_value_array_new (n_values);
+
+ members = json_object_get_members (object);
+ for (m = members; m; m = m->next)
+ {
+ const gchar *mname = m->data;
+
+ for (i = 0; i < clutter_model_get_n_columns (model); i++)
+ {
+ const gchar *cname;
+
+ cname = clutter_model_get_column_name (model, i);
+ if (strcmp (mname, cname) == 0)
+ {
+ JsonNode *member;
+ GType col_type;
+ const gchar *col_name;
+ GValue v = { 0, };
+
+ col_type = clutter_model_get_column_type (model, i);
+ col_name = clutter_model_get_column_name (model, i);
+ columns[column] = i;
+ g_value_init (&v, col_type);
+ member = json_object_get_member (object, mname);
+ clutter_script_parse_node (script, &v,
+ col_name, member,
+ NULL);
+ g_value_array_append (values, &v);
+ g_value_unset (&v);
+ break;
+ }
+ }
+ column++;
+ }
+ }
+ else
+ {
+ row++;
+ continue;
+ }
+
+ clutter_model_insertv (model, row, n_values, columns, values->values);
+ g_value_array_free (values);
+ g_free (columns);
+ json_node_free (node);
+ row++;
+ }
+ g_slist_free (rows);
+ }
}
guint
clutter_model_get_n_rows (ClutterModel *model)
{
- ClutterModelClass *klass;
- guint row_count;
-
g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0);
- klass = CLUTTER_MODEL_GET_CLASS (model);
- if (klass->get_n_rows)
- row_count = klass->get_n_rows (model);
- else
- {
- ClutterModelIter *iter;
-
- iter = clutter_model_get_first_iter (model);
- if (iter == NULL)
- return 0;
-
- row_count = 0;
- while (!clutter_model_iter_is_last (iter))
- {
- if (clutter_model_filter_iter (model, iter))
- row_count += 1;
-
- iter = clutter_model_iter_next (iter);
- }
-
- g_object_unref (iter);
- }
-
- return row_count;
+ return CLUTTER_MODEL_GET_CLASS (model)->get_n_rows (model);
}
-
/**
* clutter_model_set_sorting_column:
* @model: a #ClutterModel
* clutter_model_set_sort:
* @model: a #ClutterModel
* @column: the column to sort on
- * @func: a #ClutterModelSortFunc, or #NULL
+ * @func: (allow-none): a #ClutterModelSortFunc, or #NULL
* @user_data: user data to pass to @func, or #NULL
* @notify: destroy notifier of @user_data, or #NULL
*
*/
void
clutter_model_set_sort (ClutterModel *model,
- guint column,
+ gint column,
ClutterModelSortFunc func,
gpointer user_data,
GDestroyNotify notify)
/**
* clutter_model_set_filter:
* @model: a #ClutterModel
- * @func: a #ClutterModelFilterFunc, or #NULL
+ * @func: (allow-none): a #ClutterModelFilterFunc, or #NULL
* @user_data: user data to pass to @func, or #NULL
* @notify: destroy notifier of @user_data, or #NULL
*
* clutter_model_iter_get_value:
* @iter: a #ClutterModelIter
* @column: column number to retrieve the value from
- * @value: an empty #GValue to set
+ * @value: (out): an empty #GValue to set
*
* Sets an initializes @value to that at @column. When done with @value,
* g_value_unset() needs to be called to free any allocated memory.
ClutterModelForeachFunc func,
gpointer user_data);
void clutter_model_set_sort (ClutterModel *model,
- guint column,
+ gint column,
ClutterModelSortFunc func,
gpointer user_data,
GDestroyNotify notify);
CoglMatrix modelview;
gfloat fbo_width, fbo_height;
gfloat width, height;
+ gfloat xexpand, yexpand;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
* framebuffer. */
clutter_actor_get_size (priv->stage, &width, &height);
clutter_actor_box_get_origin (&box, &priv->x_offset, &priv->y_offset);
- cogl_set_viewport (-priv->x_offset, -priv->y_offset, width, height);
+
+ /* Expand the viewport if the actor is partially off-stage,
+ * otherwise the actor will end up clipped to the stage viewport
+ */
+ xexpand = 0.f;
+ if (priv->x_offset < 0.f)
+ xexpand = -priv->x_offset;
+ if (priv->x_offset + fbo_width > width)
+ xexpand = MAX (xexpand, (priv->x_offset + fbo_width) - width);
+
+ yexpand = 0.f;
+ if (priv->y_offset < 0.f)
+ yexpand = -priv->y_offset;
+ if (priv->y_offset + fbo_height > height)
+ yexpand = MAX (yexpand, (priv->y_offset + fbo_height) - height);
+
+ /* Set the viewport */
+ cogl_set_viewport (-(priv->x_offset + xexpand), -(priv->y_offset + yexpand),
+ width + (2 * xexpand), height + (2 * yexpand));
/* Copy the stage's projection matrix across to the framebuffer */
_clutter_stage_get_projection_matrix (CLUTTER_STAGE (priv->stage),
&projection);
cogl_set_projection_matrix (&projection);
+ /* If we've expanded the viewport, make sure to scale the modelview
+ * matrix accordingly (as it's been initialised to work with the
+ * original viewport and not our expanded one).
+ */
+ if (xexpand > 0.f || yexpand > 0.f)
+ {
+ CoglMatrix correction;
+ gfloat new_width, new_height;
+
+ new_width = width + (2 * xexpand);
+ new_height = height + (2 * yexpand);
+
+ cogl_matrix_init_identity (&correction);
+ cogl_matrix_scale (&correction,
+ width / new_width,
+ height / new_height,
+ 1);
+
+ cogl_matrix_multiply (&correction, &correction, &modelview);
+ modelview = correction;
+ }
+
/* Copy the modelview that would have been used if rendering onscreen */
cogl_set_modelview_matrix (&modelview);
cogl_push_matrix ();
+ /* Override the actor's opacity to fully opaque - we paint the offscreen
+ * texture with the actor's paint opacity, so we need to do this to avoid
+ * multiplying the opacity twice.
+ */
+ _clutter_actor_set_opacity_override (priv->actor, 0xff);
+
return TRUE;
}
cogl_matrix_translate (&modelview, priv->x_offset, priv->y_offset, 0.0f);
cogl_set_modelview_matrix (&modelview);
+ /* Remove the opacity override */
+ _clutter_actor_set_opacity_override (priv->actor, -1);
+
/* paint the target material; this is virtualized for
* sub-classes that require special hand-holding
*/
#define CLUTTER_IS_PAGE_TURN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_PAGE_TURN_EFFECT))
#define CLUTTER_PAGE_TURN_EFFECT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffectClass))
-typedef struct _ClutterPageTurnEffectClass ClutterPageTurnEffectClass;
-
struct _ClutterPageTurnEffect
{
ClutterDeformEffect parent_instance;
* Since: 1.4
*/
typedef struct _ClutterPageTurnEffect ClutterPageTurnEffect;
+typedef struct _ClutterPageTurnEffectClass ClutterPageTurnEffectClass;
GType clutter_page_turn_effect_get_type (void) G_GNUC_CONST;
#define CLUTTER_IS_PATH_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_PATH_CONSTRAINT))
#define CLUTTER_PATH_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_PATH_CONSTRAINT, ClutterPathConstraintClass))
-typedef struct _ClutterPathConstraintClass ClutterPathConstraintClass;
-
struct _ClutterPathConstraint
{
ClutterConstraint parent_instance;
*
* Since: 1.6
*/
-typedef struct _ClutterPathConstraint ClutterPathConstraint;
+typedef struct _ClutterPathConstraint ClutterPathConstraint;
+typedef struct _ClutterPathConstraintClass ClutterPathConstraintClass;
GType clutter_path_constraint_get_type (void) G_GNUC_CONST;
CLUTTER_INTERNAL_CHILD = 1 << 6
} ClutterPrivateFlags;
+/*
+ * ClutterMainContext:
+ *
+ * The shared state of Clutter
+ */
struct _ClutterMainContext
{
- ClutterBackend *backend; /* holds a pointer to the windowing
- system backend */
- GQueue *events_queue; /* the main event queue */
+ /* the main windowing system backend */
+ ClutterBackend *backend;
- guint is_initialized : 1;
- guint motion_events_per_actor : 1;/* set for enter/leave events */
- guint defer_display_setup : 1;
- guint options_parsed : 1;
+ /* the main event queue */
+ GQueue *events_queue;
- GTimer *timer; /* Used for debugging scheduler */
+ /* timer used to print the FPS count */
+ GTimer *timer;
- ClutterPickMode pick_mode; /* Indicates pick render mode */
+ ClutterPickMode pick_mode;
- gint num_reactives; /* Num of reactive actors */
+ /* mapping between reused integer ids and actors */
+ ClutterIDPool *id_pool;
- ClutterIDPool *id_pool; /* mapping between reused integer ids
- * and actors
- */
- guint frame_rate; /* Default FPS */
+ /* default FPS; this is only used if we cannot sync to vblank */
+ guint frame_rate;
- ClutterActor *pointer_grab_actor; /* The actor having the pointer grab
- * (or NULL if there is no pointer grab
- */
- ClutterActor *keyboard_grab_actor; /* The actor having the pointer grab
- * (or NULL if there is no pointer
- * grab)
- */
- GSList *shaders; /* stack of overridden shaders */
+ /* actors with a grab on all devices */
+ ClutterActor *pointer_grab_actor;
+ ClutterActor *keyboard_grab_actor;
- ClutterActor *motion_last_actor;
+ /* stack of overridden shaders during paint */
+ GSList *shaders;
/* fb bit masks for col<->id mapping in picking */
- gint fb_r_mask, fb_g_mask, fb_b_mask;
- gint fb_r_mask_used, fb_g_mask_used, fb_b_mask_used;
+ gint fb_r_mask;
+ gint fb_g_mask;
+ gint fb_b_mask;
+ gint fb_r_mask_used;
+ gint fb_g_mask_used;
+ gint fb_b_mask_used;
- PangoContext *pango_context; /* Global Pango context */
- CoglPangoFontMap *font_map; /* Global font map */
+ PangoContext *pango_context; /* Global Pango context */
+ CoglPangoFontMap *font_map; /* Global font map */
ClutterEvent *current_event;
guint32 last_event_time;
gulong redraw_count;
+ /* list of repaint functions installed through
+ * clutter_threads_add_repaint_func()
+ */
GList *repaint_funcs;
+ /* main settings singleton */
ClutterSettings *settings;
+
+ /* boolean flags */
+ guint is_initialized : 1;
+ guint motion_events_per_actor : 1;
+ guint defer_display_setup : 1;
+ guint options_parsed : 1;
};
/* shared between clutter-main.c and clutter-frame-source.c */
void _clutter_threads_dispatch_free (gpointer data);
#define CLUTTER_CONTEXT() (_clutter_context_get_default ())
-ClutterMainContext *_clutter_context_get_default (void);
-gboolean _clutter_context_is_initialized (void);
-PangoContext *_clutter_context_create_pango_context (ClutterMainContext *self);
-PangoContext *_clutter_context_get_pango_context (ClutterMainContext *self);
-
-#define CLUTTER_PARAM_READABLE \
- G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB
-#define CLUTTER_PARAM_WRITABLE \
- G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB
-#define CLUTTER_PARAM_READWRITE \
- G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |G_PARAM_STATIC_BLURB
+ClutterMainContext * _clutter_context_get_default (void);
+gboolean _clutter_context_is_initialized (void);
+PangoContext * _clutter_context_create_pango_context (ClutterMainContext *self);
+PangoContext * _clutter_context_get_pango_context (ClutterMainContext *self);
+
+#define CLUTTER_PARAM_READABLE (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)
+#define CLUTTER_PARAM_WRITABLE (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)
+#define CLUTTER_PARAM_READWRITE (G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)
+/* automagic interning of a static string */
#define I_(str) (g_intern_static_string ((str)))
/* mark all properties under the "Property" context */
/* Reinjecting queued events for processing */
void _clutter_process_event (ClutterEvent *event);
+/* clears the event queue inside the main context */
+void _clutter_clear_events_queue (void);
+void _clutter_clear_events_queue_for_stage (ClutterStage *stage);
+
/* Picking code */
ClutterActor *_clutter_do_pick (ClutterStage *stage,
gint x,
guint _clutter_pixel_to_id (guchar pixel[4]);
-void _clutter_id_to_color (guint id, ClutterColor *col);
+void _clutter_id_to_color (guint id,
+ ClutterColor *col);
/* use this function as the accumulator if you have a signal with
* a G_TYPE_BOOLEAN return value; this will stop the emission as
gpointer data);
gpointer _clutter_event_get_platform_data (const ClutterEvent *event);
+void _clutter_event_push (const ClutterEvent *event,
+ gboolean do_copy);
+void _clutter_event_set_device (ClutterEvent *event,
+ ClutterInputDevice *device);
+void _clutter_event_set_source_device (ClutterEvent *event,
+ ClutterInputDevice *device);
+
void _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
const CoglMatrix *projection,
const int *viewport,
/**
* clutter_rectangle_get_color:
* @rectangle: a #ClutterRectangle
- * @color: return location for a #ClutterColor
+ * @color: (out): return location for a #ClutterColor
*
* Retrieves the color of @rectangle.
*/
/**
* clutter_rectangle_get_border_color:
* @rectangle: a #ClutterRectangle
- * @color: return location for a #ClutterColor
+ * @color: (out): return location for a #ClutterColor
*
* Gets the color of the border used by @rectangle and places
* it into @color.
* is a custom member that will be parsed by the Scriptable
* interface implementantion
*/
- if (pspec == NULL)
+ if (pspec == NULL && !G_IS_VALUE (value))
return FALSE;
else
{
- GType p_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
+ GType p_type;
ObjectInfo *oinfo;
const gchar *id;
- g_value_init (value, p_type);
+ if (G_IS_VALUE (value))
+ p_type = G_VALUE_TYPE (value);
+ else
+ {
+ p_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
+ g_value_init (value, p_type);
+ }
if (g_type_is_a (p_type, G_TYPE_OBJECT))
{
return FALSE;
case JSON_NODE_ARRAY:
- if (!pspec)
+ if (!pspec && !G_IS_VALUE (value))
return FALSE;
else
{
- g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ if (!G_IS_VALUE (value))
+ g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
if (G_VALUE_HOLDS (value, CLUTTER_TYPE_KNOT))
{
case JSON_NODE_VALUE:
json_node_get_value (node, &node_value);
- if (pspec)
- g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
- else
+ if (!pspec && !G_IS_VALUE (value))
g_value_init (value, G_VALUE_TYPE (&node_value));
+ else if (pspec)
+ g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
{
break;
}
+ if (G_VALUE_TYPE (value) == G_TYPE_GTYPE &&
+ G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
+ {
+ const gchar *str = g_value_get_string (&node_value);
+ GType type = clutter_script_get_type_from_name (script, str);
+ g_value_set_gtype (value, type);
+ retval = TRUE;
+ }
+
g_value_unset (&node_value);
break;
}
#define CLUTTER_IS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SETTINGS))
#define CLUTTER_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SETTINGS, ClutterSettingsClass))
-typedef struct _ClutterSettingsClass ClutterSettingsClass;
-
/**
* ClutterSettings:
*
#define CLUTTER_IS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SETTINGS))
typedef struct _ClutterSettings ClutterSettings;
+typedef struct _ClutterSettingsClass ClutterSettingsClass;
GType clutter_settings_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (ClutterShader, clutter_shader, G_TYPE_OBJECT);
+static inline void
+clutter_shader_release_internal (ClutterShader *shader)
+{
+ ClutterShaderPrivate *priv = shader->priv;
+
+ if (!priv->compiled)
+ return;
+
+ g_assert (priv->program != COGL_INVALID_HANDLE);
+
+ if (priv->vertex_is_glsl && priv->vertex_shader != COGL_INVALID_HANDLE)
+ cogl_handle_unref (priv->vertex_shader);
+
+ if (priv->fragment_is_glsl && priv->fragment_shader != COGL_INVALID_HANDLE)
+ cogl_handle_unref (priv->fragment_shader);
+
+ if (priv->program != COGL_INVALID_HANDLE)
+ cogl_handle_unref (priv->program);
+
+ priv->vertex_shader = COGL_INVALID_HANDLE;
+ priv->fragment_shader = COGL_INVALID_HANDLE;
+ priv->program = COGL_INVALID_HANDLE;
+ priv->compiled = FALSE;
+}
+
static void
clutter_shader_finalize (GObject *object)
{
shader = CLUTTER_SHADER (object);
priv = shader->priv;
- clutter_shader_release (shader);
-
clutter_shaders_list = g_list_remove (clutter_shaders_list, object);
g_free (priv->fragment_source);
}
static void
+clutter_shader_dispose (GObject *object)
+{
+ ClutterShader *shader = CLUTTER_SHADER (object);
+
+ clutter_shader_release_internal (shader);
+
+ G_OBJECT_CLASS (clutter_shader_parent_class)->finalize (object);
+}
+
+static void
clutter_shader_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec = NULL;
object_class->finalize = clutter_shader_finalize;
+ object_class->dispose = clutter_shader_dispose;
object_class->set_property = clutter_shader_set_property;
object_class->get_property = clutter_shader_get_property;
object_class->constructor = clutter_shader_constructor;
void
clutter_shader_release (ClutterShader *shader)
{
- ClutterShaderPrivate *priv;
-
g_return_if_fail (CLUTTER_IS_SHADER (shader));
- priv = shader->priv;
-
- if (!priv->compiled)
- return;
-
- g_assert (priv->program != COGL_INVALID_HANDLE);
-
- if (priv->vertex_is_glsl && priv->vertex_shader != COGL_INVALID_HANDLE)
- cogl_handle_unref (priv->vertex_shader);
-
- if (priv->fragment_is_glsl && priv->fragment_shader != COGL_INVALID_HANDLE)
- cogl_handle_unref (priv->fragment_shader);
-
- if (priv->program != COGL_INVALID_HANDLE)
- cogl_handle_unref (priv->program);
-
- priv->vertex_shader = COGL_INVALID_HANDLE;
- priv->fragment_shader = COGL_INVALID_HANDLE;
- priv->program = COGL_INVALID_HANDLE;
- priv->compiled = FALSE;
+ clutter_shader_release_internal (shader);
_clutter_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_COMPILED]);
}
#define CLUTTER_IS_SNAP_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SNAP_CONSTRAINT))
#define CLUTTER_SNAP_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SNAP_CONSTRAINT, ClutterSnapConstraintClass))
-typedef struct _ClutterSnapConstraintClass ClutterSnapConstraintClass;
-
struct _ClutterSnapConstraint
{
ClutterConstraint parent_instance;
*
* Since: 1.6
*/
-typedef struct _ClutterSnapConstraint ClutterSnapConstraint;
+typedef struct _ClutterSnapConstraint ClutterSnapConstraint;
+typedef struct _ClutterSnapConstraintClass ClutterSnapConstraintClass;
/**
* ClutterSnapEdge:
#include <clutter/clutter-stage-window.h>
#include <clutter/clutter-stage.h>
+#include <clutter/clutter-input-device.h>
G_BEGIN_DECLS
ClutterPaintVolume *clip);
void _clutter_stage_queue_redraw_entry_invalidate (ClutterStageQueueRedrawEntry *entry);
+void _clutter_stage_add_device (ClutterStage *stage,
+ ClutterInputDevice *device);
+void _clutter_stage_remove_device (ClutterStage *stage,
+ ClutterInputDevice *device);
+gboolean _clutter_stage_has_device (ClutterStage *stage,
+ ClutterInputDevice *device);
+
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
if (iface->set_accept_focus)
iface->set_accept_focus (window, accept_focus);
}
+
+void
+_clutter_stage_window_redraw (ClutterStageWindow *window)
+{
+ ClutterStageWindowIface *iface;
+
+ g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
+
+ iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
+ if (iface->redraw)
+ iface->redraw (window);
+}
void (* set_accept_focus) (ClutterStageWindow *stage_window,
gboolean accept_focus);
+
+ void (* redraw) (ClutterStageWindow *stage_window);
};
GType clutter_stage_window_get_type (void) G_GNUC_CONST;
void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
gboolean accept_focus);
+void _clutter_stage_window_redraw (ClutterStageWindow *window);
+
G_END_DECLS
#endif /* __CLUTTER_STAGE_WINDOW_H__ */
ClutterPickMode pick_buffer_mode;
+ GHashTable *devices;
+
guint relayout_pending : 1;
guint redraw_pending : 1;
guint is_fullscreen : 1;
priv = stage->priv;
+ if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
+ return FALSE;
+
/* NB: We need to ensure we have an up to date layout *before* we
* check or clear the pending redraws flag since a relayout may
* queue a redraw.
{
ClutterStage *stage = CLUTTER_STAGE (object);
ClutterStagePrivate *priv = stage->priv;
- ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
- ClutterMainContext *context;
- GList *l, *next;
+ ClutterStageManager *stage_manager;
clutter_actor_hide (CLUTTER_ACTOR (object));
+ stage_manager = clutter_stage_manager_get_default ();
_clutter_stage_manager_remove_stage (stage_manager, stage);
- context = _clutter_context_get_default ();
-
- /* Remove any pending events for this stage from the event queue */
- for (l = context->events_queue->head; l; l = next)
- {
- ClutterEvent *event = l->data;
-
- next = l->next;
-
- if (event->any.stage == stage)
- {
- g_queue_delete_link (context->events_queue, l);
- clutter_event_free (event);
- }
- }
+ _clutter_clear_events_queue_for_stage (stage);
if (priv->impl != NULL)
{
ClutterStage *stage = CLUTTER_STAGE (object);
ClutterStagePrivate *priv = stage->priv;
- g_queue_foreach (priv->event_queue, (GFunc)clutter_event_free, NULL);
+ g_queue_foreach (priv->event_queue, (GFunc) clutter_event_free, NULL);
g_queue_free (priv->event_queue);
- g_free (stage->priv->title);
+ g_free (priv->title);
g_array_free (priv->paint_volume_stack, TRUE);
+ g_hash_table_destroy (priv->devices);
+
G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object);
}
priv->paint_volume_stack =
g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume));
+
+ priv->devices = g_hash_table_new (NULL, NULL);
}
/**
/**
* clutter_stage_get_color:
* @stage: A #ClutterStage
- * @color: return location for a #ClutterColor
+ * @color: (out): return location for a #ClutterColor
*
* Retrieves the stage color.
*/
gboolean
clutter_stage_is_default (ClutterStage *stage)
{
+ ClutterStageManager *stage_manager;
ClutterStageWindow *impl;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
- if (CLUTTER_ACTOR (stage) == clutter_stage_get_default ())
- return TRUE;
+ stage_manager = clutter_stage_manager_get_default ();
+ if (stage != clutter_stage_manager_get_default_stage (stage_manager))
+ return FALSE;
impl = _clutter_stage_get_window (stage);
- if (impl == _clutter_stage_get_default_window ())
- return TRUE;
+ if (impl != _clutter_stage_get_default_window ())
+ return FALSE;
- return FALSE;
+ return TRUE;
}
void
}
/**
- * clutter_stage_get_accept_focus:
+ * clutter_stage_set_accept_focus:
* @stage: a #ClutterStage
* @accept_focus: %TRUE to accept focus on show
*
return stage->priv->accept_focus;
}
+
+void
+_clutter_stage_add_device (ClutterStage *stage,
+ ClutterInputDevice *device)
+{
+ ClutterStagePrivate *priv = stage->priv;
+
+ if (g_hash_table_lookup (priv->devices, device) != NULL)
+ return;
+
+ g_hash_table_insert (priv->devices, device, GINT_TO_POINTER (1));
+ _clutter_input_device_set_stage (device, stage);
+}
+
+void
+_clutter_stage_remove_device (ClutterStage *stage,
+ ClutterInputDevice *device)
+{
+ ClutterStagePrivate *priv = stage->priv;
+
+ _clutter_input_device_set_stage (device, NULL);
+ g_hash_table_remove (priv->devices, device);
+}
+
+gboolean
+_clutter_stage_has_device (ClutterStage *stage,
+ ClutterInputDevice *device)
+{
+ ClutterStagePrivate *priv = stage->priv;
+
+ return g_hash_table_lookup (priv->devices, device) != NULL;
+}
G_CALLBACK (clutter_text_real_del_prev),
NULL, NULL);
clutter_binding_pool_install_action (binding_pool, "delete-prev",
+ CLUTTER_KEY_BackSpace, CLUTTER_SHIFT_MASK,
+ G_CALLBACK (clutter_text_real_del_prev),
+ NULL, NULL);
+ clutter_binding_pool_install_action (binding_pool, "delete-prev",
CLUTTER_KEY_BackSpace, CLUTTER_CONTROL_MASK,
G_CALLBACK (clutter_text_real_del_word_prev),
NULL, NULL);
/**
* clutter_text_get_color:
* @self: a #ClutterText
- * @color: return location for a #ClutterColor
+ * @color: (out): return location for a #ClutterColor
*
* Retrieves the text color as set by clutter_text_set_color().
*
priv = timeline->priv;
+ /* Check the is_playing variable before performing the timeline tick.
+ * This is necessary, as if a timeline is stopped in response to a
+ * master-clock generated signal of a different timeline, this code can
+ * still be reached.
+ */
+ if (!priv->is_playing)
+ return;
+
if (priv->waiting_first_tick)
{
priv->last_frame_time = tick_time;
+ priv->msecs_delta = 0;
priv->waiting_first_tick = FALSE;
+ clutter_timeline_do_frame (timeline);
}
else
{
void (*paused) (ClutterTimeline *timeline);
void (*new_frame) (ClutterTimeline *timeline,
- gint frame_num);
+ gint msecs);
void (*marker_reached) (ClutterTimeline *timeline,
const gchar *marker_name,
#include "config.h"
#endif
-#undef CLUTTER_DISABLE_DEPRECATED
#include "clutter-timeout-pool.h"
#include "clutter-debug.h"
G_BEGIN_DECLS
-#ifndef CLUTTER_DISABLE_DEPRECATED
+#if !defined(CLUTTER_DISABLE_DEPRECATED) || defined(CLUTTER_COMPILATION)
/**
* ClutterTimeoutPool: (skip)
gboolean clutter_paint_volume_set_from_allocation (ClutterPaintVolume *pv,
ClutterActor *actor);
+/**
+ * ClutterModifierType:
+ * @CLUTTER_SHIFT_MASK: Mask applied by the Shift key
+ * @CLUTTER_LOCK_MASK: Mask applied by the Caps Lock key
+ * @CLUTTER_CONTROL_MASK: Mask applied by the Control key
+ * @CLUTTER_MOD1_MASK: Mask applied by the first Mod key
+ * @CLUTTER_MOD2_MASK: Mask applied by the second Mod key
+ * @CLUTTER_MOD3_MASK: Mask applied by the third Mod key
+ * @CLUTTER_MOD4_MASK: Mask applied by the fourth Mod key
+ * @CLUTTER_MOD5_MASK: Mask applied by the fifth Mod key
+ * @CLUTTER_BUTTON1_MASK: Mask applied by the first pointer button
+ * @CLUTTER_BUTTON2_MASK: Mask applied by the second pointer button
+ * @CLUTTER_BUTTON3_MASK: Mask applied by the third pointer button
+ * @CLUTTER_BUTTON4_MASK: Mask applied by the fourth pointer button
+ * @CLUTTER_BUTTON5_MASK: Mask applied by the fifth pointer button
+ * @CLUTTER_SUPER_MASK: Mask applied by the Super key
+ * @CLUTTER_HYPER_MASK: Mask applied by the Hyper key
+ * @CLUTTER_META_MASK: Mask applied by the Meta key
+ * @CLUTTER_RELEASE_MASK: Mask applied during release
+ * @CLUTTER_MODIFIER_MASK: A mask covering all modifier types
+ *
+ * Masks applied to a #ClutterEvent by modifiers.
+ *
+ * Since: 0.4
+ */
+typedef enum {
+ CLUTTER_SHIFT_MASK = 1 << 0,
+ CLUTTER_LOCK_MASK = 1 << 1,
+ CLUTTER_CONTROL_MASK = 1 << 2,
+ CLUTTER_MOD1_MASK = 1 << 3,
+ CLUTTER_MOD2_MASK = 1 << 4,
+ CLUTTER_MOD3_MASK = 1 << 5,
+ CLUTTER_MOD4_MASK = 1 << 6,
+ CLUTTER_MOD5_MASK = 1 << 7,
+ CLUTTER_BUTTON1_MASK = 1 << 8,
+ CLUTTER_BUTTON2_MASK = 1 << 9,
+ CLUTTER_BUTTON3_MASK = 1 << 10,
+ CLUTTER_BUTTON4_MASK = 1 << 11,
+ CLUTTER_BUTTON5_MASK = 1 << 12,
+
+ /* bits 15 to 25 are currently unused; bit 29 is used internally */
+
+ CLUTTER_SUPER_MASK = 1 << 26,
+ CLUTTER_HYPER_MASK = 1 << 27,
+ CLUTTER_META_MASK = 1 << 28,
+
+ CLUTTER_RELEASE_MASK = 1 << 30,
+
+ CLUTTER_MODIFIER_MASK = 0x5c001fff
+} ClutterModifierType;
+
G_END_DECLS
#endif /* __CLUTTER_TYPES_H__ */
#include "clutter-deprecated.h"
+#include "clutter-config.h"
+
#include "clutter-action.h"
#include "clutter-actor.h"
#include "clutter-actor-meta.h"
$(srcdir)/cogl-index-array.h \
$(srcdir)/cogl-vertex-array.h \
$(srcdir)/cogl-indices.h \
- $(srcdir)/cogl-vertex-attribute.h \
+ $(srcdir)/cogl-attribute.h \
$(srcdir)/cogl-primitive.h \
$(srcdir)/cogl.h \
$(NULL)
$(srcdir)/cogl-vertex-array.c \
$(srcdir)/cogl-indices-private.h \
$(srcdir)/cogl-indices.c \
- $(srcdir)/cogl-vertex-attribute-private.h \
- $(srcdir)/cogl-vertex-attribute.c \
+ $(srcdir)/cogl-attribute-private.h \
+ $(srcdir)/cogl-attribute.c \
$(srcdir)/cogl-primitive-private.h \
$(srcdir)/cogl-primitive.c \
$(srcdir)/cogl-matrix.c \
$(srcdir)/cogl-callback-list.h \
$(srcdir)/cogl-callback-list.c \
$(srcdir)/cogl-gtype-private.h \
+ $(srcdir)/cogl-point-in-poly-private.h \
+ $(srcdir)/cogl-point-in-poly.c \
$(NULL)
if SUPPORT_XLIB
{
CoglAtlas *atlas = data;
- /* We don't know if any pipelines may currently be referenced in
- * the journal that depend on the current underlying GL texture
- * storage so we flush the journal before migrating.
+ /* We don't know if any journal entries currently depend on OpenGL
+ * texture coordinates that would be invalidated by reorganizing
+ * this atlas so we flush all journals before migrating.
*
* We are assuming that texture atlas migration never happens
* during a flush so we don't have to consider recursion here.
*/
- _cogl_journal_flush ();
+ cogl_flush ();
if (atlas->map)
_cogl_rectangle_map_foreach (atlas->map,
{
COGL_NOTE (ATLAS, "Migrating texture out of the atlas");
- /* We don't know if any pipelines may currently be referenced in
- * the journal that depend on the current underlying GL texture
- * storage so we flush the journal before migrating.
+ /* We don't know if any journal entries currently depend on
+ * OpenGL texture coordinates that would be invalidated by
+ * migrating textures in this atlas so we flush all journals
+ * before migrating.
*
* We are assuming that texture atlas migration never happens
* during a flush so we don't have to consider recursion here.
*/
- _cogl_journal_flush ();
+ cogl_flush ();
/* Notify cogl-pipeline.c that the texture's underlying GL texture
* storage is changing so it knows it may need to bind a new texture
/* Don't put textures in the atlas if the user has explicitly
requested to disable it */
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_ATLAS))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ATLAS)))
return COGL_INVALID_HANDLE;
/* We can't put the texture in the atlas if there are any special
if (bmp_width < 1 || bmp_height < 1)
return COGL_INVALID_HANDLE;
- /* If we can't use FBOs or we can't read back texture data then it
- will be too slow to migrate textures and we shouldn't use the
- atlas */
- if (!cogl_features_available (COGL_FEATURE_TEXTURE_READ_PIXELS) ||
- !cogl_features_available (COGL_FEATURE_OFFSCREEN))
+ /* If we can't use FBOs then it will be too slow to migrate textures
+ and we shouldn't use the atlas */
+ if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
return COGL_INVALID_HANDLE;
COGL_NOTE (ATLAS, "Adding texture of size %ix%i", bmp_width, bmp_height);
to set as the data for the rectangle in the atlas */
atlas_tex = g_new (CoglAtlasTexture, 1);
+ _cogl_texture_init (COGL_TEXTURE (atlas_tex),
+ &cogl_atlas_texture_vtable);
+
atlas_tex->sub_texture = COGL_INVALID_HANDLE;
/* Look for an existing atlas that can hold the texture */
g_free (atlas_tex);
return COGL_INVALID_HANDLE;
}
-
- atlas_tex->_parent.vtable = &cogl_atlas_texture_vtable;
atlas_tex->format = internal_format;
atlas_tex->atlas = atlas;
--- /dev/null
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2010 Intel Corporation.
+ *
+ * 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/>.
+ *
+ *
+ *
+ * Authors:
+ * Robert Bragg <robert@linux.intel.com>
+ */
+
+#ifndef __COGL_ATTRIBUTE_PRIVATE_H
+#define __COGL_ATTRIBUTE_PRIVATE_H
+
+#include "cogl-object-private.h"
+#include "cogl-attribute.h"
+
+typedef enum
+{
+ COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY,
+ COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY,
+ COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY,
+ COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY,
+ COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY
+} CoglAttributeNameID;
+
+struct _CoglAttribute
+{
+ CoglObject _parent;
+
+ CoglVertexArray *array;
+ char *name;
+ CoglAttributeNameID name_id;
+ gsize stride;
+ gsize offset;
+ int n_components;
+ CoglAttributeType type;
+ gboolean normalized;
+ unsigned int texture_unit;
+
+ int immutable_ref;
+};
+
+typedef enum
+{
+ COGL_DRAW_SKIP_JOURNAL_FLUSH = 1 << 0,
+ COGL_DRAW_SKIP_PIPELINE_VALIDATION = 1 << 1,
+ COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH = 1 << 2,
+ /* When flushing from the journal the logged pipeline will already
+ contain the legacy state overrides so we don't want to apply them
+ again when we flush the pipeline for drawing */
+ COGL_DRAW_SKIP_LEGACY_STATE = 1 << 3,
+ /* By default the vertex attribute drawing code will assume that if
+ there is a color attribute array enabled then we can't determine
+ if the colors will be opaque so we need to enabling
+ blending. However when drawing from the journal we know what the
+ contents of the color array is so we can override this by passing
+ this flag. */
+ COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE = 1 << 4
+} CoglDrawFlags;
+
+CoglAttribute *
+_cogl_attribute_immutable_ref (CoglAttribute *attribute);
+
+void
+_cogl_attribute_immutable_unref (CoglAttribute *attribute);
+
+void
+_cogl_draw_attributes_array (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglAttribute **attributes,
+ CoglDrawFlags flags);
+
+void
+_cogl_draw_indexed_attributes_array (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglIndices *indices,
+ CoglAttribute **attributes,
+ CoglDrawFlags flags);
+
+void
+_cogl_attribute_disable_cached_arrays (void);
+
+#endif /* __COGL_ATTRIBUTE_PRIVATE_H */
+
#include "cogl-context.h"
#include "cogl-object-private.h"
#include "cogl-journal-private.h"
-#include "cogl-vertex-attribute.h"
-#include "cogl-vertex-attribute-private.h"
+#include "cogl-attribute.h"
+#include "cogl-attribute-private.h"
#include "cogl-pipeline.h"
#include "cogl-pipeline-private.h"
#include "cogl-pipeline-opengl-private.h"
#endif
-static void _cogl_vertex_attribute_free (CoglVertexAttribute *attribute);
+static void _cogl_attribute_free (CoglAttribute *attribute);
-COGL_OBJECT_DEFINE (VertexAttribute, vertex_attribute);
+COGL_OBJECT_DEFINE (Attribute, attribute);
#if 0
gboolean
validate_gl_attribute (const char *name,
int n_components,
- CoglVertexAttributeNameID *name_id,
+ CoglAttributeNameID *name_id,
gboolean *normalized,
unsigned int *texture_unit)
{
"attributes where n_components == 2, 3 or 4");
return FALSE;
}
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
}
else if (strcmp (name, "Color") == 0)
{
"n_components == 3 or 4");
return FALSE;
}
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_COLOR_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY;
*normalized = TRUE;
}
else if (strncmp (name, "MultiTexCoord", strlen ("MultiTexCoord")) == 0)
"texture unit number, E.g. gl_MultiTexCoord0\n");
unit = 0;
}
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
}
else if (strncmp (name, "Normal") == 0)
{
"n_components == 3");
return FALSE;
}
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
*normalized = TRUE;
}
else
gboolean
validate_cogl_attribute (const char *name,
int n_components,
- CoglVertexAttributeNameID *name_id,
+ CoglAttributeNameID *name_id,
gboolean *normalized,
unsigned int *texture_unit)
{
"attributes where n_components == 2, 3 or 4");
return FALSE;
}
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
}
else if (strcmp (name, "color_in") == 0)
{
"n_components == 3 or 4");
return FALSE;
}
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_COLOR_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY;
}
else if (strcmp (name, "tex_coord_in") == 0)
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
else if (strncmp (name, "tex_coord", strlen ("tex_coord")) == 0)
{
if (sscanf (name, "tex_coord%u_in", texture_unit) != 1)
"like \"cogl_tex_coord2_in\"\n");
return FALSE;
}
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
}
- else if (strcmp (name, "normal") == 0)
+ else if (strcmp (name, "normal_in") == 0)
{
if (G_UNLIKELY (n_components != 3))
{
"where n_components == 3");
return FALSE;
}
- *name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
+ *name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
*normalized = TRUE;
}
else
return TRUE;
}
-CoglVertexAttribute *
-cogl_vertex_attribute_new (CoglVertexArray *array,
- const char *name,
- gsize stride,
- gsize offset,
- int n_components,
- CoglVertexAttributeType type)
+CoglAttribute *
+cogl_attribute_new (CoglVertexArray *array,
+ const char *name,
+ gsize stride,
+ gsize offset,
+ int n_components,
+ CoglAttributeType type)
{
- CoglVertexAttribute *attribute = g_slice_new (CoglVertexAttribute);
+ CoglAttribute *attribute = g_slice_new (CoglAttribute);
gboolean status;
attribute->array = cogl_object_ref (array);
#endif
else
{
- attribute->name_id = COGL_VERTEX_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY;
+ attribute->name_id = COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY;
attribute->normalized = FALSE;
attribute->texture_unit = 0;
status = TRUE;
if (!status)
{
- _cogl_vertex_attribute_free (attribute);
+ _cogl_attribute_free (attribute);
return NULL;
}
- return _cogl_vertex_attribute_object_new (attribute);
+ return _cogl_attribute_object_new (attribute);
}
gboolean
-cogl_vertex_attribute_get_normalized (CoglVertexAttribute *attribute)
+cogl_attribute_get_normalized (CoglAttribute *attribute)
{
- g_return_val_if_fail (cogl_is_vertex_attribute (attribute), FALSE);
+ g_return_val_if_fail (cogl_is_attribute (attribute), FALSE);
return attribute->normalized;
}
}
void
-cogl_vertex_attribute_set_normalized (CoglVertexAttribute *attribute,
+cogl_attribute_set_normalized (CoglAttribute *attribute,
gboolean normalized)
{
- g_return_if_fail (cogl_is_vertex_attribute (attribute));
+ g_return_if_fail (cogl_is_attribute (attribute));
if (G_UNLIKELY (attribute->immutable_ref))
warn_about_midscene_changes ();
}
CoglVertexArray *
-cogl_vertex_attribute_get_array (CoglVertexAttribute *attribute)
+cogl_attribute_get_array (CoglAttribute *attribute)
{
- g_return_val_if_fail (cogl_is_vertex_attribute (attribute), NULL);
+ g_return_val_if_fail (cogl_is_attribute (attribute), NULL);
return attribute->array;
}
void
-cogl_vertex_attribute_set_array (CoglVertexAttribute *attribute,
+cogl_attribute_set_array (CoglAttribute *attribute,
CoglVertexArray *array)
{
- g_return_if_fail (cogl_is_vertex_attribute (attribute));
+ g_return_if_fail (cogl_is_attribute (attribute));
if (G_UNLIKELY (attribute->immutable_ref))
warn_about_midscene_changes ();
attribute->array = array;
}
-CoglVertexAttribute *
-_cogl_vertex_attribute_immutable_ref (CoglVertexAttribute *vertex_attribute)
+CoglAttribute *
+_cogl_attribute_immutable_ref (CoglAttribute *attribute)
{
- g_return_val_if_fail (cogl_is_vertex_attribute (vertex_attribute), NULL);
+ g_return_val_if_fail (cogl_is_attribute (attribute), NULL);
- vertex_attribute->immutable_ref++;
- _cogl_buffer_immutable_ref (COGL_BUFFER (vertex_attribute->array));
- return vertex_attribute;
+ attribute->immutable_ref++;
+ _cogl_buffer_immutable_ref (COGL_BUFFER (attribute->array));
+ return attribute;
}
void
-_cogl_vertex_attribute_immutable_unref (CoglVertexAttribute *vertex_attribute)
+_cogl_attribute_immutable_unref (CoglAttribute *attribute)
{
- g_return_if_fail (cogl_is_vertex_attribute (vertex_attribute));
- g_return_if_fail (vertex_attribute->immutable_ref > 0);
+ g_return_if_fail (cogl_is_attribute (attribute));
+ g_return_if_fail (attribute->immutable_ref > 0);
- vertex_attribute->immutable_ref--;
- _cogl_buffer_immutable_unref (COGL_BUFFER (vertex_attribute->array));
+ attribute->immutable_ref--;
+ _cogl_buffer_immutable_unref (COGL_BUFFER (attribute->array));
}
static void
-_cogl_vertex_attribute_free (CoglVertexAttribute *attribute)
+_cogl_attribute_free (CoglAttribute *attribute)
{
g_free (attribute->name);
cogl_object_unref (attribute->array);
- g_slice_free (CoglVertexAttribute, attribute);
+ g_slice_free (CoglAttribute, attribute);
}
typedef struct
if (texture == COGL_INVALID_HANDLE)
goto validated;
+ _cogl_texture_flush_journal_rendering (texture);
+
/* Give the texture a chance to know that we're rendering
non-quad shaped primitives. If the texture is in an atlas it
will be migrated */
}
static CoglHandle
-enable_gl_state (CoglVertexAttribute **attributes,
+enable_gl_state (CoglDrawFlags flags,
+ CoglAttribute **attributes,
ValidateLayerState *state)
{
+ CoglFramebuffer *framebuffer = _cogl_get_framebuffer ();
int i;
#ifdef MAY_HAVE_PROGRAMABLE_GL
GLuint generic_index = 0;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
+ /* In cogl_read_pixels we have a fast-path when reading a single
+ * pixel and the scene is just comprised of simple rectangles still
+ * in the journal. For this optimization to work we need to track
+ * when the framebuffer really does get drawn to. */
+ _cogl_framebuffer_dirty (framebuffer);
+
source = cogl_get_source ();
/* Iterate the attributes to work out whether blending needs to be
for (i = 0; attributes[i]; i++)
switch (attributes[i]->name_id)
{
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
- if (!_cogl_pipeline_get_real_blend_enabled (source))
+ case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
+ if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 &&
+ !_cogl_pipeline_get_real_blend_enabled (source))
{
CoglPipelineBlendEnable blend_enable =
COGL_PIPELINE_BLEND_ENABLE_ENABLED;
skip_gl_color = TRUE;
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
n_tex_coord_attribs++;
break;
*/
}
- if (G_UNLIKELY (ctx->legacy_state_set))
+ if (G_UNLIKELY (ctx->legacy_state_set) &&
+ (flags & COGL_DRAW_SKIP_LEGACY_STATE) == 0)
{
/* If we haven't already created a derived pipeline... */
if (!copy)
for (i = 0; attributes[i]; i++)
{
- CoglVertexAttribute *attribute = attributes[i];
+ CoglAttribute *attribute = attributes[i];
CoglVertexArray *vertex_array;
CoglBuffer *buffer;
void *base;
int attrib_location;
#endif
- vertex_array = cogl_vertex_attribute_get_array (attribute);
+ vertex_array = cogl_attribute_get_array (attribute);
buffer = COGL_BUFFER (vertex_array);
base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_VERTEX_ARRAY);
switch (attribute->name_id)
{
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
#ifdef HAVE_COGL_GLES2
attrib_location =
#endif
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
#ifdef HAVE_COGL_GLES2
attrib_location =
#endif
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
#ifdef HAVE_COGL_GLES2
attrib_location = _cogl_pipeline_progend_glsl_get_tex_coord_attribute
#endif
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
#ifdef HAVE_COGL_GLES2
attrib_location =
#endif
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
{
#ifdef MAY_HAVE_PROGRAMABLE_GL
/* FIXME: go through cogl cache to enable generic array. */
}
void
-_cogl_vertex_attribute_disable_cached_arrays (void)
+_cogl_attribute_disable_cached_arrays (void)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* FIXME: we shouldn't be disabling state after drawing we should
* just disable the things not needed after enabling state. */
static void
-disable_gl_state (CoglVertexAttribute **attributes,
+disable_gl_state (CoglAttribute **attributes,
CoglPipeline *source)
{
#ifdef MAY_HAVE_PROGRAMABLE_GL
for (i = 0; attributes[i]; i++)
{
- CoglVertexAttribute *attribute = attributes[i];
+ CoglAttribute *attribute = attributes[i];
switch (attribute->name_id)
{
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
/* GE (glDisableClientState (GL_COLOR_ARRAY)); */
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
/* FIXME: go through cogl cache to enable normal array */
#ifndef HAVE_COGL_GLES2
GE (glDisableClientState (GL_NORMAL_ARRAY));
#endif
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
/* The enabled state of the texture coord arrays is
cached in ctx->enabled_texcoord_arrays so we don't
need to do anything here. The array will be disabled
by the next drawing primitive if it is not
required */
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
/* GE (glDisableClientState (GL_VERTEX_ARRAY)); */
break;
- case COGL_VERTEX_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
+ case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
#ifdef MAY_HAVE_PROGRAMABLE_GL
/* FIXME: go through cogl cache to enable generic array */
GE (glDisableVertexAttribArray (generic_index++));
add_line (void *vertices,
void *indices,
CoglIndicesType indices_type,
- CoglVertexAttribute *attribute,
+ CoglAttribute *attribute,
int start,
int end,
- CoglP3Vertex *lines,
+ CoglVertexP3 *lines,
int *n_line_vertices)
{
int start_index = get_index (indices, indices_type, start);
*n_line_vertices += 2;
}
-static CoglP3Vertex *
-get_wire_lines (CoglVertexAttribute *attribute,
+static CoglVertexP3 *
+get_wire_lines (CoglAttribute *attribute,
CoglVerticesMode mode,
int n_vertices_in,
int *n_vertices_out,
CoglIndices *_indices)
{
- CoglVertexArray *vertex_array = cogl_vertex_attribute_get_array (attribute);
+ CoglVertexArray *vertex_array = cogl_attribute_get_array (attribute);
void *vertices;
CoglIndexArray *index_array;
void *indices;
CoglIndicesType indices_type;
int i;
int n_lines;
- CoglP3Vertex *out;
+ CoglVertexP3 *out;
vertices = cogl_buffer_map (COGL_BUFFER (vertex_array),
COGL_BUFFER_ACCESS_READ, 0);
(n_vertices_in % 3) == 0)
{
n_lines = n_vertices_in;
- out = g_new (CoglP3Vertex, n_lines * 2);
+ out = g_new (CoglVertexP3, n_lines * 2);
for (i = 0; i < n_vertices_in; i += 3)
{
add_line (vertices, indices, indices_type, attribute,
n_vertices_in >= 3)
{
n_lines = 2 * n_vertices_in - 3;
- out = g_new (CoglP3Vertex, n_lines * 2);
+ out = g_new (CoglVertexP3, n_lines * 2);
add_line (vertices, indices, indices_type, attribute,
0, 1, out, n_vertices_out);
n_vertices_in >= 3)
{
n_lines = 2 * n_vertices_in - 3;
- out = g_new (CoglP3Vertex, n_lines * 2);
+ out = g_new (CoglVertexP3, n_lines * 2);
add_line (vertices, indices, indices_type, attribute,
0, 1, out, n_vertices_out);
else if (mode == GL_QUADS && (n_vertices_in % 4) == 0)
{
n_lines = n_vertices_in;
- out = g_new (CoglP3Vertex, n_lines * 2);
+ out = g_new (CoglVertexP3, n_lines * 2);
for (i = 0; i < n_vertices_in; i += 4)
{
draw_wireframe (CoglVerticesMode mode,
int first_vertex,
int n_vertices,
- CoglVertexAttribute **attributes,
+ CoglAttribute **attributes,
CoglIndices *indices)
{
- CoglVertexAttribute *position = NULL;
+ CoglAttribute *position = NULL;
int i;
int n_line_vertices;
static CoglPipeline *wire_pipeline;
- CoglVertexAttribute *wire_attribute[2];
- CoglP3Vertex *lines;
+ CoglAttribute *wire_attribute[2];
+ CoglVertexP3 *lines;
CoglVertexArray *array;
for (i = 0; attributes[i]; i++)
n_vertices,
&n_line_vertices,
indices);
- array = cogl_vertex_array_new (sizeof (CoglP3Vertex) * n_line_vertices,
+ array = cogl_vertex_array_new (sizeof (CoglVertexP3) * n_line_vertices,
lines);
wire_attribute[0] =
- cogl_vertex_attribute_new (array, "cogl_position_in",
- sizeof (CoglP3Vertex),
- 0,
- 3,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ cogl_attribute_new (array, "cogl_position_in",
+ sizeof (CoglVertexP3),
+ 0,
+ 3,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
wire_attribute[1] = NULL;
cogl_object_unref (array);
cogl_push_source (wire_pipeline);
/* temporarily disable the wireframe to avoid recursion! */
- cogl_debug_flags &= ~COGL_DEBUG_WIREFRAME;
- _cogl_draw_vertex_attributes_array (COGL_VERTICES_MODE_LINES,
- 0,
- n_line_vertices,
- wire_attribute);
- cogl_debug_flags |= COGL_DEBUG_WIREFRAME;
+ COGL_DEBUG_CLEAR_FLAG (COGL_DEBUG_WIREFRAME);
+ _cogl_draw_attributes_array (COGL_VERTICES_MODE_LINES,
+ 0,
+ n_line_vertices,
+ wire_attribute,
+ COGL_DRAW_SKIP_JOURNAL_FLUSH |
+ COGL_DRAW_SKIP_PIPELINE_VALIDATION |
+ COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH |
+ COGL_DRAW_SKIP_LEGACY_STATE);
+
+ COGL_DEBUG_SET_FLAG (COGL_DEBUG_WIREFRAME);
cogl_pop_source ();
#endif
static void
-_cogl_draw_vertex_attributes_array_real (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglVertexAttribute **attributes,
- ValidateLayerState *state)
+flush_state (CoglDrawFlags flags,
+ ValidateLayerState *state)
{
- CoglPipeline *source = enable_gl_state (attributes, state);
-
- GE (glDrawArrays ((GLenum)mode, first_vertex, n_vertices));
-
- /* FIXME: we shouldn't be disabling state after drawing we should
- * just disable the things not needed after enabling state. */
- disable_gl_state (attributes, source);
+ if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH))
+ {
+ CoglFramebuffer *framebuffer = _cogl_get_framebuffer ();
+ _cogl_journal_flush (framebuffer->journal, framebuffer);
+ }
-#ifdef COGL_ENABLE_DEBUG
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_WIREFRAME))
- draw_wireframe (mode, first_vertex, n_vertices, attributes, NULL);
-#endif
-}
+ state->unit = 0;
+ state->options.flags = 0;
+ state->fallback_layers = 0;
-/* This can be used by the CoglJournal to draw attributes skipping the
- * implicit journal flush, the framebuffer flush and pipeline
- * validation. */
-void
-_cogl_draw_vertex_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglVertexAttribute **attributes)
-{
- ValidateLayerState state;
+ if (!(flags & COGL_DRAW_SKIP_PIPELINE_VALIDATION))
+ cogl_pipeline_foreach_layer (cogl_get_source (),
+ validate_layer_cb,
+ state);
- state.unit = 0;
- state.options.flags = 0;
- state.fallback_layers = 0;
-
- _cogl_draw_vertex_attributes_array_real (mode, first_vertex, n_vertices,
- attributes, &state);
+ /* NB: _cogl_framebuffer_flush_state may disrupt various state (such
+ * as the pipeline state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. We need to do this
+ * before setting up the array pointers because setting up the clip
+ * stack can cause some drawing which would change the array
+ * pointers. */
+ if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH))
+ _cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0);
}
+/* This can be called directly by the CoglJournal to draw attributes
+ * skipping the implicit journal flush, the framebuffer flush and
+ * pipeline validation. */
void
-cogl_draw_vertex_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglVertexAttribute **attributes)
+_cogl_draw_attributes_array (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglAttribute **attributes,
+ CoglDrawFlags flags)
{
ValidateLayerState state;
+ CoglPipeline *source;
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ flush_state (flags, &state);
- _cogl_journal_flush ();
+ source = enable_gl_state (flags, attributes, &state);
- state.unit = 0;
- state.options.flags = 0;
- state.fallback_layers = 0;
+ GE (glDrawArrays ((GLenum)mode, first_vertex, n_vertices));
- cogl_pipeline_foreach_layer (cogl_get_source (),
- validate_layer_cb,
- &state);
+ /* FIXME: we shouldn't be disabling state after drawing we should
+ * just disable the things not needed after enabling state. */
+ disable_gl_state (attributes, source);
- /* NB: _cogl_framebuffer_flush_state may disrupt various state (such
- * as the pipeline state) when flushing the clip stack, so should
- * always be done first when preparing to draw. We need to do this
- * before setting up the array pointers because setting up the clip
- * stack can cause some drawing which would change the array
- * pointers. */
- _cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0);
+#ifdef COGL_ENABLE_DEBUG
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME)))
+ draw_wireframe (mode, first_vertex, n_vertices, attributes, NULL);
+#endif
+}
- _cogl_draw_vertex_attributes_array_real (mode, first_vertex, n_vertices,
- attributes, &state);
+void
+cogl_draw_attributes_array (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglAttribute **attributes)
+{
+ _cogl_draw_attributes_array (mode, first_vertex,
+ n_vertices, attributes,
+ 0 /* no flags */);
}
void
-cogl_draw_vertex_attributes (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- ...)
+cogl_draw_attributes (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ ...)
{
va_list ap;
int n_attributes;
- CoglVertexAttribute *attribute;
- CoglVertexAttribute **attributes;
+ CoglAttribute *attribute;
+ CoglAttribute **attributes;
int i;
va_start (ap, n_vertices);
- for (n_attributes = 0; va_arg (ap, CoglVertexAttribute *); n_attributes++)
+ for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++)
;
va_end (ap);
- attributes = g_alloca (sizeof (CoglVertexAttribute *) * (n_attributes + 1));
+ attributes = g_alloca (sizeof (CoglAttribute *) * (n_attributes + 1));
attributes[n_attributes] = NULL;
va_start (ap, n_vertices);
- for (i = 0; (attribute = va_arg (ap, CoglVertexAttribute *)); i++)
+ for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++)
attributes[i] = attribute;
va_end (ap);
- cogl_draw_vertex_attributes_array (mode, first_vertex, n_vertices,
- attributes);
+ cogl_draw_attributes_array (mode, first_vertex, n_vertices,
+ attributes);
}
static size_t
g_return_val_if_reached (0);
}
-static void
-_cogl_draw_indexed_vertex_attributes_array_real (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglVertexAttribute **attributes,
- ValidateLayerState *state)
+void
+_cogl_draw_indexed_attributes_array (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglIndices *indices,
+ CoglAttribute **attributes,
+ CoglDrawFlags flags)
{
- CoglPipeline *source = enable_gl_state (attributes, state);
+ ValidateLayerState state;
+ CoglPipeline *source;
CoglBuffer *buffer;
void *base;
size_t array_offset;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ flush_state (flags, &state);
+
+ source = enable_gl_state (flags, attributes, &state);
+
buffer = COGL_BUFFER (cogl_indices_get_array (indices));
base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_INDEX_ARRAY);
array_offset = cogl_indices_get_offset (indices);
disable_gl_state (attributes, source);
#ifdef COGL_ENABLE_DEBUG
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_WIREFRAME))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME)))
draw_wireframe (mode, first_vertex, n_vertices, attributes, indices);
#endif
}
void
-_cogl_draw_indexed_vertex_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglVertexAttribute **attributes)
-{
- ValidateLayerState state;
-
- state.unit = 0;
- state.options.flags = 0;
- state.fallback_layers = 0;
-
- _cogl_draw_indexed_vertex_attributes_array_real (mode,
- first_vertex,
- n_vertices,
- indices,
- attributes,
- &state);
-}
-
-void
-cogl_draw_indexed_vertex_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglVertexAttribute **attributes)
+cogl_draw_indexed_attributes_array (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglIndices *indices,
+ CoglAttribute **attributes)
{
- ValidateLayerState state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_journal_flush ();
-
- state.unit = 0;
- state.options.flags = 0;
- state.fallback_layers = 0;
-
- cogl_pipeline_foreach_layer (cogl_get_source (),
- validate_layer_cb,
- &state);
-
- /* NB: _cogl_framebuffer_flush_state may disrupt various state (such
- * as the pipeline state) when flushing the clip stack, so should
- * always be done first when preparing to draw. We need to do this
- * before setting up the array pointers because setting up the clip
- * stack can cause some drawing which would change the array
- * pointers. */
- _cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0);
-
- _cogl_draw_indexed_vertex_attributes_array_real (mode,
- first_vertex,
- n_vertices,
- indices,
- attributes,
- &state);
+ _cogl_draw_indexed_attributes_array (mode, first_vertex,
+ n_vertices, indices, attributes,
+ 0 /* no flags */);
}
void
-cogl_draw_indexed_vertex_attributes (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- ...)
+cogl_draw_indexed_attributes (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglIndices *indices,
+ ...)
{
va_list ap;
int n_attributes;
- CoglVertexAttribute **attributes;
+ CoglAttribute **attributes;
int i;
- CoglVertexAttribute *attribute;
+ CoglAttribute *attribute;
va_start (ap, indices);
- for (n_attributes = 0; va_arg (ap, CoglVertexAttribute *); n_attributes++)
+ for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++)
;
va_end (ap);
- attributes = g_alloca (sizeof (CoglVertexAttribute *) * (n_attributes + 1));
+ attributes = g_alloca (sizeof (CoglAttribute *) * (n_attributes + 1));
attributes[n_attributes] = NULL;
va_start (ap, indices);
- for (i = 0; (attribute = va_arg (ap, CoglVertexAttribute *)); i++)
+ for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++)
attributes[i] = attribute;
va_end (ap);
- cogl_draw_indexed_vertex_attributes_array (mode,
- first_vertex,
- n_vertices,
- indices,
- attributes);
+ cogl_draw_indexed_attributes_array (mode,
+ first_vertex,
+ n_vertices,
+ indices,
+ attributes);
}
#error "Only <cogl/cogl.h> can be included directly."
#endif
-#ifndef __COGL_VERTEX_ATTRIBUTE_H__
-#define __COGL_VERTEX_ATTRIBUTE_H__
+#ifndef __COGL_ATTRIBUTE_H__
+#define __COGL_ATTRIBUTE_H__
#include <cogl/cogl-vertex-array.h>
#include <cogl/cogl-indices.h>
G_BEGIN_DECLS
/**
- * SECTION:cogl-vertex-attribute
- * @short_description: Fuctions for declaring and drawing vertex
+ * SECTION:cogl-attribute
+ * @short_description: Functions for declaring and drawing vertex
* attributes
*
* FIXME
*/
-typedef struct _CoglVertexAttribute CoglVertexAttribute;
+typedef struct _CoglAttribute CoglAttribute;
/**
- * CoglVertexAttributeType:
- * @COGL_VERTEX_ATTRIBUTE_TYPE_BYTE: Data is the same size of a byte
- * @COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_BYTE: Data is the same size of an
- * unsigned byte
- * @COGL_VERTEX_ATTRIBUTE_TYPE_SHORT: Data is the same size of a short integer
- * @COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_SHORT: Data is the same size of
- * an unsigned short integer
- * @COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT: Data is the same size of a float
- *
- * Data types for the components of a vertex attribute.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-typedef enum {
- COGL_VERTEX_ATTRIBUTE_TYPE_BYTE = 0x1400,
- COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_BYTE = 0x1401,
- COGL_VERTEX_ATTRIBUTE_TYPE_SHORT = 0x1402,
- COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_SHORT = 0x1403,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT = 0x1406
-} CoglVertexAttributeType;
-
-/**
- * cogl_vertex_attribute_new:
+ * cogl_attribute_new:
* @array: The #CoglVertexArray containing the actual attribute data
* @name: The name of the attribute (used to reference it from GLSL)
* @stride: The number of bytes to jump to get to the next attribute
* mapped into the GPU which can be a bottlneck when dealing with
* a large number of vertices.
*
- * Returns: A newly allocated #CoglVertexAttribute describing the
+ * Returns: A newly allocated #CoglAttribute describing the
* layout for a list of attribute values stored in @array.
*
* Since: 1.4
*/
/* XXX: look for a precedent to see if the stride/offset args should
* have a different order. */
-CoglVertexAttribute *
-cogl_vertex_attribute_new (CoglVertexArray *array,
- const char *name,
- gsize stride,
- gsize offset,
- int components,
- CoglVertexAttributeType type);
+CoglAttribute *
+cogl_attribute_new (CoglVertexArray *array,
+ const char *name,
+ gsize stride,
+ gsize offset,
+ int components,
+ CoglAttributeType type);
/**
- * cogl_is_vertex_attribute:
+ * cogl_is_attribute:
* @object: A #CoglObject
*
- * Gets whether the given object references a #CoglVertexAttribute.
+ * Gets whether the given object references a #CoglAttribute.
*
- * Return value: %TRUE if the handle references a #CoglVertexAttribute,
+ * Return value: %TRUE if the handle references a #CoglAttribute,
* %FALSE otherwise
*/
gboolean
-cogl_is_vertex_attribute (void *object);
+cogl_is_attribute (void *object);
void
-cogl_draw_vertex_attributes (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- ...) G_GNUC_NULL_TERMINATED;
+cogl_draw_attributes (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ ...) G_GNUC_NULL_TERMINATED;
void
-cogl_draw_vertex_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglVertexAttribute **attributes);
+cogl_draw_attributes_array (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglAttribute **attributes);
void
-cogl_draw_indexed_vertex_attributes (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- ...) G_GNUC_NULL_TERMINATED;
+cogl_draw_indexed_attributes (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglIndices *indices,
+ ...) G_GNUC_NULL_TERMINATED;
void
-cogl_draw_indexed_vertex_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglVertexAttribute **attributes);
+cogl_draw_indexed_attributes_array (CoglVerticesMode mode,
+ int first_vertex,
+ int n_vertices,
+ CoglIndices *indices,
+ CoglAttribute **attributes);
G_END_DECLS
-#endif /* __COGL_VERTEX_ATTRIBUTE_H__ */
+#endif /* __COGL_ATTRIBUTE_H__ */
int width;
int height;
int rowstride;
- int aligned_rowstride;
int bits_per_sample;
int n_channels;
- guint8 *pixels;
- guint8 *out_data;
- guint8 *out;
- int r;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
return FALSE;
}
- /* Work out what the rowstride would be if it was packing the data
- but aligned to 4 bytes */
- aligned_rowstride = (width * n_channels + 3) & ~3;
-
- /* The documentation for GdkPixbuf states that is not safe to read
- all of the data as height*rowstride because the buffer might not
- be allocated to include the full length of the rowstride for the
- last row so arguably we should always copy the buffer when
- rowstride != width*bpp because some places in Cogl assume that it
- can memcpy(height*rowstride). However that rule is probably only
- in place so that GdkPixbuf can implement gdk_pixbuf_new_subpixbuf
- by just sharing the data and setting a large rowstride. That does
- not apply in this case because we are just creating a new buffer
- for a file. It seems very unlikely that GdkPixbuf would not
- allocate the full rowstride in this case and it is highly
- desirable to avoid copying the buffer. This instead just assumes
- that whatever buffer pixbuf points into will always be allocated
- to a 4-byte aligned buffer so we can avoid copying unless the
- rowstride is unusually large */
- if (rowstride <= aligned_rowstride)
- return _cogl_bitmap_new_from_data (gdk_pixbuf_get_pixels (pixbuf),
- pixel_format,
- width,
- height,
- rowstride,
- _cogl_bitmap_unref_pixbuf,
- pixbuf);
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- out_data = g_malloc (aligned_rowstride * height);
- out = out_data;
-
- for (r = 0; r < height; ++r)
- {
- memcpy (out, pixels, n_channels * width);
- pixels += rowstride;
- out += aligned_rowstride;
- }
-
- /* Destroy GdkPixbuf object */
- g_object_unref (pixbuf);
-
- return _cogl_bitmap_new_from_data (out_data,
+ /* We just use the data directly from the pixbuf so that we don't
+ have to copy to a seperate buffer. Note that Cogl is expected not
+ to read past the end of bpp*width on the last row even if the
+ rowstride is much larger so we don't need to worry about
+ GdkPixbuf's semantics that it may under-allocate the buffer. */
+ return _cogl_bitmap_new_from_data (gdk_pixbuf_get_pixels (pixbuf),
pixel_format,
width,
height,
- aligned_rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
+ rowstride,
+ _cogl_bitmap_unref_pixbuf,
+ pixbuf);
}
#else
int width,
int height);
+/* Creates a deep copy of the source bitmap */
+CoglBitmap *
+_cogl_bitmap_copy (CoglBitmap *src_bmp);
+
gboolean
_cogl_bitmap_get_size_from_file (const char *filename,
int *width,
int
_cogl_bitmap_get_rowstride (CoglBitmap *bitmap);
+/* Maps the bitmap so that the pixels can be accessed directly or if
+ the bitmap is just a memory bitmap then it just returns the pointer
+ to memory. Note that the bitmap isn't guaranteed to allocated to
+ the full size of rowstride*height so it is not safe to read up to
+ the rowstride of the last row. This will be the case if the user
+ uploads data using gdk_pixbuf_new_subpixbuf with a sub region
+ containing the last row of the pixbuf because in that case the
+ rowstride can be much larger than the width of the image */
guint8 *
_cogl_bitmap_map (CoglBitmap *bitmap,
CoglBufferAccess access,
return dst_bmp;
}
+CoglBitmap *
+_cogl_bitmap_copy (CoglBitmap *src_bmp)
+{
+ CoglBitmap *dst_bmp;
+ CoglPixelFormat src_format = _cogl_bitmap_get_format (src_bmp);
+ int bpp = _cogl_get_format_bpp (src_format);
+ int width = _cogl_bitmap_get_width (src_bmp);
+ int height = _cogl_bitmap_get_height (src_bmp);
+ int dst_rowstride = width * bpp;
+
+ /* Round the rowstride up to the next nearest multiple of 4 bytes */
+ dst_rowstride = (dst_rowstride + 3) & ~3;
+
+ dst_bmp = _cogl_bitmap_new_from_data (g_malloc (dst_rowstride * height),
+ src_format,
+ width, height,
+ dst_rowstride,
+ (CoglBitmapDestroyNotify) g_free,
+ NULL);
+
+ _cogl_bitmap_copy_subregion (src_bmp,
+ dst_bmp,
+ 0, 0, /* src_x/y */
+ 0, 0, /* dst_x/y */
+ width, height);
+
+ return dst_bmp;
+}
+
void
_cogl_bitmap_copy_subregion (CoglBitmap *src,
CoglBitmap *dst,
"Invalid texture combine string: %s",
error_string);
- if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
{
g_debug ("Invalid texture combine string: %s",
error_string);
"blend" : "texture combine",
error_string);
- if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
{
g_debug ("Invalid %s string: %s",
context == COGL_BLEND_STRING_CONTEXT_BLENDING ?
offset,
error_string);
- if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
{
g_debug ("Syntax error for argument %d at offset %d: %s",
current_arg, offset, error_string);
int remaining_argc = 0;
#if 0
- cogl_debug_flags |= COGL_DEBUG_BLEND_STRINGS;
+ COGL_DEBUG_SET_FLAG (COGL_DEBUG_BLEND_STRINGS);
#endif
- if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
{
COGL_NOTE (BLEND_STRINGS, "Compiling %s string:\n%s\n",
context == COGL_BLEND_STRING_CONTEXT_BLENDING ?
finished:
- if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
{
if (current_statement > 0)
print_statement (0, &statements[0]);
offset,
error_string);
- if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
{
g_debug ("Syntax error at offset %d: %s",
offset, error_string);
typedef enum _CoglBufferFlags
{
- COGL_BUFFER_FLAG_NONE = 0,
- COGL_BUFFER_FLAG_BUFFER_OBJECT = 1UL << 0, /* real openGL buffer object */
- COGL_BUFFER_FLAG_MAPPED = 1UL << 1
+ COGL_BUFFER_FLAG_NONE = 0,
+ COGL_BUFFER_FLAG_BUFFER_OBJECT = 1UL << 0, /* real openGL buffer object */
+ COGL_BUFFER_FLAG_MAPPED = 1UL << 1,
+ COGL_BUFFER_FLAG_MAPPED_FALLBACK = 1UL << 2
} CoglBufferFlags;
typedef enum {
void
_cogl_buffer_immutable_unref (CoglBuffer *buffer);
+/* This is a wrapper around cogl_buffer_map for internal use when we
+ want to map the buffer for write only to replace the entire
+ contents. If the map fails then it will fallback to writing to a
+ temporary buffer. When _cogl_buffer_unmap_for_fill_or_fallback is
+ called the temporary buffer will be copied into the array. Note
+ that these calls share a global array so they can not be nested. */
+void *
+_cogl_buffer_map_for_fill_or_fallback (CoglBuffer *buffer);
+
+void
+_cogl_buffer_unmap_for_fill_or_fallback (CoglBuffer *buffer);
+
G_END_DECLS
#endif /* __COGL_BUFFER_PRIVATE_H__ */
#define glBufferSubData ctx->drv.pf_glBufferSubData
#define glGetBufferSubData ctx->drv.pf_glGetBufferSubData
#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
-#define glMapBuffer ctx->drv.pf_glMapBuffer
-#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
#endif
+/* These two are always accessed through an extension, even on GLES */
+#define glMapBuffer ctx->drv.pf_glMapBuffer
+#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
+
#ifndef GL_PIXEL_PACK_BUFFER
#define GL_PIXEL_PACK_BUFFER 0x88EB
#endif
#ifndef GL_ELEMENT_ARRAY_BUFFER
#define GL_ARRAY_BUFFER 0x8893
#endif
+#ifndef GL_READ_ONLY
+#define GL_READ_ONLY 0x88B8
+#endif
+#ifndef GL_WRITE_ONLY
+#define GL_WRITE_ONLY 0x88B9
+#endif
+#ifndef GL_READ_WRITE
+#define GL_READ_WRITE 0x88BA
+#endif
/* XXX:
* The CoglHandle macros don't support any form of inheritance, so for
CoglBufferAccess access,
CoglBufferMapHint hints)
{
-#ifndef COGL_HAS_GLES
guint8 *data;
CoglBufferBindTarget target;
GLenum gl_target;
_COGL_GET_CONTEXT (ctx, NULL);
+ if ((access & COGL_BUFFER_ACCESS_READ) &&
+ !cogl_features_available (COGL_FEATURE_MAP_BUFFER_FOR_READ))
+ return NULL;
+ if ((access & COGL_BUFFER_ACCESS_WRITE) &&
+ !cogl_features_available (COGL_FEATURE_MAP_BUFFER_FOR_WRITE))
+ return NULL;
+
target = buffer->last_target;
_cogl_buffer_bind (buffer, target);
_cogl_buffer_unbind (buffer);
return data;
-
-#else /* COGL_HAS_GLES */
-
- return NULL;
-
-#endif /* COGL_HAS_GLES */
}
static void
bo_unmap (CoglBuffer *buffer)
{
-#ifndef COGL_HAS_GLES
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
_cogl_buffer_bind (buffer, buffer->last_target);
buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED;
_cogl_buffer_unbind (buffer);
-#else
- g_return_if_reached ();
-#endif
}
static gboolean
g_free (buffer->data);
}
-/* OpenGL ES 1.1 and 2 have a GL_OES_mapbuffer extension that is able to map
- * VBOs for write only, we don't support that in CoglBuffer */
-#if defined (COGL_HAS_GLES)
-GLenum
-_cogl_buffer_access_to_gl_enum (CoglBufferAccess access)
-{
- return 0;
-}
-
-#else
GLenum
_cogl_buffer_access_to_gl_enum (CoglBufferAccess access)
{
else
return GL_READ_ONLY;
}
-#endif
/* OpenGL ES 1.1 and 2 only know about STATIC_DRAW and DYNAMIC_DRAW */
#if defined (COGL_HAS_GLES)
buffer->vtable.unmap (buffer);
}
+void *
+_cogl_buffer_map_for_fill_or_fallback (CoglBuffer *buffer)
+{
+ void *ret;
+
+ _COGL_GET_CONTEXT (ctx, NULL);
+
+ g_return_val_if_fail (!ctx->buffer_map_fallback_in_use, NULL);
+
+ ctx->buffer_map_fallback_in_use = TRUE;
+
+ ret = cogl_buffer_map (buffer,
+ COGL_BUFFER_ACCESS_WRITE,
+ COGL_BUFFER_MAP_HINT_DISCARD);
+
+ if (ret)
+ return ret;
+ else
+ {
+ /* If the map fails then we'll use a temporary buffer to fill
+ the data and then upload it using cogl_buffer_set_data when
+ the buffer is unmapped. The temporary buffer is shared to
+ avoid reallocating it every time */
+ g_byte_array_set_size (ctx->buffer_map_fallback_array, buffer->size);
+
+ buffer->flags |= COGL_BUFFER_FLAG_MAPPED_FALLBACK;
+
+ return ctx->buffer_map_fallback_array->data;
+ }
+}
+
+void
+_cogl_buffer_unmap_for_fill_or_fallback (CoglBuffer *buffer)
+{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ g_return_if_fail (ctx->buffer_map_fallback_in_use);
+
+ ctx->buffer_map_fallback_in_use = FALSE;
+
+ if ((buffer->flags & COGL_BUFFER_FLAG_MAPPED_FALLBACK))
+ {
+ cogl_buffer_set_data (buffer, 0,
+ ctx->buffer_map_fallback_array->data,
+ buffer->size);
+ buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED_FALLBACK;
+ }
+ else
+ cogl_buffer_unmap (buffer);
+}
+
gboolean
cogl_buffer_set_data (CoglBuffer *buffer,
gsize offset,
/* temporarily swap in our special stenciling pipeline */
cogl_push_source (ctx->stencil_pipeline);
+ /* This can be called from the journal code which doesn't flush
+ the matrix stacks between calls so we need to ensure they're
+ flushed now */
+ _cogl_matrix_stack_flush_to_gl (modelview_stack,
+ COGL_MATRIX_MODELVIEW);
+ _cogl_matrix_stack_flush_to_gl (projection_stack,
+ COGL_MATRIX_PROJECTION);
+
if (first)
{
GE( glEnable (GL_STENCIL_TEST) );
GE( glStencilFunc (GL_NEVER, 0x1, 0x1) );
GE( glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE) );
- /* This can be called from the journal code which doesn't flush
- the matrix stacks between calls so we need to ensure they're
- flushed now */
- _cogl_matrix_stack_flush_to_gl (modelview_stack,
- COGL_MATRIX_MODELVIEW);
- _cogl_matrix_stack_flush_to_gl (projection_stack,
- COGL_MATRIX_PROJECTION);
-
_cogl_rectangle_immediate (x_1, y_1, x_2, y_2);
}
else
}
void
+_cogl_clip_stack_get_bounds (CoglClipStack *stack,
+ int *scissor_x0,
+ int *scissor_y0,
+ int *scissor_x1,
+ int *scissor_y1)
+{
+ CoglClipStack *entry;
+
+ *scissor_x0 = 0;
+ *scissor_y0 = 0;
+ *scissor_x1 = G_MAXINT;
+ *scissor_y1 = G_MAXINT;
+
+ for (entry = stack; entry; entry = entry->parent)
+ {
+ /* Get the intersection of the current scissor and the bounding
+ box of this clip */
+ *scissor_x0 = MAX (*scissor_x0, entry->bounds_x0);
+ *scissor_y0 = MAX (*scissor_y0, entry->bounds_y0);
+ *scissor_x1 = MIN (*scissor_x1, entry->bounds_x1);
+ *scissor_y1 = MIN (*scissor_y1, entry->bounds_y1);
+ }
+}
+
+void
_cogl_clip_stack_flush (CoglClipStack *stack)
{
int has_clip_planes;
gboolean using_clip_planes = FALSE;
gboolean using_stencil_buffer = FALSE;
- int scissor_x0 = 0;
- int scissor_y0 = 0;
- int scissor_x1 = G_MAXINT;
- int scissor_y1 = G_MAXINT;
+ int scissor_x0;
+ int scissor_y0;
+ int scissor_x1;
+ int scissor_y1;
CoglMatrixStack *modelview_stack;
CoglClipStack *entry;
int scissor_y_start;
/* If the stack is empty then there's nothing else to do */
if (stack == NULL)
{
+ COGL_NOTE (CLIPPING, "Flushed empty clip stack");
+
ctx->current_clip_stack_uses_stencil = FALSE;
GE (glDisable (GL_SCISSOR_TEST));
return;
clear the stencil buffer then the clear will be clipped to the
intersection of all of the bounding boxes. This saves having to
clear the whole stencil buffer */
- for (entry = stack; entry; entry = entry->parent)
- {
- /* Get the intersection of the current scissor and the bounding
- box of this clip */
- scissor_x0 = MAX (scissor_x0, entry->bounds_x0);
- scissor_y0 = MAX (scissor_y0, entry->bounds_y0);
- scissor_x1 = MIN (scissor_x1, entry->bounds_x1);
- scissor_y1 = MIN (scissor_y1, entry->bounds_y1);
- }
+ _cogl_clip_stack_get_bounds (stack,
+ &scissor_x0, &scissor_y0,
+ &scissor_x1, &scissor_y1);
/* Enable scissoring as soon as possible */
if (scissor_x0 >= scissor_x1 || scissor_y0 >= scissor_y1)
}
}
+ COGL_NOTE (CLIPPING, "Flushing scissor to (%i, %i, %i, %i)",
+ scissor_x0, scissor_y0,
+ scissor_x1, scissor_y1);
+
GE (glEnable (GL_SCISSOR_TEST));
GE (glScissor (scissor_x0, scissor_y_start,
scissor_x1 - scissor_x0,
{
CoglClipStackPath *path_entry = (CoglClipStackPath *) entry;
+ COGL_NOTE (CLIPPING, "Adding stencil clip for path");
+
_cogl_matrix_stack_push (modelview_stack);
_cogl_matrix_stack_set (modelview_stack, &path_entry->matrix);
them then use that instead */
if (has_clip_planes)
{
+ COGL_NOTE (CLIPPING, "Adding clip planes clip for rectangle");
+
set_clip_planes (rect->x0,
rect->y0,
rect->x1,
}
else
{
+ COGL_NOTE (CLIPPING, "Adding stencil clip for rectangle");
+
add_stencil_clip_rectangle (rect->x0,
rect->y0,
rect->x1,
_cogl_clip_stack_pop (CoglClipStack *stack);
void
+_cogl_clip_stack_get_bounds (CoglClipStack *stack,
+ int *scissor_x0,
+ int *scissor_y0,
+ int *scissor_x1,
+ int *scissor_y1);
+
+void
_cogl_clip_stack_flush (CoglClipStack *stack);
CoglClipStack *
void
cogl_clip_ensure (void)
{
+ CoglFramebuffer *framebuffer = _cogl_get_framebuffer ();
CoglClipState *clip_state;
- clip_state = _cogl_framebuffer_get_clip_state (_cogl_get_framebuffer ());
+ clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
/* Flushing the clip state doesn't cause the journal to be
flushed. This function may be being called by an external
application however so it makes sense to flush the journal
here */
- _cogl_journal_flush ();
+ _cogl_framebuffer_flush_journal (framebuffer);
_cogl_clip_state_flush (clip_state);
}
}
CoglClipStack *
-_cogl_get_clip_stack (void)
+_cogl_clip_state_get_stack (CoglClipState *clip_state)
{
- CoglFramebuffer *framebuffer;
- CoglClipState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- framebuffer = _cogl_get_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
return clip_state->stacks->data;
}
void
-_cogl_set_clip_stack (CoglClipStack *stack)
+_cogl_clip_state_set_stack (CoglClipState *clip_state,
+ CoglClipStack *stack)
{
- CoglFramebuffer *framebuffer;
- CoglClipState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = _cogl_get_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
/* Replace the top of the stack of stacks */
_cogl_clip_stack_ref (stack);
_cogl_clip_stack_unref (clip_state->stacks->data);
void
_cogl_clip_state_flush (CoglClipState *clip_state);
-/*
- * _cogl_get_clip_stack:
- *
- * Gets a pointer to the current clip stack. This can be used to later
- * return to the same clip stack state with _cogl_set_clip_stack(). A
- * reference is not taken on the stack so if you want to keep it you
- * should call _cogl_clip_stack_ref().
- *
- * Return value: a pointer to the current clip stack.
- */
CoglClipStack *
-_cogl_get_clip_stack (void);
+_cogl_clip_state_get_stack (CoglClipState *clip_state);
-/*
- * _cogl_set_clip_stack:
- * @stack: a pointer to the replacement clip stack
- *
- * Replaces the current clip stack with @stack.
- */
void
-_cogl_set_clip_stack (CoglClipStack *stack);
+_cogl_clip_state_set_stack (CoglClipState *clip_state,
+ CoglClipStack *clip_stack);
#endif /* __COGL_CLIP_STATE_H */
static void
_cogl_init_feature_overrides (CoglContext *ctx)
{
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_VBOS))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_VBOS)))
ctx->feature_flags &= ~COGL_FEATURE_VBOS;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_PBOS))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PBOS)))
ctx->feature_flags &= ~COGL_FEATURE_PBOS;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_ARBFP))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ARBFP)))
ctx->feature_flags &= ~COGL_FEATURE_SHADERS_ARBFP;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_GLSL))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_GLSL)))
ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_NPOT_TEXTURES))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_NPOT_TEXTURES)))
ctx->feature_flags &= ~(COGL_FEATURE_TEXTURE_NPOT |
COGL_FEATURE_TEXTURE_NPOT_BASIC |
COGL_FEATURE_TEXTURE_NPOT_MIPMAP |
_context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
_context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE;
- _context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
- _context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));
+ _context->framebuffers = NULL;
+
_context->journal_flush_attributes_array =
- g_array_new (TRUE, FALSE, sizeof (CoglVertexAttribute *));
+ g_array_new (TRUE, FALSE, sizeof (CoglAttribute *));
_context->journal_clip_bounds = NULL;
_context->polygon_vertices = g_array_new (FALSE, FALSE, sizeof (float));
_context->atlases = NULL;
+ _context->buffer_map_fallback_array = g_byte_array_new ();
+ _context->buffer_map_fallback_in_use = FALSE;
+
/* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
unless GL_COORD_REPLACE is enabled for an individual
layer. Therefore it seems like it should be ok to just leave it
enabled all the time instead of having to have a set property on
each pipeline to track whether any layers have point sprite
- coords enabled */
+ coords enabled. We don't need to do this for GLES2 because point
+ sprites are handled using a builtin varying in the shader. */
+#ifndef HAVE_COGL_GLES2
if (cogl_features_available (COGL_FEATURE_POINT_SPRITE))
GE (glEnable (GL_POINT_SPRITE));
+#endif
return TRUE;
}
if (_context->texture_pipeline)
cogl_handle_unref (_context->texture_pipeline);
- if (_context->journal)
- g_array_free (_context->journal, TRUE);
- if (_context->logged_vertices)
- g_array_free (_context->logged_vertices, TRUE);
if (_context->journal_flush_attributes_array)
g_array_free (_context->journal_flush_attributes_array, TRUE);
if (_context->journal_clip_bounds)
g_hash_table_unref (_context->arbfp_cache);
#endif
+ g_byte_array_free (_context->buffer_map_fallback_array, TRUE);
+
g_free (_context);
}
CoglHandle default_gl_texture_2d_tex;
CoglHandle default_gl_texture_rect_tex;
- /* Batching geometry... */
- /* We journal the texture rectangles we want to submit to OpenGL so
- * we have an oppertunity to optimise the final order so that we
- * can batch things together. */
- GArray *journal;
- GArray *logged_vertices;
+ /* Central list of all framebuffers so all journals can be flushed
+ * at any time. */
+ GList *framebuffers;
+
+ /* Global journal buffers */
GArray *journal_flush_attributes_array;
- size_t journal_needed_vbo_len;
GArray *journal_clip_bounds;
GArray *polygon_vertices;
stencil buffer */
gboolean current_clip_stack_uses_stencil;
+ /* This is used as a temporary buffer to fill a CoglBuffer when
+ cogl_buffer_map fails and we only want to map to fill it with new
+ data */
+ GByteArray *buffer_map_fallback_array;
+ gboolean buffer_map_fallback_in_use;
+
CoglContextDriver drv;
CoglContextWinsys winsys;
} CoglContext;
"disable-program-caches",
"Disable program caches",
"Disable fallback caches for arbfp and glsl programs")
-
+OPT (DISABLE_FAST_READ_PIXEL,
+ "Root Cause",
+ "disable-fast-read-pixel",
+ "Disable read pixel optimization",
+ "Disable optimization for reading 1px for simple "
+ "scenes of opaque rectangles")
+OPT (CLIPPING,
+ "Cogl Tracing",
+ "clipping",
+ "Trace clipping",
+ "Logs information about how Cogl is implementing clipping")
{ "show-source", COGL_DEBUG_SHOW_SOURCE},
{ "offscreen", COGL_DEBUG_OFFSCREEN },
{ "texture-pixmap", COGL_DEBUG_TEXTURE_PIXMAP },
- { "bitmap", COGL_DEBUG_BITMAP }
+ { "bitmap", COGL_DEBUG_BITMAP },
+ { "clipping", COGL_DEBUG_CLIPPING }
};
static const int n_cogl_log_debug_keys =
G_N_ELEMENTS (cogl_log_debug_keys);
{ "disable-npot-textures", COGL_DEBUG_DISABLE_NPOT_TEXTURES},
{ "wireframe", COGL_DEBUG_WIREFRAME},
{ "disable-software-clip", COGL_DEBUG_DISABLE_SOFTWARE_CLIP},
- { "disable-program-caches", COGL_DEBUG_DISABLE_PROGRAM_CACHES}
+ { "disable-program-caches", COGL_DEBUG_DISABLE_PROGRAM_CACHES},
+ { "disable-fast-read-pixel", COGL_DEBUG_DISABLE_FAST_READ_PIXEL}
};
static const int n_cogl_behavioural_debug_keys =
G_N_ELEMENTS (cogl_behavioural_debug_keys);
#endif /* COGL_ENABLE_DEBUG */
-unsigned int cogl_debug_flags = 0;
+unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
#ifdef COGL_ENABLE_DEBUG
-static unsigned int
+
+static void
+_cogl_parse_debug_string_for_keys (const char *value,
+ gboolean enable,
+ const GDebugKey *keys,
+ unsigned int nkeys)
+{
+ int int_num, key_num;
+
+ /* g_parse_debug_string expects the value field in GDebugKey to be a
+ mask in a guint but we may have multiple guints so we need to
+ build a separate array for each possible guint */
+
+ for (int_num = 0; int_num < COGL_DEBUG_N_INTS; int_num++)
+ {
+ GDebugKey keys_for_int[sizeof (unsigned int) * 8];
+ unsigned int mask_for_int;
+ int nkeys_for_int = 0;
+
+ for (key_num = 0; key_num < nkeys; key_num++)
+ if (COGL_DEBUG_GET_FLAG_INDEX (keys[key_num].value) == int_num)
+ {
+ keys_for_int[nkeys_for_int] = keys[key_num];
+ keys_for_int[nkeys_for_int].value =
+ COGL_DEBUG_GET_FLAG_MASK (keys[key_num].value);
+ nkeys_for_int++;
+ }
+
+ if (nkeys_for_int > 0)
+ {
+ mask_for_int = g_parse_debug_string (value,
+ keys_for_int,
+ nkeys_for_int);
+ if (enable)
+ _cogl_debug_flags[int_num] |= mask_for_int;
+ else
+ _cogl_debug_flags[int_num] &= ~mask_for_int;
+ }
+ }
+}
+
+static void
_cogl_parse_debug_string (const char *value,
+ gboolean enable,
gboolean ignore_help)
{
- unsigned int flags = 0;
-
if (ignore_help && strcmp (value, "help") == 0)
- return 0;
+ return;
/* We don't want to let g_parse_debug_string handle "all" because
* literally enabling all the debug options wouldn't be useful to
{
int i;
for (i = 0; i < n_cogl_log_debug_keys; i++)
- flags |= cogl_log_debug_keys[i].value;
+ if (enable)
+ COGL_DEBUG_SET_FLAG (cogl_log_debug_keys[i].value);
+ else
+ COGL_DEBUG_CLEAR_FLAG (cogl_log_debug_keys[i].value);
}
else if (strcmp (value, "help") == 0)
{
}
else
{
- flags |=
- g_parse_debug_string (value,
- cogl_log_debug_keys,
- n_cogl_log_debug_keys);
- flags |=
- g_parse_debug_string (value,
- cogl_behavioural_debug_keys,
- n_cogl_behavioural_debug_keys);
+ _cogl_parse_debug_string_for_keys (value,
+ enable,
+ cogl_log_debug_keys,
+ n_cogl_log_debug_keys);
+ _cogl_parse_debug_string_for_keys (value,
+ enable,
+ cogl_behavioural_debug_keys,
+ n_cogl_behavioural_debug_keys);
}
-
- return flags;
}
static gboolean
const char *value,
gpointer user_data)
{
- cogl_debug_flags |= _cogl_parse_debug_string (value, FALSE);
+ _cogl_parse_debug_string (value,
+ TRUE /* enable the flags */,
+ FALSE /* don't ignore help */);
return TRUE;
}
const char *value,
gpointer user_data)
{
- cogl_debug_flags &= ~_cogl_parse_debug_string (value, TRUE);
+ _cogl_parse_debug_string (value,
+ FALSE, /* disable the flags */
+ TRUE /* ignore help */);
return TRUE;
}
#endif /* COGL_ENABLE_DEBUG */
env_string = g_getenv ("COGL_DEBUG");
if (env_string != NULL)
{
- cogl_debug_flags |= _cogl_parse_debug_string (env_string, FALSE);
+ _cogl_parse_debug_string (env_string,
+ TRUE /* enable the flags */,
+ FALSE /* don't ignore help */);
env_string = NULL;
}
#endif /* COGL_ENABLE_DEBUG */
G_BEGIN_DECLS
typedef enum {
- COGL_DEBUG_SLICING = 1 << 1,
- COGL_DEBUG_OFFSCREEN = 1 << 2,
- COGL_DEBUG_DRAW = 1 << 3,
- COGL_DEBUG_PANGO = 1 << 4,
- COGL_DEBUG_RECTANGLES = 1 << 5,
- COGL_DEBUG_HANDLE = 1 << 6,
- COGL_DEBUG_BLEND_STRINGS = 1 << 7,
- COGL_DEBUG_DISABLE_BATCHING = 1 << 8,
- COGL_DEBUG_DISABLE_VBOS = 1 << 9,
- COGL_DEBUG_DISABLE_PBOS = 1 << 10,
- COGL_DEBUG_JOURNAL = 1 << 11,
- COGL_DEBUG_BATCHING = 1 << 12,
- COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM = 1 << 13,
- COGL_DEBUG_MATRICES = 1 << 14,
- COGL_DEBUG_ATLAS = 1 << 15,
- COGL_DEBUG_DUMP_ATLAS_IMAGE = 1 << 16,
- COGL_DEBUG_DISABLE_ATLAS = 1 << 17,
- COGL_DEBUG_OPENGL = 1 << 18,
- COGL_DEBUG_DISABLE_TEXTURING = 1 << 19,
- COGL_DEBUG_DISABLE_ARBFP = 1 << 20,
- COGL_DEBUG_DISABLE_FIXED = 1 << 21,
- COGL_DEBUG_DISABLE_GLSL = 1 << 22,
- COGL_DEBUG_SHOW_SOURCE = 1 << 23,
- COGL_DEBUG_DISABLE_BLENDING = 1 << 24,
- COGL_DEBUG_TEXTURE_PIXMAP = 1 << 25,
- COGL_DEBUG_BITMAP = 1 << 26,
- COGL_DEBUG_DISABLE_NPOT_TEXTURES = 1 << 27,
- COGL_DEBUG_WIREFRAME = 1 << 28,
- COGL_DEBUG_DISABLE_SOFTWARE_CLIP = 1 << 29,
- COGL_DEBUG_DISABLE_PROGRAM_CACHES = 1 << 30
+ COGL_DEBUG_SLICING,
+ COGL_DEBUG_OFFSCREEN,
+ COGL_DEBUG_DRAW,
+ COGL_DEBUG_PANGO,
+ COGL_DEBUG_RECTANGLES,
+ COGL_DEBUG_HANDLE,
+ COGL_DEBUG_BLEND_STRINGS,
+ COGL_DEBUG_DISABLE_BATCHING,
+ COGL_DEBUG_DISABLE_VBOS,
+ COGL_DEBUG_DISABLE_PBOS,
+ COGL_DEBUG_JOURNAL,
+ COGL_DEBUG_BATCHING,
+ COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM,
+ COGL_DEBUG_MATRICES,
+ COGL_DEBUG_ATLAS,
+ COGL_DEBUG_DUMP_ATLAS_IMAGE,
+ COGL_DEBUG_DISABLE_ATLAS,
+ COGL_DEBUG_OPENGL,
+ COGL_DEBUG_DISABLE_TEXTURING,
+ COGL_DEBUG_DISABLE_ARBFP,
+ COGL_DEBUG_DISABLE_FIXED,
+ COGL_DEBUG_DISABLE_GLSL,
+ COGL_DEBUG_SHOW_SOURCE,
+ COGL_DEBUG_DISABLE_BLENDING,
+ COGL_DEBUG_TEXTURE_PIXMAP,
+ COGL_DEBUG_BITMAP,
+ COGL_DEBUG_DISABLE_NPOT_TEXTURES,
+ COGL_DEBUG_WIREFRAME,
+ COGL_DEBUG_DISABLE_SOFTWARE_CLIP,
+ COGL_DEBUG_DISABLE_PROGRAM_CACHES,
+ COGL_DEBUG_DISABLE_FAST_READ_PIXEL,
+ COGL_DEBUG_CLIPPING,
+
+ COGL_DEBUG_N_FLAGS
} CoglDebugFlags;
#ifdef COGL_ENABLE_DEBUG
+#define COGL_DEBUG_N_INTS ((COGL_DEBUG_N_FLAGS + \
+ (sizeof (unsigned int) * 8 - 1)) \
+ / (sizeof (unsigned int) * 8))
+
+/* It would probably make sense to use unsigned long here instead
+ because then on 64-bit systems where it can handle 64-bits just as
+ easily and it can test more bits. However GDebugKey uses a guint
+ for the mask and we need to fit the masks into this */
+extern unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
+
+#define COGL_DEBUG_GET_FLAG_INDEX(flag) \
+ ((flag) / (sizeof (unsigned int) * 8))
+#define COGL_DEBUG_GET_FLAG_MASK(flag) \
+ (1U << ((unsigned int) (flag) & (sizeof (unsigned int) * 8 - 1)))
+
+#define COGL_DEBUG_ENABLED(flag) \
+ (!!(_cogl_debug_flags[COGL_DEBUG_GET_FLAG_INDEX (flag)] & \
+ COGL_DEBUG_GET_FLAG_MASK (flag)))
+
+#define COGL_DEBUG_SET_FLAG(flag) \
+ (_cogl_debug_flags[COGL_DEBUG_GET_FLAG_INDEX (flag)] |= \
+ COGL_DEBUG_GET_FLAG_MASK (flag))
+
+#define COGL_DEBUG_CLEAR_FLAG(flag) \
+ (_cogl_debug_flags[COGL_DEBUG_GET_FLAG_INDEX (flag)] &= \
+ ~COGL_DEBUG_GET_FLAG_MASK (flag))
+
#ifdef __GNUC__
#define COGL_NOTE(type,x,a...) G_STMT_START { \
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_##type)) { \
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_##type))) { \
_cogl_profile_trace_message ("[" #type "] " G_STRLOC " & " x, ##a); \
} } G_STMT_END
#else
#define COGL_NOTE(type,...) G_STMT_START { \
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_##type)) { \
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_##type)) { \
char *_fmt = g_strdup_printf (__VA_ARGS__); \
_cogl_profile_trace_message ("[" #type "] " G_STRLOC " & %s", _fmt);\
g_free (_fmt); \
#define COGL_NOTE(type,...) G_STMT_START {} G_STMT_END
-#endif /* COGL_ENABLE_DEBUG */
+#define COGL_DEBUG_ENABLED(flag) FALSE
+
+#define COGL_DEBUG_SET_FLAG(flag) \
+ G_STMT_START { } G_STMT_END
-extern unsigned int cogl_debug_flags;
+#define COGL_DEBUG_CLEAR_FLAG(flag) \
+ G_STMT_START { } G_STMT_END
+
+#endif /* COGL_ENABLE_DEBUG */
G_END_DECLS
#include "cogl-handle.h"
#include "cogl-matrix-stack.h"
#include "cogl-clip-state.h"
+#include "cogl-journal-private.h"
typedef enum _CoglFramebufferType {
COGL_FRAMEBUFFER_TYPE_ONSCREEN,
int blue_bits;
int green_bits;
int alpha_bits;
+
+ /* We journal the textured rectangles we want to submit to OpenGL so
+ * we have an oppertunity to batch them together into less draw
+ * calls. */
+ CoglJournal *journal;
+
+ /* The scene of a given framebuffer may depend on images in other
+ * framebuffers... */
+ GList *deps;
+
+ /* As part of an optimization for reading-back single pixels from a
+ * framebuffer in some simple cases where the geometry is still
+ * available in the journal we need to track the bounds of the last
+ * region cleared, its color and we need to track when something
+ * does in fact draw to that region so it is no longer clear.
+ */
+ float clear_color_red;
+ float clear_color_green;
+ float clear_color_blue;
+ float clear_color_alpha;
+ int clear_clip_x0;
+ int clear_clip_y0;
+ int clear_clip_x1;
+ int clear_clip_y1;
+ gboolean clear_clip_dirty;
};
#define COGL_FRAMEBUFFER(X) ((CoglFramebuffer *)(X))
void
_cogl_framebuffer_state_init (void);
+void
+_cogl_clear4f (unsigned long buffers,
+ float red,
+ float green,
+ float blue,
+ float alpha);
+
+void
+_cogl_framebuffer_clear (CoglFramebuffer *framebuffer,
+ unsigned long buffers,
+ const CoglColor *color);
+
+void
+_cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
+ unsigned long buffers,
+ float red,
+ float green,
+ float blue,
+ float alpha);
+
+void
+_cogl_framebuffer_dirty (CoglFramebuffer *framebuffer);
+
int
_cogl_framebuffer_get_width (CoglFramebuffer *framebuffer);
CoglClipState *
_cogl_framebuffer_get_clip_state (CoglFramebuffer *framebuffer);
+/*
+ * _cogl_framebuffer_get_clip_stack:
+ * @framebuffer: A #CoglFramebuffer
+ *
+ * Gets a pointer to the current clip stack. This can be used to later
+ * return to the same clip stack state with
+ * _cogl_framebuffer_set_clip_stack(). A reference is not taken on the
+ * stack so if you want to keep it you should call
+ * _cogl_clip_stack_ref().
+ *
+ * Return value: a pointer to the @framebuffer clip stack.
+ */
+CoglClipStack *
+_cogl_framebuffer_get_clip_stack (CoglFramebuffer *framebuffer);
+
+/*
+ * _cogl_framebuffer_set_clip_stack:
+ * @framebuffer: A #CoglFramebuffer
+ * @stack: a pointer to the replacement clip stack
+ *
+ * Replaces the @framebuffer clip stack with @stack.
+ */
+void
+_cogl_framebuffer_set_clip_stack (CoglFramebuffer *framebuffer,
+ CoglClipStack *stack);
+
void
_cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
int x,
CoglMatrixStack *
_cogl_framebuffer_get_projection_stack (CoglFramebuffer *framebuffer);
+void
+_cogl_framebuffer_add_dependency (CoglFramebuffer *framebuffer,
+ CoglFramebuffer *dependency);
+
+void
+_cogl_framebuffer_remove_all_dependencies (CoglFramebuffer *framebuffer);
+
+void
+_cogl_framebuffer_flush_journal (CoglFramebuffer *framebuffer);
+
+void
+_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer);
+
+void
+_cogl_framebuffer_swap_notify (CoglFramebuffer *framebuffer);
+
+gboolean
+_cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
+ int x,
+ int y,
+ CoglReadPixelsFlags source,
+ CoglPixelFormat format,
+ guint8 *pixel);
+
typedef enum _CoglFramebufferFlushFlags
{
/* XXX: When using this, that imples you are going to manually load the
int width,
int height)
{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
framebuffer->type = type;
framebuffer->width = width;
framebuffer->height = height;
/* Initialise the clip stack */
_cogl_clip_state_init (&framebuffer->clip_state);
+
+ framebuffer->journal = _cogl_journal_new ();
+
+ /* Ensure we know the framebuffer->clear_color* members can't be
+ * referenced for our fast-path read-pixel optimization (see
+ * _cogl_journal_try_read_pixel()) until some region of the
+ * framebuffer is initialized.
+ */
+ framebuffer->clear_clip_dirty = TRUE;
+
+ /* XXX: We have to maintain a central list of all framebuffers
+ * because at times we need to be able to flush all known journals.
+ *
+ * Examples where we need to flush all journals are:
+ * - because journal entries can reference OpenGL texture
+ * coordinates that may not survive texture-atlas reorganization
+ * so we need the ability to flush those entries.
+ * - because although we generally advise against modifying
+ * pipelines after construction we have to handle that possibility
+ * and since pipelines may be referenced in journal entries we
+ * need to be able to flush them before allowing the pipelines to
+ * be changed.
+ *
+ * Note we don't maintain a list of journals and associate
+ * framebuffers with journals by e.g. having a journal->framebuffer
+ * reference since that would introduce a circular reference.
+ *
+ * Note: As a future change to try and remove the need to index all
+ * journals it might be possible to defer resolving of OpenGL
+ * texture coordinates for rectangle primitives until we come to
+ * flush a journal. This would mean for instance that a single
+ * rectangle entry in a journal could later be expanded into
+ * multiple quad primitives to handle sliced textures but would mean
+ * we don't have to worry about retaining references to OpenGL
+ * texture coordinates that may later become invalid.
+ */
+ ctx->framebuffers = g_list_prepend (ctx->framebuffers, framebuffer);
}
void
_cogl_framebuffer_free (CoglFramebuffer *framebuffer)
{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ ctx->framebuffers = g_list_remove (ctx->framebuffers, framebuffer);
+
_cogl_clip_state_destroy (&framebuffer->clip_state);
cogl_object_unref (framebuffer->modelview_stack);
cogl_object_unref (framebuffer->projection_stack);
framebuffer->projection_stack = NULL;
+
+ cogl_object_unref (framebuffer->journal);
+}
+
+/* This version of cogl_clear can be used internally as an alternative
+ * to avoid flushing the journal or the framebuffer state. This is
+ * needed when doing operations that may be called whiling flushing
+ * the journal */
+void
+_cogl_clear4f (unsigned long buffers,
+ float red,
+ float green,
+ float blue,
+ float alpha)
+{
+ GLbitfield gl_buffers = 0;
+
+ if (buffers & COGL_BUFFER_BIT_COLOR)
+ {
+ GE( glClearColor (red, green, blue, alpha) );
+ gl_buffers |= GL_COLOR_BUFFER_BIT;
+ }
+
+ if (buffers & COGL_BUFFER_BIT_DEPTH)
+ gl_buffers |= GL_DEPTH_BUFFER_BIT;
+
+ if (buffers & COGL_BUFFER_BIT_STENCIL)
+ gl_buffers |= GL_STENCIL_BUFFER_BIT;
+
+ if (!gl_buffers)
+ {
+ static gboolean shown = FALSE;
+
+ if (!shown)
+ {
+ g_warning ("You should specify at least one auxiliary buffer "
+ "when calling cogl_clear");
+ }
+
+ return;
+ }
+
+ GE (glClear (gl_buffers));
+}
+
+void
+_cogl_framebuffer_dirty (CoglFramebuffer *framebuffer)
+{
+ framebuffer->clear_clip_dirty = TRUE;
+}
+
+void
+_cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
+ unsigned long buffers,
+ float red,
+ float green,
+ float blue,
+ float alpha)
+{
+ CoglClipStack *clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer);
+ int scissor_x0;
+ int scissor_y0;
+ int scissor_x1;
+ int scissor_y1;
+
+ _cogl_clip_stack_get_bounds (clip_stack,
+ &scissor_x0, &scissor_y0,
+ &scissor_x1, &scissor_y1);
+
+ /* NB: the previous clear could have had an arbitrary clip.
+ * NB: everything for the last frame might still be in the journal
+ * but we can't assume anything about how each entry was
+ * clipped.
+ * NB: Clutter will scissor its pick renders which would mean all
+ * journal entries have a common ClipStack entry, but without
+ * a layering violation Cogl has to explicitly walk the journal
+ * entries to determine if this is the case.
+ * NB: We have a software only read-pixel optimization in the
+ * journal that determines the color at a given framebuffer
+ * coordinate for simple scenes without rendering with the GPU.
+ * When Clutter is hitting this fast-path we can expect to
+ * receive calls to clear the framebuffer with an un-flushed
+ * journal.
+ * NB: To fully support software based picking for Clutter we
+ * need to be able to reliably detect when the contents of a
+ * journal can be discarded and when we can skip the call to
+ * glClear because it matches the previous clear request.
+ */
+
+ /* Note: we don't check for the stencil buffer being cleared here
+ * since there isn't any public cogl api to manipulate the stencil
+ * buffer.
+ *
+ * Note: we check for an exact clip match here because
+ * 1) a smaller clip could mean existing journal entries may
+ * need to contribute to regions outside the new clear-clip
+ * 2) a larger clip would mean we need to issue a real
+ * glClear and we only care about cases avoiding a
+ * glClear.
+ *
+ * Note: Comparing without an epsilon is considered
+ * appropriate here.
+ */
+ if (buffers & COGL_BUFFER_BIT_COLOR &&
+ buffers & COGL_BUFFER_BIT_DEPTH &&
+ !framebuffer->clear_clip_dirty &&
+ framebuffer->clear_color_red == red &&
+ framebuffer->clear_color_green == green &&
+ framebuffer->clear_color_blue == blue &&
+ framebuffer->clear_color_alpha == alpha &&
+ scissor_x0 == framebuffer->clear_clip_x0 &&
+ scissor_y0 == framebuffer->clear_clip_y0 &&
+ scissor_x1 == framebuffer->clear_clip_x1 &&
+ scissor_y1 == framebuffer->clear_clip_y1)
+ {
+ /* NB: We only have to consider the clip state of journal
+ * entries if the current clear is clipped since otherwise we
+ * know every pixel of the framebuffer is affected by the clear
+ * and so all journal entries become redundant and can simply be
+ * discarded.
+ */
+ if (clip_stack)
+ {
+ /*
+ * Note: the function for checking the journal entries is
+ * quite strict. It avoids detailed checking of all entry
+ * clip_stacks by only checking the details of the first
+ * entry and then it only verifies that the remaining
+ * entries share the same clip_stack ancestry. This means
+ * it's possible for some false negatives here but that will
+ * just result in us falling back to a real clear.
+ */
+ if (_cogl_journal_all_entries_within_bounds (framebuffer->journal,
+ scissor_x0, scissor_y0,
+ scissor_x1, scissor_y1))
+ {
+ _cogl_journal_discard (framebuffer->journal);
+ goto cleared;
+ }
+ }
+ else
+ {
+ _cogl_journal_discard (framebuffer->journal);
+ goto cleared;
+ }
+ }
+
+ COGL_NOTE (DRAW, "Clear begin");
+
+ _cogl_framebuffer_flush_journal (framebuffer);
+
+ /* NB: _cogl_framebuffer_flush_state may disrupt various state (such
+ * as the pipeline state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_framebuffer_flush_state (framebuffer, 0);
+
+ _cogl_clear4f (buffers, red, green, blue, alpha);;
+
+ /* 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_ENABLED (COGL_DEBUG_RECTANGLES)) &&
+ buffers & COGL_BUFFER_BIT_COLOR)
+ {
+ _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
+ ctxt->journal_rectangles_color = 1;
+ }
+
+ COGL_NOTE (DRAW, "Clear end");
+
+cleared:
+
+ if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH)
+ {
+ /* For our fast-path for reading back a single pixel of simple
+ * scenes where the whole frame is in the journal we need to
+ * track the cleared color of the framebuffer in case the point
+ * read doesn't intersect any of the journal rectangles. */
+ framebuffer->clear_clip_dirty = FALSE;
+ framebuffer->clear_color_red = red;
+ framebuffer->clear_color_green = green;
+ framebuffer->clear_color_blue = blue;
+ framebuffer->clear_color_alpha = alpha;
+
+ /* NB: A clear may be scissored so we need to track the extents
+ * that the clear is applicable too... */
+ if (clip_stack)
+ {
+ _cogl_clip_stack_get_bounds (clip_stack,
+ &framebuffer->clear_clip_x0,
+ &framebuffer->clear_clip_y0,
+ &framebuffer->clear_clip_x1,
+ &framebuffer->clear_clip_y1);
+ }
+ else
+ {
+ /* FIXME: set degenerate clip */
+ }
+ }
+ else
+ _cogl_framebuffer_dirty (framebuffer);
+}
+
+/* XXX: We'll need to consider if this API is a good approach for the
+ * planned, public, CoglFramebuffer API. A framebuffer may have
+ * multiple color buffers associated with it and the user may want to
+ * only clear a subset of those buffers. Flags aren't a great
+ * mechanism for handling this, but I don't think it would be very
+ * convenient if you had to explicitly enumerate the individual
+ * ancillary buffers to clear them.
+ *
+ * My current expectation is that we'll keep this flag based API but
+ * also add a way to enumerate the individual color buffers for
+ * clearing individually.
+ *
+ * Note: the 'buffers' and 'color' arguments were switched around on
+ * purpose compared to the original cogl_clear API since it was odd
+ * that you would be expected to specify a color before even
+ * necessarily choosing to clear the color buffer.
+ */
+void
+_cogl_framebuffer_clear (CoglFramebuffer *framebuffer,
+ unsigned long buffers,
+ const CoglColor *color)
+{
+ _cogl_framebuffer_clear4f (framebuffer, buffers,
+ cogl_color_get_red_float (color),
+ cogl_color_get_green_float (color),
+ cogl_color_get_blue_float (color),
+ cogl_color_get_alpha_float (color));
+}
+
+void
+_cogl_framebuffer_swap_notify (CoglFramebuffer *framebuffer)
+{
}
int
return &framebuffer->clip_state;
}
+CoglClipStack *
+_cogl_framebuffer_get_clip_stack (CoglFramebuffer *framebuffer)
+{
+ CoglClipState *clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
+
+ return _cogl_clip_state_get_stack (clip_state);
+}
+
+void
+_cogl_framebuffer_set_clip_stack (CoglFramebuffer *framebuffer,
+ CoglClipStack *stack)
+{
+ CoglClipState *clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
+
+ _cogl_clip_state_set_stack (clip_state, stack);
+}
+
void
_cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
int x,
framebuffer->viewport_height == height)
return;
- _cogl_journal_flush ();
+ _cogl_framebuffer_flush_journal (framebuffer);
framebuffer->viewport_x = x;
framebuffer->viewport_y = y;
return framebuffer->projection_stack;
}
+void
+_cogl_framebuffer_add_dependency (CoglFramebuffer *framebuffer,
+ CoglFramebuffer *dependency)
+{
+ GList *l;
+
+ for (l = framebuffer->deps; l; l = l->next)
+ {
+ CoglFramebuffer *existing_dep = l->data;
+ if (existing_dep == dependency)
+ return;
+ }
+
+ /* TODO: generalize the primed-array type structure we e.g. use for
+ * cogl_object_set_user_data or for pipeline children as a way to
+ * avoid quite a lot of mid-scene micro allocations here... */
+ framebuffer->deps =
+ g_list_prepend (framebuffer->deps, cogl_object_ref (dependency));
+}
+
+void
+_cogl_framebuffer_remove_all_dependencies (CoglFramebuffer *framebuffer)
+{
+ GList *l;
+ for (l = framebuffer->deps; l; l = l->next)
+ cogl_object_unref (l->data);
+ g_list_free (framebuffer->deps);
+ framebuffer->deps = NULL;
+}
+
+void
+_cogl_framebuffer_flush_journal (CoglFramebuffer *framebuffer)
+{
+ _cogl_journal_flush (framebuffer->journal, framebuffer);
+}
+
+void
+_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer)
+{
+ GList *l;
+ for (l = framebuffer->deps; l; l = l->next)
+ _cogl_framebuffer_flush_journal (l->data);
+ _cogl_framebuffer_remove_all_dependencies (framebuffer);
+}
+
static inline void
_cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
{
)
return FALSE;
- /* We are about to generate and bind a new fbo, so we pretend to change framebuffer
- * state so that the old framebuffer will be rebound again before drawing.
- * The framebuffer state can't be changed while their are active entries, so flush
- * first. */
- _cogl_journal_flush ();
+ /* We are about to generate and bind a new fbo, so we pretend to
+ * change framebuffer state so that the old framebuffer will be
+ * rebound again before drawing. */
ctx->dirty_bound_framebuffer = 1;
/* Generate framebuffer */
if (fbo_created)
{
+ CoglOffscreen *ret;
+
_cogl_framebuffer_init (COGL_FRAMEBUFFER (offscreen),
COGL_FRAMEBUFFER_TYPE_OFFSCREEN,
cogl_texture_get_format (texhandle),
data.level_width,
data.level_height);
- return _cogl_offscreen_object_new (offscreen);
+ ret = _cogl_offscreen_object_new (offscreen);
+ _cogl_texture_associate_framebuffer (texhandle, COGL_FRAMEBUFFER (ret));
+ return ret;
}
else
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_flush ();
-
entry = (CoglFramebuffer **)&ctx->framebuffer_stack->data;
ctx->dirty_bound_framebuffer = 1;
ctx->dirty_gl_viewport = 1;
- if (framebuffer != COGL_INVALID_HANDLE)
+ if (framebuffer)
cogl_object_ref (framebuffer);
- if (*entry != COGL_INVALID_HANDLE)
+ if (*entry)
cogl_object_unref (*entry);
*entry = framebuffer;
void
cogl_set_framebuffer (CoglFramebuffer *framebuffer)
{
+ CoglFramebuffer *current;
+
g_return_if_fail (_cogl_is_framebuffer (framebuffer));
- if (_cogl_get_framebuffer () != framebuffer)
- _cogl_set_framebuffer_real (framebuffer);
+ current = _cogl_get_framebuffer ();
+ if (current != framebuffer)
+ {
+ /* XXX: eventually we want to remove this implicit journal flush
+ * so we can log into the journal beyond framebuffer changes to
+ * support batching scenes that depend on the results of
+ * mid-scene renders to textures. Current will be NULL when the
+ * framebuffer stack is first created so we need to guard
+ * against that here */
+ if (current)
+ _cogl_framebuffer_flush_journal (current);
+ _cogl_set_framebuffer_real (framebuffer);
+ }
}
/* XXX: deprecated API */
g_return_if_fail (_cogl_is_framebuffer (buffer));
g_assert (ctx->framebuffer_stack);
- cogl_flush ();
-
+ /* Copy the top of the stack so that when we call cogl_set_framebuffer
+ it will still know what the old framebuffer was */
ctx->framebuffer_stack =
- g_slist_prepend (ctx->framebuffer_stack, COGL_INVALID_HANDLE);
+ g_slist_prepend (ctx->framebuffer_stack,
+ cogl_object_ref (_cogl_get_framebuffer ()));
cogl_set_framebuffer (buffer);
}
to_pop = ctx->framebuffer_stack->data;
to_restore = ctx->framebuffer_stack->next->data;
- cogl_flush ();
+ if (to_pop != to_restore)
+ {
+ /* XXX: eventually we want to remove this implicit journal flush
+ * so we can log into the journal beyond framebuffer changes to
+ * support batching scenes that depend on the results of
+ * mid-scene renders to textures. */
+ _cogl_framebuffer_flush_journal (to_pop);
+ }
cogl_object_unref (to_pop);
ctx->framebuffer_stack =
return framebuffer->alpha_bits;
}
+gboolean
+_cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
+ int x,
+ int y,
+ CoglReadPixelsFlags source,
+ CoglPixelFormat format,
+ guint8 *pixel)
+{
+ gboolean found_intersection;
+
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FAST_READ_PIXEL)))
+ return FALSE;
+
+ if (source != COGL_READ_PIXELS_COLOR_BUFFER)
+ return FALSE;
+
+ if (format != COGL_PIXEL_FORMAT_RGBA_8888_PRE &&
+ format != COGL_PIXEL_FORMAT_RGBA_8888)
+ return FALSE;
+
+ if (!_cogl_journal_try_read_pixel (framebuffer->journal,
+ x, y, format, pixel,
+ &found_intersection))
+ return FALSE;
+
+ /* If we can't determine the color from the primitives in the
+ * journal then see if we can use the last recorded clear color
+ */
+
+ /* If _cogl_journal_try_read_pixel() failed even though there was an
+ * intersection of the given point with a primitive in the journal
+ * then we can't fallback to the framebuffer's last clear color...
+ * */
+ if (found_intersection)
+ return TRUE;
+
+ /* If the framebuffer has been rendered too since it was last
+ * cleared then we can't return the last known clear color. */
+ if (framebuffer->clear_clip_dirty)
+ return FALSE;
+
+ if (x >= framebuffer->clear_clip_x0 &&
+ x < framebuffer->clear_clip_x1 &&
+ y >= framebuffer->clear_clip_y0 &&
+ y < framebuffer->clear_clip_y1)
+ {
+
+ /* we currently only care about cases where the premultiplied or
+ * unpremultipled colors are equivalent... */
+ if (framebuffer->clear_color_alpha != 1.0)
+ return FALSE;
+
+ pixel[0] = framebuffer->clear_color_red * 255.0;
+ pixel[1] = framebuffer->clear_color_green * 255.0;
+ pixel[2] = framebuffer->clear_color_blue * 255.0;
+ pixel[3] = framebuffer->clear_color_alpha * 255.0;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
* data.
*
* XXX: I think in the end it'll be that CoglIndices are to
- * CoglIndexArrays as CoglVertexAttributes are to CoglVertices. I.e
+ * CoglIndexArrays as CoglAttributes are to CoglVertices. I.e
* a CoglIndexArray is a lite subclass of CoglBuffer that simply
* implies that the buffer will later be bound as indices but doesn't
* track more detailed meta data. CoglIndices build on a
*
* XXX: The double plurel form that "Indices" "Array" implies could be
* a bit confusing. Also to be a bit more consistent with
- * CoglVertexArray vs CoglVertexAttribute it might be best to rename so
+ * CoglVertexArray vs CoglAttribute it might be best to rename so
* we have CoglIndexArray vs CoglIndices? maybe even
* CoglIndexRange :-/ ?
*
#include "cogl-handle.h"
#include "cogl-clip-stack.h"
+typedef struct _CoglJournal
+{
+ CoglObject _parent;
+
+ GArray *entries;
+ GArray *vertices;
+ size_t needed_vbo_len;
+
+ int fast_read_pixel_count;
+
+} CoglJournal;
+
/* To improve batching of geometry when submitting vertices to OpenGL we
* log the texture rectangles we want to draw to a journal, so when we
* later flush the journal we aim to batch data, and gl draw calls. */
* later. */
} CoglJournalEntry;
+CoglJournal *
+_cogl_journal_new (void);
+
void
-_cogl_journal_log_quad (const float *position,
+_cogl_journal_log_quad (CoglJournal *journal,
+ const float *position,
CoglPipeline *pipeline,
int n_layers,
CoglHandle layer0_override_texture,
unsigned int tex_coords_len);
void
-_cogl_journal_flush (void);
+_cogl_journal_flush (CoglJournal *journal,
+ CoglFramebuffer *framebuffer);
+
+void
+_cogl_journal_discard (CoglJournal *journal);
+
+gboolean
+_cogl_journal_all_entries_within_bounds (CoglJournal *journal,
+ float clip_x0,
+ float clip_y0,
+ float clip_x1,
+ float clip_y1);
+
+gboolean
+_cogl_journal_try_read_pixel (CoglJournal *journal,
+ int x,
+ int y,
+ CoglPixelFormat format,
+ guint8 *pixel,
+ gboolean *found_intersection);
#endif /* __COGL_JOURNAL_PRIVATE_H */
#include "cogl-vertex-buffer-private.h"
#include "cogl-framebuffer-private.h"
#include "cogl-profile.h"
-#include "cogl-vertex-attribute-private.h"
+#include "cogl-attribute-private.h"
+#include "cogl-point-in-poly-private.h"
#include <string.h>
#include <gmodule.h>
*
* So for a given number of layers this gets the stride in 32bit words:
*/
-#define SW_TRANSFORM (!(cogl_debug_flags & \
- COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
+#define SW_TRANSFORM (!(COGL_DEBUG_ENABLED \
+ (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
#define POS_STRIDE (SW_TRANSFORM ? 3 : 2) /* number of 32bit words */
#define N_POS_COMPONENTS POS_STRIDE
#define COLOR_STRIDE 1 /* number of 32bit words */
typedef struct _CoglJournalFlushState
{
+ CoglJournal *journal;
+
CoglVertexArray *vertex_array;
GArray *attributes;
int current_attribute;
typedef gboolean (*CoglJournalBatchTest) (CoglJournalEntry *entry0,
CoglJournalEntry *entry1);
+static void _cogl_journal_free (CoglJournal *journal);
+
+COGL_OBJECT_DEFINE (Journal, journal);
+
+static void
+_cogl_journal_free (CoglJournal *journal)
+{
+ if (journal->entries)
+ g_array_free (journal->entries, TRUE);
+ if (journal->vertices)
+ g_array_free (journal->vertices, TRUE);
+ g_slice_free (CoglJournal, journal);
+}
+
+CoglJournal *
+_cogl_journal_new (void)
+{
+ CoglJournal *journal = g_slice_new0 (CoglJournal);
+
+ journal->entries = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
+ journal->vertices = g_array_new (FALSE, FALSE, sizeof (float));
+
+ return _cogl_journal_object_new (journal);
+}
+
static void
_cogl_journal_dump_logged_quad (guint8 *data, int n_layers)
{
guint8 *c = data + (POS_STRIDE * 4) + (i * stride * 4);
int j;
- if (G_UNLIKELY (cogl_debug_flags &
- COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED
+ (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
g_print ("v%d: x = %f, y = %f, rgba=0x%02X%02X%02X%02X",
i, v[0], v[1], c[0], c[1], c[2], c[3]);
else
void *data)
{
CoglJournalFlushState *state = data;
- CoglVertexAttribute **attributes;
+ CoglAttribute **attributes;
+ CoglDrawFlags draw_flags = (COGL_DRAW_SKIP_JOURNAL_FLUSH |
+ COGL_DRAW_SKIP_PIPELINE_VALIDATION |
+ COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH |
+ COGL_DRAW_SKIP_LEGACY_STATE);
+
COGL_STATIC_TIMER (time_flush_modelview_and_entries,
"flush: pipeline+entries", /* parent */
"flush: modelview+entries",
COGL_TIMER_START (_cogl_uprof_context, time_flush_modelview_and_entries);
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_BATCHING))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
g_print ("BATCHING: modelview batch len = %d\n", batch_len);
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
{
_cogl_matrix_stack_set (state->modelview_stack,
&batch_start->model_view);
COGL_MATRIX_MODELVIEW);
}
- attributes = (CoglVertexAttribute **)state->attributes->data;
+ attributes = (CoglAttribute **)state->attributes->data;
cogl_push_source (state->source);
+ if (!_cogl_pipeline_get_real_blend_enabled (state->source))
+ draw_flags |= COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE;
+
#ifdef HAVE_COGL_GL
/* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */
- _cogl_draw_vertex_attributes_array (GL_QUADS,
- state->current_vertex, batch_len * 4,
- attributes);
+ _cogl_draw_attributes_array (GL_QUADS,
+ state->current_vertex, batch_len * 4,
+ attributes,
+ draw_flags);
#else /* HAVE_COGL_GL */
if (batch_len > 1)
{
- _cogl_draw_indexed_vertex_attributes_array (COGL_VERTICES_MODE_TRIANGLES,
- state->current_vertex * 6 / 4,
- batch_len * 6,
- state->indices,
- attributes);
+ _cogl_draw_indexed_attributes_array (COGL_VERTICES_MODE_TRIANGLES,
+ state->current_vertex * 6 / 4,
+ batch_len * 6,
+ state->indices,
+ attributes,
+ draw_flags);
+
}
else
{
- _cogl_draw_vertex_attributes_array (COGL_VERTICES_MODE_TRIANGLE_FAN,
- state->current_vertex, 4,
- attributes);
+ _cogl_draw_attributes_array (COGL_VERTICES_MODE_TRIANGLE_FAN,
+ state->current_vertex, 4,
+ attributes,
+ draw_flags);
}
#endif
* issues, visually seeing what is batched and debugging blending
* issues, plus it looks quite cool.
*/
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_RECTANGLES))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_RECTANGLES)))
{
static CoglPipeline *outline = NULL;
guint8 color_intensity;
int i;
- CoglVertexAttribute *loop_attributes[2];
+ CoglAttribute *loop_attributes[2];
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
loop_attributes[0] = attributes[0]; /* we just want the position */
loop_attributes[1] = NULL;
for (i = 0; i < batch_len; i++)
- _cogl_draw_vertex_attributes_array (COGL_VERTICES_MODE_LINE_LOOP,
- 4 * i + state->current_vertex, 4,
- loop_attributes);
+ _cogl_draw_attributes_array (COGL_VERTICES_MODE_LINE_LOOP,
+ 4 * i + state->current_vertex, 4,
+ loop_attributes,
+ draw_flags);
/* Go to the next color */
do
COGL_TIMER_START (_cogl_uprof_context, time_flush_pipeline_entries);
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_BATCHING))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
g_print ("BATCHING: pipeline batch len = %d\n", batch_len);
state->source = batch_start->pipeline;
/* If we haven't transformed the quads in software then we need to also break
* up batches according to changes in the modelview matrix... */
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
{
batch_and_call (batch_start,
batch_len,
/* NB: attributes 0 and 1 are position and color */
for (i = 2; i < state->attributes->len; i++)
- cogl_object_unref (g_array_index (state->attributes,
- CoglVertexAttribute *, i));
+ cogl_object_unref (g_array_index (state->attributes, CoglAttribute *, i));
g_array_set_size (state->attributes, batch_start->n_layers + 2);
for (i = 0; i < batch_start->n_layers; i++)
{
- CoglVertexAttribute **attribute_entry =
- &g_array_index (state->attributes, CoglVertexAttribute *, i + 2);
+ CoglAttribute **attribute_entry =
+ &g_array_index (state->attributes, CoglAttribute *, i + 2);
const char *names[] = {
"cogl_tex_coord0_in",
"cogl_tex_coord1_in",
/* XXX: it may be worth having some form of static initializer for
* attributes... */
*attribute_entry =
- cogl_vertex_attribute_new (state->vertex_array,
- name,
- state->stride,
- state->array_offset +
- (POS_STRIDE + COLOR_STRIDE) * 4 +
- TEX_STRIDE * 4 * i,
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ cogl_attribute_new (state->vertex_array,
+ name,
+ state->stride,
+ state->array_offset +
+ (POS_STRIDE + COLOR_STRIDE) * 4 +
+ TEX_STRIDE * 4 * i,
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
if (i >= 8)
g_free (name);
CoglJournalFlushState *state = data;
gsize stride;
int i;
- CoglVertexAttribute **attribute_entry;
+ CoglAttribute **attribute_entry;
COGL_STATIC_TIMER (time_flush_vbo_texcoord_pipeline_entries,
"flush: clip+vbo+texcoords+pipeline+entries", /* parent */
"flush: vbo+texcoords+pipeline+entries",
COGL_TIMER_START (_cogl_uprof_context,
time_flush_vbo_texcoord_pipeline_entries);
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_BATCHING))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
g_print ("BATCHING: vbo offset batch len = %d\n", batch_len);
/* XXX NB:
state->stride = stride;
for (i = 0; i < state->attributes->len; i++)
- cogl_object_unref (g_array_index (state->attributes,
- CoglVertexAttribute *, i));
+ cogl_object_unref (g_array_index (state->attributes, CoglAttribute *, i));
g_array_set_size (state->attributes, 2);
- attribute_entry =
- &g_array_index (state->attributes, CoglVertexAttribute *, 0);
- *attribute_entry =
- cogl_vertex_attribute_new (state->vertex_array,
- "cogl_position_in",
- stride,
- state->array_offset,
- N_POS_COMPONENTS,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
-
- attribute_entry =
- &g_array_index (state->attributes, CoglVertexAttribute *, 1);
+ attribute_entry = &g_array_index (state->attributes, CoglAttribute *, 0);
+ *attribute_entry = cogl_attribute_new (state->vertex_array,
+ "cogl_position_in",
+ stride,
+ state->array_offset,
+ N_POS_COMPONENTS,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+
+ attribute_entry = &g_array_index (state->attributes, CoglAttribute *, 1);
*attribute_entry =
- cogl_vertex_attribute_new (state->vertex_array,
- "cogl_color_in",
- stride,
- state->array_offset + (POS_STRIDE * 4),
- 4,
- COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
+ cogl_attribute_new (state->vertex_array,
+ "cogl_color_in",
+ stride,
+ state->array_offset + (POS_STRIDE * 4),
+ 4,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
#ifndef HAVE_COGL_GL
state->indices = cogl_get_rectangle_indices (batch_len);
#endif
- /* We only create new VertexAttributes when the stride within the
- * VertexArray changes. (due to a change in the number of pipeline layers)
- * While the stride remains constant we walk forward through the above
- * VertexArray using a vertex offset passed to cogl_draw_vertex_attributes
+ /* We only create new Attributes when the stride within the
+ * VertexArray changes. (due to a change in the number of pipeline
+ * layers) While the stride remains constant we walk forward through
+ * the above VertexArray using a vertex offset passed to
+ * cogl_draw_attributes
*/
state->current_vertex = 0;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_JOURNAL))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL)))
{
guint8 *verts;
/* progress forward through the VBO containing all our vertices */
state->array_offset += (stride * 4 * batch_len);
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_JOURNAL))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL)))
g_print ("new vbo offset = %lu\n", (unsigned long)state->array_offset);
COGL_TIMER_STOP (_cogl_uprof_context,
COGL_TIMER_START (_cogl_uprof_context,
time_flush_clip_stack_pipeline_entries);
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_BATCHING))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
g_print ("BATCHING: clip stack batch len = %d\n", batch_len);
_cogl_clip_stack_flush (batch_start->clip_stack);
* no further model transform is applied by loading the identity
* matrix here. We need to do this after flushing the clip stack
* because the clip stack flushing code can modify the matrix */
- if (G_LIKELY (!(cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
+ if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))))
{
_cogl_matrix_stack_load_identity (state->modelview_stack);
_cogl_matrix_stack_flush_to_gl (state->modelview_stack,
float x_2, y_2;
} ClipBounds;
+static gboolean
+can_software_clip_entry (CoglJournalEntry *journal_entry,
+ CoglJournalEntry *prev_journal_entry,
+ CoglClipStack *clip_stack,
+ ClipBounds *clip_bounds_out)
+{
+ CoglPipeline *pipeline = journal_entry->pipeline;
+ CoglClipStack *clip_entry;
+ int layer_num;
+
+ clip_bounds_out->x_1 = -G_MAXFLOAT;
+ clip_bounds_out->y_1 = -G_MAXFLOAT;
+ clip_bounds_out->x_2 = G_MAXFLOAT;
+ clip_bounds_out->y_2 = G_MAXFLOAT;
+
+ /* Check the pipeline is usable. We can short-cut here for
+ entries using the same pipeline as the previous entry */
+ if (prev_journal_entry == NULL || pipeline != prev_journal_entry->pipeline)
+ {
+ /* If the pipeline has a user program then we can't reliably modify
+ the texture coordinates */
+ if (cogl_pipeline_get_user_program (pipeline))
+ return FALSE;
+
+ /* If any of the pipeline layers have a texture matrix then we can't
+ reliably modify the texture coordinates */
+ for (layer_num = cogl_pipeline_get_n_layers (pipeline) - 1;
+ layer_num >= 0;
+ layer_num--)
+ if (_cogl_pipeline_layer_has_user_matrix (pipeline, layer_num))
+ return FALSE;
+ }
+
+ /* Now we need to verify that each clip entry's matrix is just a
+ translation of the journal entry's modelview matrix. We can
+ also work out the bounds of the clip in modelview space using
+ this translation */
+ for (clip_entry = clip_stack; clip_entry; clip_entry = clip_entry->parent)
+ {
+ float rect_x1, rect_y1, rect_x2, rect_y2;
+ CoglClipStackRect *clip_rect;
+ float tx, ty;
+
+ clip_rect = (CoglClipStackRect *) clip_entry;
+
+ if (!calculate_translation (&clip_rect->matrix,
+ &journal_entry->model_view,
+ &tx, &ty))
+ return FALSE;
+
+ if (clip_rect->x0 < clip_rect->x1)
+ {
+ rect_x1 = clip_rect->x0;
+ rect_x2 = clip_rect->x1;
+ }
+ else
+ {
+ rect_x1 = clip_rect->x1;
+ rect_x2 = clip_rect->x0;
+ }
+ if (clip_rect->y0 < clip_rect->y1)
+ {
+ rect_y1 = clip_rect->y0;
+ rect_y2 = clip_rect->y1;
+ }
+ else
+ {
+ rect_y1 = clip_rect->y1;
+ rect_y2 = clip_rect->y0;
+ }
+
+ clip_bounds_out->x_1 = MAX (clip_bounds_out->x_1, rect_x1 - tx);
+ clip_bounds_out->y_1 = MAX (clip_bounds_out->y_1, rect_y1 - ty);
+ clip_bounds_out->x_2 = MIN (clip_bounds_out->x_2, rect_x2 - tx);
+ clip_bounds_out->y_2 = MIN (clip_bounds_out->y_2, rect_y2 - ty);
+ }
+
+ return TRUE;
+}
+
+static void
+software_clip_entry (CoglJournalEntry *journal_entry,
+ float *verts,
+ ClipBounds *clip_bounds)
+{
+ size_t stride =
+ GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (journal_entry->n_layers);
+ float rx1, ry1, rx2, ry2;
+ float vx1, vy1, vx2, vy2;
+ int layer_num;
+
+ /* Remove the clip on the entry */
+ _cogl_clip_stack_unref (journal_entry->clip_stack);
+ journal_entry->clip_stack = NULL;
+
+ vx1 = verts[0];
+ vy1 = verts[1];
+ vx2 = verts[stride];
+ vy2 = verts[stride + 1];
+
+ if (vx1 < vx2)
+ {
+ rx1 = vx1;
+ rx2 = vx2;
+ }
+ else
+ {
+ rx1 = vx2;
+ rx2 = vx1;
+ }
+ if (vy1 < vy2)
+ {
+ ry1 = vy1;
+ ry2 = vy2;
+ }
+ else
+ {
+ ry1 = vy2;
+ ry2 = vy1;
+ }
+
+ rx1 = CLAMP (rx1, clip_bounds->x_1, clip_bounds->x_2);
+ ry1 = CLAMP (ry1, clip_bounds->y_1, clip_bounds->y_2);
+ rx2 = CLAMP (rx2, clip_bounds->x_1, clip_bounds->x_2);
+ ry2 = CLAMP (ry2, clip_bounds->y_1, clip_bounds->y_2);
+
+ /* Check if the rectangle intersects the clip at all */
+ if (rx1 == rx2 || ry1 == ry2)
+ /* Will set all of the vertex data to 0 in the hope that this
+ will create a degenerate rectangle and the GL driver will
+ be able to clip it quickly */
+ memset (verts, 0, sizeof (float) * stride * 2);
+ else
+ {
+ if (vx1 > vx2)
+ {
+ float t = rx1;
+ rx1 = rx2;
+ rx2 = t;
+ }
+ if (vy1 > vy2)
+ {
+ float t = ry1;
+ ry1 = ry2;
+ ry2 = t;
+ }
+
+ verts[0] = rx1;
+ verts[1] = ry1;
+ verts[stride] = rx2;
+ verts[stride + 1] = ry2;
+
+ /* Convert the rectangle coordinates to a fraction of the original
+ rectangle */
+ rx1 = (rx1 - vx1) / (vx2 - vx1);
+ ry1 = (ry1 - vy1) / (vy2 - vy1);
+ rx2 = (rx2 - vx1) / (vx2 - vx1);
+ ry2 = (ry2 - vy1) / (vy2 - vy1);
+
+ for (layer_num = 0; layer_num < journal_entry->n_layers; layer_num++)
+ {
+ float *t = verts + 2 + 2 * layer_num;
+ float tx1 = t[0], ty1 = t[1];
+ float tx2 = t[stride], ty2 = t[stride + 1];
+ t[0] = rx1 * (tx2 - tx1) + tx1;
+ t[1] = ry1 * (ty2 - ty1) + ty1;
+ t[stride] = rx2 * (tx2 - tx1) + tx1;
+ t[stride + 1] = ry2 * (ty2 - ty1) + ty1;
+ }
+ }
+}
+
static void
-check_software_clip_for_batch (CoglJournalEntry *batch_start,
- int batch_len,
- CoglJournalFlushState *state)
+maybe_software_clip_entries (CoglJournalEntry *batch_start,
+ int batch_len,
+ CoglJournalFlushState *state)
{
+ CoglJournal *journal = state->journal;
CoglClipStack *clip_stack, *clip_entry;
int entry_num;
for (entry_num = 0; entry_num < batch_len; entry_num++)
{
CoglJournalEntry *journal_entry = batch_start + entry_num;
- CoglPipeline *pipeline = journal_entry->pipeline;
+ CoglJournalEntry *prev_journal_entry =
+ entry_num ? batch_start + (entry_num - 1) : NULL;
ClipBounds *clip_bounds = &g_array_index (ctx->journal_clip_bounds,
ClipBounds, entry_num);
- int layer_num;
-
- clip_bounds->x_1 = -G_MAXFLOAT;
- clip_bounds->y_1 = -G_MAXFLOAT;
- clip_bounds->x_2 = G_MAXFLOAT;
- clip_bounds->y_2 = G_MAXFLOAT;
-
- /* Check the pipeline is usable. We can short-cut here for
- entries using the same pipeline as the previous entry */
- if (entry_num == 0 || pipeline != batch_start[entry_num - 1].pipeline)
- {
- /* If the pipeline has a user program then we can't reliably modify
- the texture coordinates */
- if (cogl_pipeline_get_user_program (pipeline))
- return;
-
- /* If any of the pipeline layers have a texture matrix then we can't
- reliably modify the texture coordinates */
- for (layer_num = cogl_pipeline_get_n_layers (pipeline) - 1;
- layer_num >= 0;
- layer_num--)
- if (_cogl_pipeline_layer_has_user_matrix (pipeline, layer_num))
- return;
- }
-
- /* Now we need to verify that each clip entry's matrix is just a
- translation of the journal entry's modelview matrix. We can
- also work out the bounds of the clip in modelview space using
- this translation */
- for (clip_entry = clip_stack; clip_entry; clip_entry = clip_entry->parent)
- {
- float rect_x1, rect_y1, rect_x2, rect_y2;
- CoglClipStackRect *clip_rect;
- float tx, ty;
-
- clip_rect = (CoglClipStackRect *) clip_entry;
- if (!calculate_translation (&clip_rect->matrix,
- &journal_entry->model_view,
- &tx, &ty))
- return;
-
- if (clip_rect->x0 < clip_rect->x1)
- {
- rect_x1 = clip_rect->x0;
- rect_x2 = clip_rect->x1;
- }
- else
- {
- rect_x1 = clip_rect->x1;
- rect_x2 = clip_rect->x0;
- }
- if (clip_rect->y0 < clip_rect->y1)
- {
- rect_y1 = clip_rect->y0;
- rect_y2 = clip_rect->y1;
- }
- else
- {
- rect_y1 = clip_rect->y1;
- rect_y2 = clip_rect->y0;
- }
-
- clip_bounds->x_1 = MAX (clip_bounds->x_1, rect_x1 - tx);
- clip_bounds->y_1 = MAX (clip_bounds->y_1, rect_y1 - ty);
- clip_bounds->x_2 = MIN (clip_bounds->x_2, rect_x2 - tx);
- clip_bounds->y_2 = MIN (clip_bounds->y_2, rect_y2 - ty);
- }
+ if (!can_software_clip_entry (journal_entry, prev_journal_entry,
+ clip_stack,
+ clip_bounds))
+ return;
}
/* If we make it here then we know we can software clip the entire batch */
+ COGL_NOTE (CLIPPING, "Software clipping a batch of length %i", batch_len);
+
for (entry_num = 0; entry_num < batch_len; entry_num++)
{
CoglJournalEntry *journal_entry = batch_start + entry_num;
- float *verts = &g_array_index (ctx->logged_vertices, float,
+ float *verts = &g_array_index (journal->vertices, float,
journal_entry->array_offset + 1);
ClipBounds *clip_bounds = &g_array_index (ctx->journal_clip_bounds,
ClipBounds, entry_num);
- size_t stride =
- GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (journal_entry->n_layers);
- float rx1, ry1, rx2, ry2;
- float vx1, vy1, vx2, vy2;
- int layer_num;
-
- /* Remove the clip on the entry */
- _cogl_clip_stack_unref (journal_entry->clip_stack);
- journal_entry->clip_stack = NULL;
-
- vx1 = verts[0];
- vy1 = verts[1];
- vx2 = verts[stride];
- vy2 = verts[stride + 1];
-
- if (vx1 < vx2)
- {
- rx1 = vx1;
- rx2 = vx2;
- }
- else
- {
- rx1 = vx2;
- rx2 = vx1;
- }
- if (vy1 < vy2)
- {
- ry1 = vy1;
- ry2 = vy2;
- }
- else
- {
- ry1 = vy2;
- ry2 = vy1;
- }
-
- rx1 = CLAMP (rx1, clip_bounds->x_1, clip_bounds->x_2);
- ry1 = CLAMP (ry1, clip_bounds->y_1, clip_bounds->y_2);
- rx2 = CLAMP (rx2, clip_bounds->x_1, clip_bounds->x_2);
- ry2 = CLAMP (ry2, clip_bounds->y_1, clip_bounds->y_2);
-
- /* Check if the rectangle intersects the clip at all */
- if (rx1 == rx2 || ry1 == ry2)
- /* Will set all of the vertex data to 0 in the hope that this
- will create a degenerate rectangle and the GL driver will
- be able to clip it quickly */
- memset (verts, 0, sizeof (float) * stride * 2);
- else
- {
- if (vx1 > vx2)
- {
- float t = rx1;
- rx1 = rx2;
- rx2 = t;
- }
- if (vy1 > vy2)
- {
- float t = ry1;
- ry1 = ry2;
- ry2 = t;
- }
-
- verts[0] = rx1;
- verts[1] = ry1;
- verts[stride] = rx2;
- verts[stride + 1] = ry2;
-
- /* Convert the rectangle coordinates to a fraction of the original
- rectangle */
- rx1 = (rx1 - vx1) / (vx2 - vx1);
- ry1 = (ry1 - vy1) / (vy2 - vy1);
- rx2 = (rx2 - vx1) / (vx2 - vx1);
- ry2 = (ry2 - vy1) / (vy2 - vy1);
-
- for (layer_num = 0; layer_num < journal_entry->n_layers; layer_num++)
- {
- float *t = verts + 2 + 2 * layer_num;
- float tx1 = t[0], ty1 = t[1];
- float tx2 = t[stride], ty2 = t[stride + 1];
- t[0] = rx1 * (tx2 - tx1) + tx1;
- t[1] = ry1 * (ty2 - ty1) + ty1;
- t[stride] = rx2 * (tx2 - tx1) + tx1;
- t[stride + 1] = ry2 * (ty2 - ty1) + ty1;
- }
- }
+ software_clip_entry (journal_entry, verts, clip_bounds);
}
return;
}
static void
-_cogl_journal_check_software_clip (CoglJournalEntry *batch_start,
- int batch_len,
- void *data)
+_cogl_journal_maybe_software_clip_entries (CoglJournalEntry *batch_start,
+ int batch_len,
+ void *data)
{
CoglJournalFlushState *state = data;
COGL_STATIC_TIMER (time_check_software_clip,
"Journal Flush", /* parent */
- "flush: check software clip",
- "Time spent checking for software clip",
+ "flush: software clipping",
+ "Time spent software clipping",
0 /* no application private data */);
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
COGL_TIMER_START (_cogl_uprof_context,
time_check_software_clip);
- check_software_clip_for_batch (batch_start, batch_len, state);
+ maybe_software_clip_entries (batch_start, batch_len, state);
COGL_TIMER_STOP (_cogl_uprof_context,
time_check_software_clip);
buffer = COGL_BUFFER (array);
cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_STATIC);
- vout = cogl_buffer_map (buffer, COGL_BUFFER_ACCESS_WRITE,
- COGL_BUFFER_MAP_HINT_DISCARD);
+ vout = _cogl_buffer_map_for_fill_or_fallback (buffer);
vin = &g_array_index (vertices, float, 0);
/* Expand the number of vertices from 2 to 4 while uploading */
memcpy (vout + vb_stride * i + POS_STRIDE, vin, 4);
vin++;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
{
vout[vb_stride * 0] = vin[0];
vout[vb_stride * 0 + 1] = vin[1];
vout += vb_stride * 4;
}
- cogl_buffer_unmap (buffer);
+ _cogl_buffer_unmap_for_fill_or_fallback (buffer);
return array;
}
+void
+_cogl_journal_discard (CoglJournal *journal)
+{
+ int i;
+
+ for (i = 0; i < journal->entries->len; i++)
+ {
+ CoglJournalEntry *entry =
+ &g_array_index (journal->entries, CoglJournalEntry, i);
+ _cogl_pipeline_journal_unref (entry->pipeline);
+ _cogl_clip_stack_unref (entry->clip_stack);
+ }
+
+ g_array_set_size (journal->entries, 0);
+ g_array_set_size (journal->vertices, 0);
+ journal->needed_vbo_len = 0;
+ journal->fast_read_pixel_count = 0;
+}
+
+/* Note: A return value of FALSE doesn't mean 'no' it means
+ * 'unknown' */
+gboolean
+_cogl_journal_all_entries_within_bounds (CoglJournal *journal,
+ float clip_x0,
+ float clip_y0,
+ float clip_x1,
+ float clip_y1)
+{
+ CoglJournalEntry *entry = (CoglJournalEntry *)journal->entries->data;
+ CoglClipStack *clip_entry;
+ CoglClipStack *reference = NULL;
+ int bounds_x0;
+ int bounds_y0;
+ int bounds_x1;
+ int bounds_y1;
+ int i;
+
+ if (journal->entries->len == 0)
+ return TRUE;
+
+ /* Find the shortest clip_stack ancestry that leaves us in the
+ * required bounds */
+ for (clip_entry = entry->clip_stack;
+ clip_entry;
+ clip_entry = clip_entry->parent)
+ {
+ _cogl_clip_stack_get_bounds (clip_entry,
+ &bounds_x0, &bounds_y0,
+ &bounds_x1, &bounds_y1);
+
+ if (bounds_x0 >= clip_x0 && bounds_y0 >= clip_y0 &&
+ bounds_x1 <= clip_x1 && bounds_y1 <= clip_y1)
+ reference = clip_entry;
+ else
+ break;
+ }
+
+ if (!reference)
+ return FALSE;
+
+ /* For the remaining journal entries we will only verify they share
+ * 'reference' as an ancestor in their clip stack since that's
+ * enough to know that they would be within the required bounds.
+ */
+ for (i = 1; i < journal->entries->len; i++)
+ {
+ gboolean found_reference = FALSE;
+ entry = &g_array_index (journal->entries, CoglJournalEntry, i);
+
+ for (clip_entry = entry->clip_stack;
+ clip_entry;
+ clip_entry = clip_entry->parent)
+ {
+ if (clip_entry == reference)
+ {
+ found_reference = TRUE;
+ break;
+ }
+ }
+
+ if (!found_reference)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* XXX NB: When _cogl_journal_flush() returns all state relating
* to pipelines, all glEnable flags and current matrix state
* is undefined.
*/
void
-_cogl_journal_flush (void)
+_cogl_journal_flush (CoglJournal *journal,
+ CoglFramebuffer *framebuffer)
{
CoglJournalFlushState state;
int i;
- CoglFramebuffer *framebuffer;
CoglMatrixStack *modelview_stack;
COGL_STATIC_TIMER (flush_timer,
"Mainloop", /* parent */
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- if (ctx->journal->len == 0)
+ if (journal->entries->len == 0)
return;
+ /* The entries in this journal may depend on images in other
+ * framebuffers which may require that we flush the journals
+ * associated with those framebuffers before we can flush
+ * this journal... */
+ _cogl_framebuffer_flush_dependency_journals (framebuffer);
+
+ /* Note: we start the timer after flushing dependency journals so
+ * that the timer isn't started recursively. */
COGL_TIMER_START (_cogl_uprof_context, flush_timer);
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_BATCHING))
- g_print ("BATCHING: journal len = %d\n", ctx->journal->len);
+ cogl_push_framebuffer (framebuffer);
+
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
+ g_print ("BATCHING: journal len = %d\n", journal->entries->len);
+
+ /* NB: the journal deals with flushing the modelview stack and clip
+ state manually */
+ _cogl_framebuffer_flush_state (framebuffer,
+ COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW |
+ COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE);
+
+ state.journal = journal;
state.attributes = ctx->journal_flush_attributes_array;
- framebuffer = _cogl_get_framebuffer ();
modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer);
state.modelview_stack = modelview_stack;
state.projection_stack = _cogl_framebuffer_get_projection_stack (framebuffer);
- if (G_UNLIKELY ((cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_CLIP) == 0))
+ if (G_UNLIKELY ((COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_CLIP)) == 0))
{
/* We do an initial walk of the journal to analyse the clip stack
batches to see if we can do software clipping. We do this as a
separate walk of the journal because we can modify entries and
this may end up joining together clip stack batches in the next
iteration. */
- batch_and_call ((CoglJournalEntry *)ctx->journal->data, /* first entry */
- ctx->journal->len, /* max number of entries to consider */
+ batch_and_call ((CoglJournalEntry *)journal->entries->data, /* first entry */
+ journal->entries->len, /* max number of entries to consider */
compare_entry_clip_stacks,
- _cogl_journal_check_software_clip, /* callback */
+ _cogl_journal_maybe_software_clip_entries, /* callback */
&state); /* data */
}
/* We upload the vertices after the clip stack pass in case it
modifies the entries */
- state.vertex_array = upload_vertices (&g_array_index (ctx->journal,
+ state.vertex_array = upload_vertices (&g_array_index (journal->entries,
CoglJournalEntry, 0),
- ctx->journal->len,
- ctx->journal_needed_vbo_len,
- ctx->logged_vertices);
+ journal->entries->len,
+ journal->needed_vbo_len,
+ journal->vertices);
state.array_offset = 0;
/* batch_and_call() batches a list of journal entries according to some
* Note: Splitting by modelview changes is skipped when are doing the
* vertex transformation in software at log time.
*/
- batch_and_call ((CoglJournalEntry *)ctx->journal->data, /* first entry */
- ctx->journal->len, /* max number of entries to consider */
+ batch_and_call ((CoglJournalEntry *)journal->entries->data, /* first entry */
+ journal->entries->len, /* max number of entries to consider */
compare_entry_clip_stacks,
_cogl_journal_flush_clip_stacks_and_entries, /* callback */
&state); /* data */
for (i = 0; i < state.attributes->len; i++)
- cogl_object_unref (g_array_index (state.attributes,
- CoglVertexAttribute *, i));
+ cogl_object_unref (g_array_index (state.attributes, CoglAttribute *, i));
g_array_set_size (state.attributes, 0);
cogl_object_unref (state.vertex_array);
- for (i = 0; i < ctx->journal->len; i++)
- {
- CoglJournalEntry *entry =
- &g_array_index (ctx->journal, CoglJournalEntry, i);
- _cogl_pipeline_journal_unref (entry->pipeline);
- _cogl_clip_stack_unref (entry->clip_stack);
- }
+ _cogl_journal_discard (journal);
- g_array_set_size (ctx->journal, 0);
- g_array_set_size (ctx->logged_vertices, 0);
+ cogl_pop_framebuffer ();
COGL_TIMER_STOP (_cogl_uprof_context, flush_timer);
}
-static void
-_cogl_journal_init (void)
+static gboolean
+add_framebuffer_deps_cb (CoglPipelineLayer *layer, void *user_data)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ CoglFramebuffer *framebuffer = user_data;
+ CoglHandle texture = _cogl_pipeline_layer_get_texture_real (layer);
+ const GList *l;
- /* Here we flush anything that we know must remain constant until the
- * next the the journal is flushed. Note: This lets up flush things
- * that themselves depend on the journal, such as clip state. */
+ if (!texture)
+ return TRUE;
- /* NB: the journal deals with flushing the modelview stack and clip
- state manually */
- _cogl_framebuffer_flush_state (_cogl_get_framebuffer (),
- COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW |
- COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE);
+ for (l = _cogl_texture_get_associated_framebuffers (texture); l; l = l->next)
+ _cogl_framebuffer_add_dependency (framebuffer, l->data);
- ctx->journal_needed_vbo_len = 0;
+ return TRUE;
}
void
-_cogl_journal_log_quad (const float *position,
+_cogl_journal_log_quad (CoglJournal *journal,
+ const float *position,
CoglPipeline *pipeline,
int n_layers,
CoglHandle layer0_override_texture,
{
gsize stride;
int next_vert;
- GLfloat *v;
+ float *v;
int i;
int next_entry;
guint32 disable_layers;
CoglJournalEntry *entry;
CoglPipeline *source;
+ CoglClipStack *clip_stack;
CoglPipelineFlushOptions flush_options;
COGL_STATIC_TIMER (log_timer,
"Mainloop", /* parent */
COGL_TIMER_START (_cogl_uprof_context, log_timer);
- if (ctx->logged_vertices->len == 0)
- _cogl_journal_init ();
-
/* The vertex data is logged into a separate array. The data needs
to be copied into a vertex array before it's given to GL so we
only store two vertices per quad and expand it to four while
* about how we pack our vertex data */
stride = GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (n_layers);
- next_vert = ctx->logged_vertices->len;
- g_array_set_size (ctx->logged_vertices, next_vert + 2 * stride + 1);
- v = &g_array_index (ctx->logged_vertices, GLfloat, next_vert);
+ next_vert = journal->vertices->len;
+ g_array_set_size (journal->vertices, next_vert + 2 * stride + 1);
+ v = &g_array_index (journal->vertices, float, next_vert);
/* We calculate the needed size of the vbo as we go because it
depends on the number of layers in each entry and it's not easy
calculate based on the length of the logged vertices array */
- ctx->journal_needed_vbo_len +=
- GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers) * 4;
+ journal->needed_vbo_len += GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers) * 4;
/* XXX: All the jumping around to fill in this strided buffer doesn't
* seem ideal. */
memcpy (t + stride, tex_coords + i * 4 + 2, sizeof (float) * 2);
}
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_JOURNAL))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL)))
{
g_print ("Logged new quad:\n");
- v = &g_array_index (ctx->logged_vertices, GLfloat, next_vert);
+ v = &g_array_index (journal->vertices, float, next_vert);
_cogl_journal_dump_logged_quad ((guint8 *)v, n_layers);
}
- next_entry = ctx->journal->len;
- g_array_set_size (ctx->journal, next_entry + 1);
- entry = &g_array_index (ctx->journal, CoglJournalEntry, next_entry);
+ next_entry = journal->entries->len;
+ g_array_set_size (journal->entries, next_entry + 1);
+ entry = &g_array_index (journal->entries, CoglJournalEntry, next_entry);
entry->n_layers = n_layers;
entry->array_offset = next_vert;
}
entry->pipeline = _cogl_pipeline_journal_ref (source);
- entry->clip_stack = _cogl_clip_stack_ref (_cogl_get_clip_stack ());
+
+ clip_stack = _cogl_framebuffer_get_clip_stack (_cogl_get_framebuffer ());
+ entry->clip_stack = _cogl_clip_stack_ref (clip_stack);
if (G_UNLIKELY (source != pipeline))
cogl_handle_unref (source);
cogl_get_modelview_matrix (&entry->model_view);
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_BATCHING))
- _cogl_journal_flush ();
+ _cogl_pipeline_foreach_layer_internal (pipeline,
+ add_framebuffer_deps_cb,
+ _cogl_get_framebuffer ());
+
+ /* XXX: It doesn't feel very nice that in this case we just assume
+ * that the journal is associated with the current framebuffer. I
+ * think a journal->framebuffer reference would seem nicer here but
+ * the reason we don't have that currently is that it would
+ * introduce a circular reference. */
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BATCHING)))
+ _cogl_framebuffer_flush_journal (_cogl_get_framebuffer ());
COGL_TIMER_STOP (_cogl_uprof_context, log_timer);
}
+static void
+entry_to_screen_polygon (const CoglJournalEntry *entry,
+ float *vertices,
+ float *poly)
+{
+ size_t array_stride =
+ GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (entry->n_layers);
+ CoglMatrixStack *projection_stack;
+ CoglMatrix projection;
+ int i;
+ int viewport[4];
+
+ poly[0] = vertices[0];
+ poly[1] = vertices[1];
+ poly[2] = 0;
+ poly[3] = 1;
+
+ poly[4] = vertices[0];
+ poly[5] = vertices[array_stride + 1];
+ poly[6] = 0;
+ poly[7] = 1;
+
+ poly[8] = vertices[array_stride];
+ poly[9] = vertices[array_stride + 1];
+ poly[10] = 0;
+ poly[11] = 1;
+
+ poly[12] = vertices[array_stride];
+ poly[13] = vertices[1];
+ poly[14] = 0;
+ poly[15] = 1;
+
+ /* TODO: perhaps split the following out into a more generalized
+ * _cogl_transform_points utility...
+ */
+
+ cogl_matrix_transform_points (&entry->model_view,
+ 2, /* n_components */
+ sizeof (float) * 4, /* stride_in */
+ poly, /* points_in */
+ /* strideout */
+ sizeof (float) * 4,
+ poly, /* points_out */
+ 4 /* n_points */);
+
+ projection_stack =
+ _cogl_framebuffer_get_projection_stack (_cogl_get_framebuffer ());
+ _cogl_matrix_stack_get (projection_stack, &projection);
+
+ cogl_matrix_project_points (&projection,
+ 3, /* n_components */
+ sizeof (float) * 4, /* stride_in */
+ poly, /* points_in */
+ /* strideout */
+ sizeof (float) * 4,
+ poly, /* points_out */
+ 4 /* n_points */);
+
+ _cogl_framebuffer_get_viewport4fv (_cogl_get_framebuffer (),
+ viewport);
+
+/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1)
+ * to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with
+ * (0,0) being top left. */
+#define VIEWPORT_TRANSFORM_X(x, vp_origin_x, vp_width) \
+ ( ( ((x) + 1.0) * ((vp_width) / 2.0) ) + (vp_origin_x) )
+/* Note: for Y we first flip all coordinates around the X axis while in
+ * normalized device coodinates */
+#define VIEWPORT_TRANSFORM_Y(y, vp_origin_y, vp_height) \
+ ( ( ((-(y)) + 1.0) * ((vp_height) / 2.0) ) + (vp_origin_y) )
+
+ /* Scale from normalized device coordinates (in range [-1,1]) to
+ * window coordinates ranging [0,window-size] ... */
+ for (i = 0; i < 4; i++)
+ {
+ float w = poly[4 * i + 3];
+
+ /* Perform perspective division */
+ poly[4 * i] /= w;
+ poly[4 * i + 1] /= w;
+
+ /* Apply viewport transform */
+ poly[4 * i] = VIEWPORT_TRANSFORM_X (poly[4 * i],
+ viewport[0], viewport[2]);
+ poly[4 * i + 1] = VIEWPORT_TRANSFORM_Y (poly[4 * i + 1],
+ viewport[1], viewport[3]);
+ }
+
+#undef VIEWPORT_TRANSFORM_X
+#undef VIEWPORT_TRANSFORM_Y
+}
+
+static gboolean
+try_checking_point_hits_entry_after_clipping (CoglJournalEntry *entry,
+ float *vertices,
+ float x,
+ float y,
+ gboolean *hit)
+{
+ gboolean can_software_clip = TRUE;
+ gboolean needs_software_clip = FALSE;
+ CoglClipStack *clip_entry;
+
+ *hit = TRUE;
+
+ /* Verify that all of the clip stack entries are simple rectangle
+ * clips */
+ for (clip_entry = entry->clip_stack;
+ clip_entry;
+ clip_entry = clip_entry->parent)
+ {
+ if (x < clip_entry->bounds_x0 ||
+ x >= clip_entry->bounds_x1 ||
+ y < clip_entry->bounds_y0 ||
+ y >= clip_entry->bounds_y1)
+ {
+ *hit = FALSE;
+ return TRUE;
+ }
+
+ if (clip_entry->type == COGL_CLIP_STACK_WINDOW_RECT)
+ {
+ /* XXX: technically we could still run the software clip in
+ * this case because for our purposes we know this clip
+ * can be ignored now, but [can_]sofware_clip_entry() doesn't
+ * know this and will bail out. */
+ can_software_clip = FALSE;
+ }
+ else if (clip_entry->type == COGL_CLIP_STACK_RECT)
+ {
+ CoglClipStackRect *rect_entry = (CoglClipStackRect *)entry;
+
+ if (rect_entry->can_be_scissor == FALSE)
+ needs_software_clip = TRUE;
+ /* If can_be_scissor is TRUE then we know it's screen
+ * aligned and the hit test we did above has determined
+ * that we are inside this clip. */
+ }
+ else
+ return FALSE;
+ }
+
+ if (needs_software_clip)
+ {
+ ClipBounds clip_bounds;
+ float poly[16];
+
+ if (!can_software_clip)
+ return FALSE;
+
+ if (!can_software_clip_entry (entry, NULL,
+ entry->clip_stack, &clip_bounds))
+ return FALSE;
+
+ software_clip_entry (entry, vertices, &clip_bounds);
+ entry_to_screen_polygon (entry, vertices, poly);
+
+ *hit = _cogl_util_point_in_poly (x, y, poly, sizeof (float) * 4, 4);
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+_cogl_journal_try_read_pixel (CoglJournal *journal,
+ int x,
+ int y,
+ CoglPixelFormat format,
+ guint8 *pixel,
+ gboolean *found_intersection)
+{
+ int i;
+
+ _COGL_GET_CONTEXT (ctx, FALSE);
+
+ /* XXX: this number has been plucked out of thin air, but the idea
+ * is that if so many pixels are being read from the same un-changed
+ * journal than we expect that it will be more efficient to fail
+ * here so we end up flushing and rendering the journal so that
+ * further reads can directly read from the framebuffer. There will
+ * be a bit more lag to flush the render but if there are going to
+ * continue being lots of arbitrary single pixel reads they will end
+ * up faster in the end. */
+ if (journal->fast_read_pixel_count > 50)
+ return FALSE;
+
+ if (format != COGL_PIXEL_FORMAT_RGBA_8888_PRE &&
+ format != COGL_PIXEL_FORMAT_RGBA_8888)
+ return FALSE;
+
+ *found_intersection = FALSE;
+
+ /* NB: The most recently added journal entry is the last entry, and
+ * assuming this is a simple scene only comprised of opaque coloured
+ * rectangles with no special pipelines involved (e.g. enabling
+ * depth testing) then we can assume painter's algorithm for the
+ * entries and so our fast read-pixel just needs to walk backwards
+ * through the journal entries trying to intersect each entry with
+ * the given point of interest. */
+ for (i = journal->entries->len - 1; i >= 0; i--)
+ {
+ CoglJournalEntry *entry =
+ &g_array_index (journal->entries, CoglJournalEntry, i);
+ guint8 *color = (guint8 *)&g_array_index (journal->vertices, float,
+ entry->array_offset);
+ float *vertices = (float *)color + 1;
+ float poly[16];
+
+ entry_to_screen_polygon (entry, vertices, poly);
+
+ if (!_cogl_util_point_in_poly (x, y, poly, sizeof (float) * 4, 4))
+ continue;
+
+ /* FIXME: the journal should have a back pointer to the
+ * associated framebuffer, because it should be possible to read
+ * a pixel from arbitrary framebuffers without needing to
+ * internally call _cogl_push/pop_framebuffer.
+ */
+ if (entry->clip_stack)
+ {
+ gboolean hit;
+
+ if (!try_checking_point_hits_entry_after_clipping (entry, vertices,
+ x, y, &hit))
+ return FALSE; /* hit couldn't be determined */
+
+ if (!hit)
+ continue;
+ }
+
+ *found_intersection = TRUE;
+
+ /* If we find that the rectangle the point of interest
+ * intersects has any state more complex than a constant opaque
+ * color then we bail out. */
+ if (!_cogl_pipeline_equal (ctx->opaque_color_pipeline, entry->pipeline,
+ (COGL_PIPELINE_STATE_ALL &
+ ~COGL_PIPELINE_STATE_COLOR),
+ COGL_PIPELINE_LAYER_STATE_ALL,
+ 0))
+ return FALSE;
+
+
+ /* we currently only care about cases where the premultiplied or
+ * unpremultipled colors are equivalent... */
+ if (color[3] != 0xff)
+ return FALSE;
+
+ pixel[0] = color[0];
+ pixel[1] = color[1];
+ pixel[2] = color[2];
+ pixel[3] = color[3];
+
+ goto success;
+ }
+
+success:
+ journal->fast_read_pixel_count++;
+ return TRUE;
+}
G_BEGIN_DECLS
#define _COGL_MATRIX_DEBUG_PRINT(MATRIX) \
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_MATRICES)) \
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_MATRICES))) \
{ \
g_print ("%s:\n", G_STRFUNC); \
_cogl_matrix_print (MATRIX); \
} Point4f;
static void
-_cogl_matrix_transform_points_f2_packed (const CoglMatrix *matrix,
- void *points_in,
- void *points_out,
- int n_points)
+_cogl_matrix_transform_points_f2 (const CoglMatrix *matrix,
+ size_t stride_in,
+ void *points_in,
+ size_t stride_out,
+ void *points_out,
+ int n_points)
{
- Point2f *p = points_in;
- Point3f *o = points_out;
int i;
for (i = 0; i < n_points; i++)
{
- o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y +
- matrix->xw;
- o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y +
- matrix->yw;
- o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y +
- matrix->zw;
- }
-}
-
-static void
-_cogl_matrix_transform_points_f2_strided (const CoglMatrix *matrix,
- size_t stride_in,
- void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- Point2f *p = (Point2f *)((guint8 *)points_in + i * stride_in);
+ Point2f p = *(Point2f *)((guint8 *)points_in + i * stride_in);
Point3f *o = (Point3f *)((guint8 *)points_out + i * stride_out);
- o->x = matrix->xx * p->x + matrix->xy * p->y + matrix->xw;
- o->y = matrix->yx * p->x + matrix->yy * p->y + matrix->yw;
- o->z = matrix->zx * p->x + matrix->zy * p->y + matrix->zw;
- }
-}
-
-static void
-_cogl_matrix_project_points_f2_packed (const CoglMatrix *matrix,
- void *points_in,
- void *points_out,
- int n_points)
-{
- Point2f *p = points_in;
- Point4f *o = points_out;
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y +
- matrix->xw;
- o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y +
- matrix->yw;
- o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y +
- matrix->zw;
- o[i].w = matrix->wx * p[i].x + matrix->wy * p[i].y +
- matrix->ww;
+ o->x = matrix->xx * p.x + matrix->xy * p.y + matrix->xw;
+ o->y = matrix->yx * p.x + matrix->yy * p.y + matrix->yw;
+ o->z = matrix->zx * p.x + matrix->zy * p.y + matrix->zw;
}
}
static void
-_cogl_matrix_project_points_f2_strided (const CoglMatrix *matrix,
- size_t stride_in,
- void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
+_cogl_matrix_project_points_f2 (const CoglMatrix *matrix,
+ size_t stride_in,
+ void *points_in,
+ size_t stride_out,
+ void *points_out,
+ int n_points)
{
int i;
for (i = 0; i < n_points; i++)
{
- Point2f *p = (Point2f *)((guint8 *)points_in + i * stride_in);
+ Point2f p = *(Point2f *)((guint8 *)points_in + i * stride_in);
Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
- o->x = matrix->xx * p->x + matrix->xy * p->y + matrix->xw;
- o->y = matrix->yx * p->x + matrix->yy * p->y + matrix->yw;
- o->z = matrix->zx * p->x + matrix->zy * p->y + matrix->zw;
- o->w = matrix->wx * p->x + matrix->wy * p->y + matrix->ww;
- }
-}
-
-static void
-_cogl_matrix_transform_points_f3_packed (const CoglMatrix *matrix,
- void *points_in,
- void *points_out,
- int n_points)
-{
- Point3f *p = points_in;
- Point3f *o = points_out;
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y +
- matrix->xz * p[i].z + matrix->xw;
- o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y +
- matrix->yz * p[i].z + matrix->yw;
- o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y +
- matrix->zz * p[i].z + matrix->zw;
+ o->x = matrix->xx * p.x + matrix->xy * p.y + matrix->xw;
+ o->y = matrix->yx * p.x + matrix->yy * p.y + matrix->yw;
+ o->z = matrix->zx * p.x + matrix->zy * p.y + matrix->zw;
+ o->w = matrix->wx * p.x + matrix->wy * p.y + matrix->ww;
}
}
static void
-_cogl_matrix_transform_points_f3_strided (const CoglMatrix *matrix,
- size_t stride_in,
- void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
+_cogl_matrix_transform_points_f3 (const CoglMatrix *matrix,
+ size_t stride_in,
+ void *points_in,
+ size_t stride_out,
+ void *points_out,
+ int n_points)
{
int i;
for (i = 0; i < n_points; i++)
{
- Point3f *p = (Point3f *)((guint8 *)points_in + i * stride_in);
+ Point3f p = *(Point3f *)((guint8 *)points_in + i * stride_in);
Point3f *o = (Point3f *)((guint8 *)points_out + i * stride_out);
- o->x = matrix->xx * p->x + matrix->xy * p->y +
- matrix->xz * p->z + matrix->xw;
- o->y = matrix->yx * p->x + matrix->yy * p->y +
- matrix->yz * p->z + matrix->yw;
- o->z = matrix->zx * p->x + matrix->zy * p->y +
- matrix->zz * p->z + matrix->zw;
+ o->x = matrix->xx * p.x + matrix->xy * p.y +
+ matrix->xz * p.z + matrix->xw;
+ o->y = matrix->yx * p.x + matrix->yy * p.y +
+ matrix->yz * p.z + matrix->yw;
+ o->z = matrix->zx * p.x + matrix->zy * p.y +
+ matrix->zz * p.z + matrix->zw;
}
}
static void
-_cogl_matrix_project_points_f3_packed (const CoglMatrix *matrix,
- void *points_in,
- void *points_out,
- int n_points)
+_cogl_matrix_project_points_f3 (const CoglMatrix *matrix,
+ size_t stride_in,
+ void *points_in,
+ size_t stride_out,
+ void *points_out,
+ int n_points)
{
- Point3f *p = points_in;
- Point4f *o = points_out;
int i;
for (i = 0; i < n_points; i++)
{
- o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y +
- matrix->xz * p[i].z + matrix->xw;
- o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y +
- matrix->yz * p[i].z + matrix->yw;
- o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y +
- matrix->zz * p[i].z + matrix->zw;
- o[i].w = matrix->wx * p[i].x + matrix->wy * p[i].y +
- matrix->wz * p[i].z + matrix->ww;
- }
-}
-
-static void
-_cogl_matrix_project_points_f3_strided (const CoglMatrix *matrix,
- size_t stride_in,
- void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- Point3f *p = (Point3f *)((guint8 *)points_in + i * stride_in);
+ Point3f p = *(Point3f *)((guint8 *)points_in + i * stride_in);
Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
- o->x = matrix->xx * p->x + matrix->xy * p->y +
- matrix->xz * p->z + matrix->xw;
- o->y = matrix->yx * p->x + matrix->yy * p->y +
- matrix->yz * p->z + matrix->yw;
- o->z = matrix->zx * p->x + matrix->zy * p->y +
- matrix->zz * p->z + matrix->zw;
- o->w = matrix->wx * p->x + matrix->wy * p->y +
- matrix->wz * p->z + matrix->ww;
- }
-}
-
-static void
-_cogl_matrix_project_points_f4_packed (const CoglMatrix *matrix,
- void *points_in,
- void *points_out,
- int n_points)
-{
- Point4f *p = points_in;
- Point4f *o = points_out;
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y +
- matrix->xz * p[i].z + matrix->xw * p[i].w;
- o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y +
- matrix->yz * p[i].z + matrix->yw * p[i].w;
- o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y +
- matrix->zz * p[i].z + matrix->zw * p[i].w;
- o[i].w = matrix->wx * p[i].x + matrix->wy * p[i].y +
- matrix->wz * p[i].z + matrix->ww * p[i].w;
+ o->x = matrix->xx * p.x + matrix->xy * p.y +
+ matrix->xz * p.z + matrix->xw;
+ o->y = matrix->yx * p.x + matrix->yy * p.y +
+ matrix->yz * p.z + matrix->yw;
+ o->z = matrix->zx * p.x + matrix->zy * p.y +
+ matrix->zz * p.z + matrix->zw;
+ o->w = matrix->wx * p.x + matrix->wy * p.y +
+ matrix->wz * p.z + matrix->ww;
}
}
static void
-_cogl_matrix_project_points_f4_strided (const CoglMatrix *matrix,
- size_t stride_in,
- void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
+_cogl_matrix_project_points_f4 (const CoglMatrix *matrix,
+ size_t stride_in,
+ void *points_in,
+ size_t stride_out,
+ void *points_out,
+ int n_points)
{
int i;
for (i = 0; i < n_points; i++)
{
- Point4f *p = (Point4f *)((guint8 *)points_in + i * stride_in);
+ Point4f p = *(Point4f *)((guint8 *)points_in + i * stride_in);
Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
- o->x = matrix->xx * p->x + matrix->xy * p->y +
- matrix->xz * p->z + matrix->xw * p->w;
- o->y = matrix->yx * p->x + matrix->yy * p->y +
- matrix->yz * p->z + matrix->yw * p->w;
- o->z = matrix->zx * p->x + matrix->zy * p->y +
- matrix->zz * p->z + matrix->zw * p->w;
- o->w = matrix->wx * p->x + matrix->wy * p->y +
- matrix->wz * p->z + matrix->ww * p->w;
+ o->x = matrix->xx * p.x + matrix->xy * p.y +
+ matrix->xz * p.z + matrix->xw * p.w;
+ o->y = matrix->yx * p.x + matrix->yy * p.y +
+ matrix->yz * p.z + matrix->yw * p.w;
+ o->z = matrix->zx * p.x + matrix->zy * p.y +
+ matrix->zz * p.z + matrix->zw * p.w;
+ o->w = matrix->wx * p.x + matrix->wy * p.y +
+ matrix->wz * p.z + matrix->ww * p.w;
}
}
g_return_if_fail (stride_out >= sizeof (Point3f));
if (n_components == 2)
- {
- if (stride_in == sizeof (Point2f) &&
- stride_out == sizeof (Point3f))
- _cogl_matrix_transform_points_f2_packed (matrix,
- points_in, points_out,
- n_points);
- else
- _cogl_matrix_transform_points_f2_strided (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
- }
+ _cogl_matrix_transform_points_f2 (matrix,
+ stride_in, points_in,
+ stride_out, points_out,
+ n_points);
else
{
g_return_if_fail (n_components == 3);
- if (stride_in == sizeof (Point3f) && stride_out == stride_in)
- _cogl_matrix_transform_points_f3_packed (matrix,
- points_in, points_out,
- n_points);
- else
- _cogl_matrix_transform_points_f3_strided (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
+ _cogl_matrix_transform_points_f3 (matrix,
+ stride_in, points_in,
+ stride_out, points_out,
+ n_points);
}
}
int n_points)
{
if (n_components == 2)
- {
- if (stride_in == sizeof (Point2f) &&
- stride_out == sizeof (Point4f))
- _cogl_matrix_project_points_f2_packed (matrix,
- points_in, points_out,
- n_points);
- else
- _cogl_matrix_project_points_f2_strided (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
- }
+ _cogl_matrix_project_points_f2 (matrix,
+ stride_in, points_in,
+ stride_out, points_out,
+ n_points);
else if (n_components == 3)
- {
- if (stride_in == sizeof (Point3f) &&
- stride_out == sizeof (Point4f))
- _cogl_matrix_project_points_f3_packed (matrix,
- points_in, points_out,
- n_points);
- else
- _cogl_matrix_project_points_f3_strided (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
- }
+ _cogl_matrix_project_points_f3 (matrix,
+ stride_in, points_in,
+ stride_out, points_out,
+ n_points);
else
{
g_return_if_fail (n_components == 4);
- if (stride_in == sizeof (Point4f) && stride_out == stride_in)
- _cogl_matrix_project_points_f4_packed (matrix,
- points_in, points_out,
- n_points);
- else
- _cogl_matrix_project_points_f4_strided (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
+ _cogl_matrix_project_points_f4 (matrix,
+ stride_in, points_in,
+ stride_out, points_out,
+ n_points);
}
}
-
* @b: A 4x4 transformation matrix
*
* Multiplies the two supplied matrices together and stores
- * the resulting matrix inside @result
+ * the resulting matrix inside @result.
+ *
+ * <note>It is possible to multiply the @a matrix in-place, so
+ * @result can be equal to @a but can't be equal to @b.</note>
*/
void
cogl_matrix_multiply (CoglMatrix *result,
typedef struct _CoglObjectClass CoglHandleClass;
typedef struct _CoglObject CoglHandleObject;
+/* XXX: sadly we didn't fully consider when we copied the cairo API
+ * for _set_user_data that the callback doesn't get a pointer to the
+ * instance which is desired in most cases. This means you tend to end
+ * up creating micro allocations for the private data just so you can
+ * pair up the data of interest with the original instance for
+ * identification when it is later destroyed.
+ *
+ * Internally we use a small hack to avoid needing these micro
+ * allocations by actually passing the instance as a second argument
+ * to the callback */
+typedef void (*CoglUserDataDestroyInternalCallback) (void *user_data,
+ void *instance);
+
typedef struct _CoglObjectClass
{
GQuark type;
{
CoglUserDataKey *key;
void *user_data;
- CoglUserDataDestroyCallback destroy;
+ CoglUserDataDestroyInternalCallback destroy;
} CoglUserDataEntry;
/* All Cogl objects inherit from this base object by adding a member:
#define COGL_HANDLE_DEFINE(TypeName, type_name) \
COGL_HANDLE_DEFINE_WITH_CODE (TypeName, type_name, (void) 0)
+void
+_cogl_object_set_user_data (CoglObject *object,
+ CoglUserDataKey *key,
+ void *user_data,
+ CoglUserDataDestroyInternalCallback destroy);
+
#endif /* __COGL_OBJECT_PRIVATE_H */
{
CoglUserDataEntry *entry = &obj->user_data_entry[i];
if (entry->destroy)
- entry->destroy (entry->user_data);
+ entry->destroy (entry->user_data, obj);
}
if (obj->user_data_array != NULL)
CoglUserDataEntry, i);
if (entry->destroy)
- entry->destroy (entry->user_data);
+ entry->destroy (entry->user_data, obj);
}
g_array_free (obj->user_data_array, TRUE);
}
}
void
-cogl_object_set_user_data (CoglObject *object,
- CoglUserDataKey *key,
- void *user_data,
- CoglUserDataDestroyCallback destroy)
+_cogl_object_set_user_data (CoglObject *object,
+ CoglUserDataKey *key,
+ void *user_data,
+ CoglUserDataDestroyInternalCallback destroy)
{
CoglUserDataEntry new_entry;
CoglUserDataEntry *entry;
if (entry)
{
if (G_LIKELY (entry->destroy))
- entry->destroy (entry->user_data);
+ entry->destroy (entry->user_data, object);
}
else
{
*entry = new_entry;
}
+void
+cogl_object_set_user_data (CoglObject *object,
+ CoglUserDataKey *key,
+ void *user_data,
+ CoglUserDataDestroyCallback destroy)
+{
+ _cogl_object_set_user_data (object, key, user_data,
+ (CoglUserDataDestroyInternalCallback)destroy);
+}
+
void *
cogl_object_get_user_data (CoglObject *object, CoglUserDataKey *key)
{
CoglVertexArray *fill_vbo;
CoglIndices *fill_vbo_indices;
unsigned int fill_vbo_n_indices;
- CoglVertexAttribute *fill_vbo_attributes[COGL_PATH_N_ATTRIBUTES + 1];
+ CoglAttribute *fill_vbo_attributes[COGL_PATH_N_ATTRIBUTES + 1];
CoglVertexArray *stroke_vbo;
- CoglVertexAttribute **stroke_vbo_attributes;
+ CoglAttribute **stroke_vbo_attributes;
unsigned int stroke_vbo_n_attributes;
};
(pipeline,
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
~COGL_PIPELINE_STATE_LAYERS,
- COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN,
- COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET);
+ COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN);
authority_priv = get_arbfp_priv (authority);
if (authority_priv &&
authority_priv->arbfp_program_state)
/* If we haven't yet found an existing program then before we resort to
* generating a new arbfp program we see if we can find a suitable
* program in the arbfp_cache. */
- if (G_LIKELY (!(cogl_debug_flags & COGL_DEBUG_DISABLE_PROGRAM_CACHES)))
+ if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES))))
{
arbfp_program_state = g_hash_table_lookup (ctx->arbfp_cache, authority);
if (arbfp_program_state)
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
unsigned long layer_fragment_state =
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
- CoglPipelineEvalFlags flags = COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA;
return _cogl_pipeline_hash ((CoglPipeline *)data,
fragment_state, layer_fragment_state,
- flags);
+ 0);
}
gboolean
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
unsigned long layer_fragment_state =
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
- CoglPipelineEvalFlags flags = COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA;
return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
fragment_state, layer_fragment_state,
- flags);
+ 0);
}
static const char *
"MOV result.color,output;\n");
g_string_append (arbfp_program_state->source, "END\n");
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_SHOW_SOURCE))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
g_message ("pipeline program:\n%s", arbfp_program_state->source->str);
GE (glGenPrograms (1, &arbfp_program_state->gl_program));
arbfp_program_state->source = NULL;
- if (G_LIKELY (!(cogl_debug_flags & COGL_DEBUG_DISABLE_PROGRAM_CACHES)))
+ if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES))))
{
CoglPipeline *key;
{
CoglHandle user_program;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_FIXED))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
return FALSE;
/* If there is a user program with a fragment shader then the
}
/* Handle enabling or disabling the right texture target */
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE)
+ if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET)
{
- CoglPipelineLayer *authority =
+ CoglPipelineLayer *tex_authority =
_cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE);
- CoglHandle texture;
- GLuint gl_texture;
- GLenum gl_target;
-
- texture = (authority->texture == COGL_INVALID_HANDLE ?
- ctx->default_gl_texture_2d_tex :
- authority->texture);
-
- cogl_texture_get_gl_texture (texture,
- &gl_texture,
- &gl_target);
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
+ CoglPipelineLayer *target_authority =
+ _cogl_pipeline_layer_get_authority (layer,
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET);
+ /* XXX: currently layers with no associated texture fallback to
+ * using ctx->default_gl_texture_2d_tex so they have a texture
+ * target of GL_TEXTURE_2D */
+ GLenum gl_target =
+ tex_authority->texture ? target_authority->target : GL_TEXTURE_2D;
_cogl_set_active_texture_unit (unit_index);
GE (glDisable (unit->enabled_gl_target));
/* Enable the new target */
- if (!G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_TEXTURING))
+ if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)))
{
GE (glEnable (gl_target));
unit->enabled_gl_target = gl_target;
* texture unit has been disabled for some time so we need to assert that
* it's enabled now.
*/
- if (!G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_TEXTURING) &&
+ if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)) &&
!unit->enabled_gl_target == 0)
{
_cogl_set_active_texture_unit (unit_index);
(pipeline,
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
~COGL_PIPELINE_STATE_LAYERS,
- COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN,
- COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET);
+ COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN);
authority_priv = get_glsl_priv (authority);
if (!authority_priv)
* we continue to check the rest */
}
}
+
static void
set_glsl_program (GLuint gl_program)
{
+#ifdef HAVE_COGL_GLES
+
+ g_return_if_reached ();
+
+#else /* HAVE_COGL_GLES */
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (ctx->current_gl_program != gl_program)
ctx->current_gl_program = 0;
}
}
+
+#endif /* HAVE_COGL_GLES */
}
void
blend_state->blend_dst_factor_rgb));
}
+#ifndef HAVE_COGL_GLES2
+
/* Under GLES2 the alpha function is implemented as part of the
fragment shader */
-#ifndef HAVE_COGL_GLES2
if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC |
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE))
{
GE (glAlphaFunc (alpha_state->alpha_func,
alpha_state->alpha_func_reference));
}
+
+ /* Under GLES2 the lighting parameters are implemented as uniforms
+ in the progend */
+ if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING)
+ {
+ CoglPipeline *authority =
+ _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
+ CoglPipelineLightingState *lighting_state =
+ &authority->big_state->lighting_state;
+
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT,
+ lighting_state->ambient));
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE,
+ lighting_state->diffuse));
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR,
+ lighting_state->specular));
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION,
+ lighting_state->emission));
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS,
+ &lighting_state->shininess));
+ }
+
#endif /* HAVE_COGL_GLES2 */
if (pipelines_difference & COGL_PIPELINE_STATE_DEPTH)
return FALSE;
}
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE)
+ if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
{
+ unsigned long state = COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE);
+ _cogl_pipeline_layer_get_authority (layer, state);
CoglHandle texture;
GLuint gl_texture;
GLenum gl_target;
* then we force an update of the texture state...
*/
if (unit->texture_storage_changed)
- state->layer_differences[state->i] |= COGL_PIPELINE_LAYER_STATE_TEXTURE;
+ state->layer_differences[state->i] |=
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
state->i++;
{
/* Bail out asap if we've been asked to re-flush the already current
* pipeline and we can see the pipeline hasn't changed */
- if (ctx->current_pipeline_age == pipeline->age)
+ if (ctx->current_pipeline_age == pipeline->age &&
+ ctx->current_pipeline_skip_gl_color == skip_gl_color)
goto done;
pipelines_difference = ctx->current_pipeline_changes_since_flush;
{
/* sparse state */
COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX,
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX,
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX,
COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
COGL_PIPELINE_LAYER_STATE_COUNT = COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT
} CoglPipelineLayerStateIndex;
+/* XXX: If you add or remove state groups here you may need to update
+ * some of the state masks following this enum too!
+ *
+ * FIXME: perhaps it would be better to rename this enum to
+ * CoglPipelineLayerStateGroup to better convey the fact that a single
+ * enum here can map to multiple properties.
+ */
typedef enum
{
COGL_PIPELINE_LAYER_STATE_UNIT =
1L<<COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
- COGL_PIPELINE_LAYER_STATE_TEXTURE =
- 1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX,
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET =
+ 1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX,
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA =
+ 1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX,
COGL_PIPELINE_LAYER_STATE_FILTERS =
1L<<COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
COGL_PIPELINE_LAYER_STATE_WRAP_MODES =
/* COGL_PIPELINE_LAYER_STATE_TEXTURE_INTERN = 1L<<8, */
- COGL_PIPELINE_LAYER_STATE_ALL =
- (1L<<COGL_PIPELINE_LAYER_STATE_COUNT) - 1,
-
- COGL_PIPELINE_LAYER_STATE_ALL_SPARSE =
- (1L<<COGL_PIPELINE_LAYER_STATE_COUNT) - 1,
-
- COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE =
- COGL_PIPELINE_LAYER_STATE_COMBINE |
- COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT |
- COGL_PIPELINE_LAYER_STATE_USER_MATRIX |
- COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS,
-
- COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN =
- COGL_PIPELINE_LAYER_STATE_COMBINE |
- /* FIXME: Only texture target changes should really affect the
- codegen, but this is difficult to detect */
- COGL_PIPELINE_LAYER_STATE_TEXTURE |
- /* On GLES2 we need to use a different varying for the texture
- lookups when point sprite coords are enabled */
+} CoglPipelineLayerState;
+
+/*
+ * Various special masks that tag state-groups in different ways...
+ */
+
+#define COGL_PIPELINE_LAYER_STATE_ALL \
+ ((1L<<COGL_PIPELINE_LAYER_STATE_COUNT) - 1)
+
+#define COGL_PIPELINE_LAYER_STATE_ALL_SPARSE \
+ COGL_PIPELINE_LAYER_STATE_ALL
+
+#define COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE \
+ (COGL_PIPELINE_LAYER_STATE_COMBINE | \
+ COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT | \
+ COGL_PIPELINE_LAYER_STATE_USER_MATRIX | \
+ COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS)
+
+#define COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY \
+ (COGL_PIPELINE_LAYER_STATE_FILTERS | \
+ COGL_PIPELINE_LAYER_STATE_WRAP_MODES | \
+ COGL_PIPELINE_LAYER_STATE_COMBINE)
+
+/* FIXME: Only texture target changes should really affect the
+ * codegen, but this is difficult to detect */
#ifdef HAVE_COGL_GLES2
- COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS |
+/* On GLES2 we need to use a different varying for the texture lookups
+ * when point sprite coords are enabled */
+#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
+ (COGL_PIPELINE_LAYER_STATE_COMBINE | \
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \
+ COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \
+ COGL_PIPELINE_LAYER_STATE_UNIT)
+#else
+#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
+ (COGL_PIPELINE_LAYER_STATE_COMBINE | \
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \
+ COGL_PIPELINE_LAYER_STATE_UNIT)
#endif
- COGL_PIPELINE_LAYER_STATE_UNIT,
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN = 0
+#define COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN 0
-} CoglPipelineLayerState;
typedef enum
{
/* The texture for this layer, or COGL_INVALID_HANDLE for an empty
* layer */
CoglHandle texture;
+ GLenum target;
CoglPipelineFilter mag_filter;
CoglPipelineFilter min_filter;
} CoglPipelineStateIndex;
/* Used in pipeline->differences masks and for notifying pipeline
- * state changes... */
+ * state changes.
+ *
+ * XXX: If you add or remove state groups here you may need to update
+ * some of the state masks following this enum too!
+ *
+ * FIXME: perhaps it would be better to rename this enum to
+ * CoglPipelineStateGroup to better convey the fact that a single enum
+ * here can map to multiple properties.
+ */
typedef enum _CoglPipelineState
{
COGL_PIPELINE_STATE_COLOR =
COGL_PIPELINE_STATE_REAL_BLEND_ENABLE =
1L<<COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
- COGL_PIPELINE_STATE_ALL =
- ((1L<<COGL_PIPELINE_STATE_COUNT) - 1),
-
- COGL_PIPELINE_STATE_ALL_SPARSE =
- (COGL_PIPELINE_STATE_ALL
- & ~COGL_PIPELINE_STATE_REAL_BLEND_ENABLE),
-
- COGL_PIPELINE_STATE_AFFECTS_BLENDING =
- COGL_PIPELINE_STATE_COLOR |
- COGL_PIPELINE_STATE_BLEND_ENABLE |
- COGL_PIPELINE_STATE_LAYERS |
- COGL_PIPELINE_STATE_LIGHTING |
- COGL_PIPELINE_STATE_BLEND |
- COGL_PIPELINE_STATE_USER_SHADER,
-
- COGL_PIPELINE_STATE_NEEDS_BIG_STATE =
- COGL_PIPELINE_STATE_LIGHTING |
- COGL_PIPELINE_STATE_ALPHA_FUNC |
- COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE |
- COGL_PIPELINE_STATE_BLEND |
- COGL_PIPELINE_STATE_USER_SHADER |
- COGL_PIPELINE_STATE_DEPTH |
- COGL_PIPELINE_STATE_FOG |
- COGL_PIPELINE_STATE_POINT_SIZE,
-
- COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN =
- COGL_PIPELINE_STATE_LAYERS |
+} CoglPipelineState;
+
+/*
+ * Various special masks that tag state-groups in different ways...
+ */
+
+#define COGL_PIPELINE_STATE_ALL \
+ ((1L<<COGL_PIPELINE_STATE_COUNT) - 1)
+
+#define COGL_PIPELINE_STATE_ALL_SPARSE \
+ (COGL_PIPELINE_STATE_ALL \
+ & ~COGL_PIPELINE_STATE_REAL_BLEND_ENABLE)
+
+#define COGL_PIPELINE_STATE_AFFECTS_BLENDING \
+ (COGL_PIPELINE_STATE_COLOR | \
+ COGL_PIPELINE_STATE_BLEND_ENABLE | \
+ COGL_PIPELINE_STATE_LAYERS | \
+ COGL_PIPELINE_STATE_LIGHTING | \
+ COGL_PIPELINE_STATE_BLEND | \
+ COGL_PIPELINE_STATE_USER_SHADER)
+
+#define COGL_PIPELINE_STATE_NEEDS_BIG_STATE \
+ (COGL_PIPELINE_STATE_LIGHTING | \
+ COGL_PIPELINE_STATE_ALPHA_FUNC | \
+ COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE | \
+ COGL_PIPELINE_STATE_BLEND | \
+ COGL_PIPELINE_STATE_USER_SHADER | \
+ COGL_PIPELINE_STATE_DEPTH | \
+ COGL_PIPELINE_STATE_FOG | \
+ COGL_PIPELINE_STATE_POINT_SIZE)
+
+#define COGL_PIPELINE_STATE_MULTI_PROPERTY \
+ (COGL_PIPELINE_STATE_LAYERS | \
+ COGL_PIPELINE_STATE_LIGHTING | \
+ COGL_PIPELINE_STATE_BLEND | \
+ COGL_PIPELINE_STATE_DEPTH | \
+ COGL_PIPELINE_STATE_FOG)
+
#ifdef HAVE_COGL_GLES2
/* Under GLES2 the alpha func becomes part of the fragment program
so we can't share programs there */
- COGL_PIPELINE_STATE_ALPHA_FUNC |
+#define COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN \
+ (COGL_PIPELINE_STATE_LAYERS | \
+ COGL_PIPELINE_STATE_ALPHA_FUNC | \
+ COGL_PIPELINE_STATE_USER_SHADER)
+#else
+#define COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN \
+ (COGL_PIPELINE_STATE_LAYERS | \
+ COGL_PIPELINE_STATE_USER_SHADER)
#endif
- COGL_PIPELINE_STATE_USER_SHADER,
- COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN =
- COGL_PIPELINE_STATE_LAYERS |
- COGL_PIPELINE_STATE_USER_SHADER
-
-} CoglPipelineState;
+#define COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN \
+ (COGL_PIPELINE_STATE_LAYERS | \
+ COGL_PIPELINE_STATE_USER_SHADER)
typedef enum
{
CoglPipelineLayer *layer;
} CoglPipelineLayerCacheEntry;
-/* Flags used for _cogl_pipeline_find_equivalent_parent */
-typedef enum
-{
- COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET = 1L<<0
-} CoglPipelineFindEquivalentFlags;
-
/*
* CoglPipelineDestroyCallback
* @pipeline: The #CoglPipeline that has been destroyed
* semantics */
typedef enum _CoglPipelineEvalFlags
{
- /* When evaluating a pipeline-layer with associated textures then
- * evaluate the texture target, but don't consider the texture data
- * itself. */
- COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA = 1L<<0
+ COGL_PIPELINE_EVAL_FLAG_NONE = 0
} CoglPipelineEvalFlags;
gboolean
CoglPipeline *
_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
CoglPipelineState pipeline_state,
- CoglPipelineLayerState layer_state,
- CoglPipelineFindEquivalentFlags flags);
+ CoglPipelineLayerState layer_state);
CoglHandle
_cogl_pipeline_get_layer_texture (CoglPipeline *pipeline,
CoglHandle
_cogl_pipeline_layer_get_texture (CoglPipelineLayer *layer);
+CoglHandle
+_cogl_pipeline_layer_get_texture_real (CoglPipelineLayer *layer);
+
CoglPipelineFilter
_cogl_pipeline_layer_get_min_filter (CoglPipelineLayer *layer);
#define __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H
#include "cogl-pipeline-private.h"
-#include "cogl-vertex-attribute-private.h"
+#include "cogl-attribute-private.h"
extern const CoglPipelineProgend _cogl_pipeline_glsl_progend;
#define glUniform1f ctx->drv.pf_glUniform1f
#define glUniform4fv ctx->drv.pf_glUniform4fv
+#else
+
+/* These are used to generalise updating some uniforms that are
+ required when building for GLES2 */
+
+typedef void (* UpdateUniformFunc) (CoglPipeline *pipeline,
+ int uniform_location,
+ void *getter_func);
+
+static void update_float_uniform (CoglPipeline *pipeline,
+ int uniform_location,
+ void *getter_func);
+
+typedef struct
+{
+ const char *uniform_name;
+ void *getter_func;
+ UpdateUniformFunc update_func;
+ CoglPipelineState change;
+} BuiltinUniformData;
+
+static BuiltinUniformData builtin_uniforms[] =
+ {
+ { "cogl_point_size_in",
+ cogl_pipeline_get_point_size, update_float_uniform,
+ COGL_PIPELINE_STATE_POINT_SIZE },
+ { "_cogl_alpha_test_ref",
+ cogl_pipeline_get_alpha_test_reference, update_float_uniform,
+ COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE }
+ };
+
#endif /* HAVE_COGL_GLES2 */
const CoglPipelineProgend _cogl_pipeline_glsl_progend;
int n_tex_coord_attribs;
#ifdef HAVE_COGL_GLES2
- /* Under GLES2 the alpha test is implemented in the shader. We need
- a uniform for the reference value */
- gboolean dirty_alpha_test_reference;
- GLint alpha_test_reference_uniform;
-
- gboolean dirty_point_size;
- GLint point_size_uniform;
+ unsigned long dirty_builtin_uniforms;
+ GLint builtin_uniform_locations[G_N_ELEMENTS (builtin_uniforms)];
/* Under GLES2 we can't use the builtin functions to set attribute
pointers such as the vertex position. Instead the vertex
#ifdef HAVE_COGL_GLES2
static void
-update_alpha_test_reference (CoglPipeline *pipeline,
- GLuint gl_program,
- CoglPipelineProgendPrivate *priv)
+update_builtin_uniforms (CoglPipeline *pipeline,
+ GLuint gl_program,
+ CoglPipelineProgendPrivate *priv)
{
- float alpha_reference;
-
- if (priv->dirty_alpha_test_reference &&
- priv->alpha_test_reference_uniform != -1)
- {
- alpha_reference = cogl_pipeline_get_alpha_test_reference (pipeline);
-
- GE( glUniform1f (priv->alpha_test_reference_uniform,
- alpha_reference) );
+ int i;
- priv->dirty_alpha_test_reference = FALSE;
- }
-}
-
-static void
-update_point_size (CoglPipeline *pipeline,
- GLuint gl_program,
- CoglPipelineProgendPrivate *priv)
-{
- if (priv->dirty_point_size && priv->point_size_uniform != -1)
- {
- float point_size = cogl_pipeline_get_point_size (pipeline);
+ if (priv->dirty_builtin_uniforms == 0)
+ return;
- GE( glUniform1f (priv->point_size_uniform, point_size) );
+ for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
+ if ((priv->dirty_builtin_uniforms & (1 << i)) &&
+ priv->builtin_uniform_locations[i] != -1)
+ builtin_uniforms[i].update_func (pipeline,
+ priv->builtin_uniform_locations[i],
+ builtin_uniforms[i].getter_func);
- priv->dirty_point_size = FALSE;
- }
+ priv->dirty_builtin_uniforms = 0;
}
#endif /* HAVE_COGL_GLES2 */
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN) &
~COGL_PIPELINE_STATE_LAYERS,
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN |
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN,
- COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET);
+ COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);
priv = get_glsl_priv (authority);
#ifdef HAVE_COGL_GLES2
if (program_changed)
{
+ int i;
+
clear_attribute_cache (priv);
clear_flushed_matrix_stacks (priv);
- GE_RET( priv->alpha_test_reference_uniform,
- glGetUniformLocation (gl_program,
- "_cogl_alpha_test_ref") );
+ for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
+ GE_RET( priv->builtin_uniform_locations[i],
+ glGetUniformLocation (gl_program,
+ builtin_uniforms[i].uniform_name) );
GE_RET( priv->modelview_uniform,
glGetUniformLocation (gl_program,
GE_RET( priv->mvp_uniform,
glGetUniformLocation (gl_program,
"cogl_modelview_projection_matrix") );
-
- GE_RET( priv->point_size_uniform,
- glGetUniformLocation (gl_program,
- "cogl_point_size_in") );
}
if (program_changed ||
priv->last_used_for_pipeline != pipeline)
- {
- priv->dirty_alpha_test_reference = TRUE;
- priv->dirty_point_size = TRUE;
- }
+ priv->dirty_builtin_uniforms = ~(unsigned long) 0;
- update_alpha_test_reference (pipeline, gl_program, priv);
- update_point_size (pipeline, gl_program, priv);
+ update_builtin_uniforms (pipeline, gl_program, priv);
#endif
if (user_program)
if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN))
dirty_glsl_program_state (pipeline);
#ifdef HAVE_COGL_GLES2
- else if ((change & COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE))
- {
- CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
- if (priv)
- priv->dirty_alpha_test_reference = TRUE;
- }
- else if ((change & COGL_PIPELINE_STATE_POINT_SIZE))
+ else
{
- CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
- if (priv)
- priv->dirty_point_size = TRUE;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
+ if ((change & builtin_uniforms[i].change))
+ {
+ CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
+ if (priv)
+ priv->dirty_builtin_uniforms |= 1 << i;
+ return;
+ }
}
#endif /* HAVE_COGL_GLES2 */
}
priv);
}
+static void
+update_float_uniform (CoglPipeline *pipeline,
+ int uniform_location,
+ void *getter_func)
+{
+ float (* float_getter_func) (CoglPipeline *) = getter_func;
+ float value;
+
+ value = float_getter_func (pipeline);
+ GE( glUniform1f (uniform_location, value) );
+}
+
#endif
const CoglPipelineProgend _cogl_pipeline_glsl_progend =
{
CoglProgram *user_program;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_FIXED))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
return FALSE;
/* If there is a user program with a vertex shader then the
_cogl_matrix_stack_set (unit->matrix_stack,
&authority->big_state->matrix);
+ _cogl_set_active_texture_unit (unit_index);
+
_cogl_matrix_stack_flush_to_gl (unit->matrix_stack, COGL_MATRIX_TEXTURE);
}
{
_COGL_GET_CONTEXT (ctx, FALSE);
- if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING)
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
- CoglPipelineLightingState *lighting_state =
- &authority->big_state->lighting_state;
-
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT,
- lighting_state->ambient));
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE,
- lighting_state->diffuse));
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR,
- lighting_state->specular));
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION,
- lighting_state->emission));
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS,
- &lighting_state->shininess));
- }
-
if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE)
{
CoglPipeline *authority =
(pipeline,
COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN &
~COGL_PIPELINE_STATE_LAYERS,
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN,
- 0);
+ COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);
priv = get_glsl_priv (authority);
_cogl_matrix_stack_set (unit->matrix_stack,
&authority->big_state->matrix);
+ _cogl_set_active_texture_unit (unit_index);
+
_cogl_matrix_stack_flush_to_gl (unit->matrix_stack, COGL_MATRIX_TEXTURE);
}
*/
tex_authority =
_cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE);
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
if (tex_authority->texture &&
cogl_texture_get_format (tex_authority->texture) & COGL_A_BIT)
{
CoglPipelineBlendEnable enabled;
unsigned long other_state;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_BLENDING))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BLENDING)))
return FALSE;
enable_authority =
}
static void
-_cogl_pipeline_initialize_sparse_state (CoglPipeline *dest,
- CoglPipeline *src,
- CoglPipelineState state)
+_cogl_pipeline_init_multi_property_sparse_state (CoglPipeline *pipeline,
+ CoglPipelineState change)
{
- if (dest == src)
+ CoglPipeline *authority;
+
+ g_return_if_fail (change & COGL_PIPELINE_STATE_ALL_SPARSE);
+
+ if (!(change & COGL_PIPELINE_STATE_MULTI_PROPERTY))
return;
- g_return_if_fail (state & COGL_PIPELINE_STATE_ALL_SPARSE);
+ authority = _cogl_pipeline_get_authority (pipeline, change);
- if (state != COGL_PIPELINE_STATE_LAYERS)
- _cogl_pipeline_copy_differences (dest, src, state);
- else
+ switch (change)
{
- dest->n_layers = src->n_layers;
- dest->layer_differences = NULL;
+ /* XXX: avoid using a default: label so we get a warning if we
+ * don't explicitly handle a newly defined state-group here. */
+ case COGL_PIPELINE_STATE_COLOR:
+ case COGL_PIPELINE_STATE_BLEND_ENABLE:
+ case COGL_PIPELINE_STATE_ALPHA_FUNC:
+ case COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE:
+ case COGL_PIPELINE_STATE_POINT_SIZE:
+ case COGL_PIPELINE_STATE_USER_SHADER:
+ case COGL_PIPELINE_STATE_REAL_BLEND_ENABLE:
+ g_return_if_reached ();
+
+ case COGL_PIPELINE_STATE_LAYERS:
+ pipeline->n_layers = authority->n_layers;
+ pipeline->layer_differences = NULL;
+ break;
+ case COGL_PIPELINE_STATE_LIGHTING:
+ {
+ memcpy (&pipeline->big_state->lighting_state,
+ &authority->big_state->lighting_state,
+ sizeof (CoglPipelineLightingState));
+ break;
+ }
+ case COGL_PIPELINE_STATE_BLEND:
+ {
+ memcpy (&pipeline->big_state->blend_state,
+ &authority->big_state->blend_state,
+ sizeof (CoglPipelineBlendState));
+ break;
+ }
+ case COGL_PIPELINE_STATE_DEPTH:
+ {
+ memcpy (&pipeline->big_state->depth_state,
+ &authority->big_state->depth_state,
+ sizeof (CoglPipelineDepthState));
+ break;
+ }
+ case COGL_PIPELINE_STATE_FOG:
+ {
+ memcpy (&pipeline->big_state->fog_state,
+ &authority->big_state->fog_state,
+ sizeof (CoglPipelineFogState));
+ break;
+ }
}
}
const CoglColor *new_color,
gboolean from_layer_change)
{
- CoglPipeline *authority;
int i;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
}
if (!skip_journal_flush)
- _cogl_journal_flush ();
+ {
+ /* XXX: note we use cogl_flush() not _cogl_flush_journal() so
+ * we will flush *all* known journals that might reference the
+ * current pipeline. */
+ cogl_flush ();
+ }
}
/* The fixed function backend has no private state and can't
pipeline->age++;
- /* If changing a sparse property and if the pipeline isn't already an
- * authority for the state group being modified then we need to
- * initialize the corresponding state. */
+ if (change & COGL_PIPELINE_STATE_NEEDS_BIG_STATE &&
+ !pipeline->has_big_state)
+ {
+ pipeline->big_state = g_slice_new (CoglPipelineBigState);
+ pipeline->has_big_state = TRUE;
+ }
+
+ /* Note: conceptually we have just been notified that a single
+ * property value is about to change, but since some state-groups
+ * contain multiple properties and 'pipeline' is about to take over
+ * being the authority for the property's corresponding state-group
+ * we need to maintain the integrity of the other property values
+ * too.
+ *
+ * To ensure this we handle multi-property state-groups by copying
+ * all the values from the old-authority to the new...
+ *
+ * We don't have to worry about non-sparse property groups since
+ * we never take over being an authority for such properties so
+ * they automatically maintain integrity.
+ */
if (change & COGL_PIPELINE_STATE_ALL_SPARSE &&
!(pipeline->differences & change))
{
- authority = _cogl_pipeline_get_authority (pipeline, change);
- _cogl_pipeline_initialize_sparse_state (pipeline, authority, change);
+ _cogl_pipeline_init_multi_property_sparse_state (pipeline, change);
+ pipeline->differences |= change;
}
/* Each pipeline has a sorted cache of the layers it depends on
}
static void
-_cogl_pipeline_layer_initialize_state (CoglPipelineLayer *dest,
- CoglPipelineLayer *src,
- unsigned long differences)
+_cogl_pipeline_layer_init_multi_property_sparse_state (
+ CoglPipelineLayer *layer,
+ CoglPipelineLayerState change)
{
- CoglPipelineLayerBigState *big_state;
-
- dest->differences |= differences;
-
- if (differences & COGL_PIPELINE_LAYER_STATE_UNIT)
- dest->unit_index = src->unit_index;
-
- if (differences & COGL_PIPELINE_LAYER_STATE_TEXTURE)
- dest->texture = src->texture;
-
- if (differences & COGL_PIPELINE_LAYER_STATE_FILTERS)
- {
- dest->min_filter = src->min_filter;
- dest->mag_filter = src->mag_filter;
- }
-
- if (differences & COGL_PIPELINE_LAYER_STATE_WRAP_MODES)
- {
- dest->wrap_mode_s = src->wrap_mode_s;
- dest->wrap_mode_t = src->wrap_mode_t;
- dest->wrap_mode_p = src->wrap_mode_p;
- }
+ CoglPipelineLayer *authority;
- if (differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE)
- {
- if (!dest->has_big_state)
- {
- dest->big_state = g_slice_new (CoglPipelineLayerBigState);
- dest->has_big_state = TRUE;
- }
- big_state = dest->big_state;
- }
- else
+ /* Nothing to initialize in these cases since they are all comprised
+ * of one member which we expect to immediately be overwritten. */
+ if (!(change & COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY))
return;
- if (differences & COGL_PIPELINE_LAYER_STATE_COMBINE)
- {
- int n_args;
- int i;
- GLint func = src->big_state->texture_combine_rgb_func;
- big_state->texture_combine_rgb_func = func;
- n_args = _cogl_get_n_args_for_combine_func (func);
- for (i = 0; i < n_args; i++)
- {
- big_state->texture_combine_rgb_src[i] =
- src->big_state->texture_combine_rgb_src[i];
- big_state->texture_combine_rgb_op[i] =
- src->big_state->texture_combine_rgb_op[i];
- }
+ authority = _cogl_pipeline_layer_get_authority (layer, change);
- func = src->big_state->texture_combine_alpha_func;
- big_state->texture_combine_alpha_func = func;
- n_args = _cogl_get_n_args_for_combine_func (func);
- for (i = 0; i < n_args; i++)
- {
- big_state->texture_combine_alpha_src[i] =
- src->big_state->texture_combine_alpha_src[i];
- big_state->texture_combine_alpha_op[i] =
- src->big_state->texture_combine_alpha_op[i];
- }
+ switch (change)
+ {
+ /* XXX: avoid using a default: label so we get a warning if we
+ * don't explicitly handle a newly defined state-group here. */
+ case COGL_PIPELINE_LAYER_STATE_UNIT:
+ case COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET:
+ case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA:
+ case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS:
+ case COGL_PIPELINE_LAYER_STATE_USER_MATRIX:
+ case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT:
+ g_return_if_reached ();
+
+ /* XXX: technically we could probably even consider these as
+ * single property state-groups from the pov that currently the
+ * corresponding property setters always update all of the values
+ * at the same time. */
+ case COGL_PIPELINE_LAYER_STATE_FILTERS:
+ layer->min_filter = authority->min_filter;
+ layer->mag_filter = authority->mag_filter;
+ break;
+ case COGL_PIPELINE_LAYER_STATE_WRAP_MODES:
+ layer->wrap_mode_s = authority->wrap_mode_s;
+ layer->wrap_mode_t = authority->wrap_mode_t;
+ layer->wrap_mode_p = authority->wrap_mode_p;
+ break;
+ case COGL_PIPELINE_LAYER_STATE_COMBINE:
+ {
+ int n_args;
+ int i;
+ CoglPipelineLayerBigState *src_big_state = authority->big_state;
+ CoglPipelineLayerBigState *dest_big_state = layer->big_state;
+ GLint func = src_big_state->texture_combine_rgb_func;
+
+ dest_big_state->texture_combine_rgb_func = func;
+ n_args = _cogl_get_n_args_for_combine_func (func);
+ for (i = 0; i < n_args; i++)
+ {
+ dest_big_state->texture_combine_rgb_src[i] =
+ src_big_state->texture_combine_rgb_src[i];
+ dest_big_state->texture_combine_rgb_op[i] =
+ src_big_state->texture_combine_rgb_op[i];
+ }
+
+ func = src_big_state->texture_combine_alpha_func;
+ dest_big_state->texture_combine_alpha_func = func;
+ n_args = _cogl_get_n_args_for_combine_func (func);
+ for (i = 0; i < n_args; i++)
+ {
+ dest_big_state->texture_combine_alpha_src[i] =
+ src_big_state->texture_combine_alpha_src[i];
+ dest_big_state->texture_combine_alpha_op[i] =
+ src_big_state->texture_combine_alpha_op[i];
+ }
+ break;
+ }
}
-
- if (differences & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT)
- memcpy (dest->big_state->texture_combine_constant,
- src->big_state->texture_combine_constant,
- sizeof (float) * 4);
-
- if (differences & COGL_PIPELINE_LAYER_STATE_USER_MATRIX)
- dest->big_state->matrix = src->big_state->matrix;
-
- if (differences & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS)
- dest->big_state->point_sprite_coords = src->big_state->point_sprite_coords;
}
/* NB: This function will allocate a new derived layer if you are
CoglPipelineLayerState change)
{
CoglTextureUnit *unit;
- CoglPipelineLayer *authority;
/* Identify the case where the layer is new with no owner or
* dependants and so we don't need to do anything. */
if (required_owner)
required_owner->age++;
- /* If the pipeline isn't already an authority for the state group
- * being modified then we need to initialize the corresponding
- * state. */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
- _cogl_pipeline_layer_initialize_state (layer, authority, change);
+ if (change & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE &&
+ !layer->has_big_state)
+ {
+ layer->big_state = g_slice_new (CoglPipelineLayerBigState);
+ layer->has_big_state = TRUE;
+ }
+
+ /* Note: conceptually we have just been notified that a single
+ * property value is about to change, but since some state-groups
+ * contain multiple properties and 'layer' is about to take over
+ * being the authority for the property's corresponding state-group
+ * we need to maintain the integrity of the other property values
+ * too.
+ *
+ * To ensure this we handle multi-property state-groups by copying
+ * all the values from the old-authority to the new...
+ *
+ * We don't have to worry about non-sparse property groups since
+ * we never take over being an authority for such properties so
+ * they automatically maintain integrity.
+ */
+ if (change & COGL_PIPELINE_LAYER_STATE_ALL_SPARSE &&
+ !(layer->differences & change))
+ {
+ _cogl_pipeline_layer_init_multi_property_sparse_state (layer, change);
+ layer->differences |= change;
+ }
return layer;
}
{
CoglPipelineLayer *authority =
_cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE);
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
return authority->texture;
}
}
}
-void
-cogl_pipeline_set_layer_texture (CoglPipeline *pipeline,
- int layer_index,
- CoglHandle texture)
+static void
+_cogl_pipeline_set_layer_texture_target (CoglPipeline *pipeline,
+ int layer_index,
+ GLenum target)
{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE;
+ CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET;
+ CoglPipelineLayer *layer;
+ CoglPipelineLayer *authority;
+ CoglPipelineLayer *new;
+
+ /* Note: this will ensure that the layer exists, creating one if it
+ * doesn't already.
+ *
+ * Note: If the layer already existed it's possibly owned by another
+ * pipeline. If the layer is created then it will be owned by
+ * pipeline. */
+ layer = _cogl_pipeline_get_layer (pipeline, layer_index);
+
+ /* Now find the ancestor of the layer that is the authority for the
+ * state we want to change */
+ authority = _cogl_pipeline_layer_get_authority (layer, change);
+
+ if (target == authority->target)
+ return;
+
+ new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
+ if (new != layer)
+ layer = new;
+ else
+ {
+ /* If the original layer we found is currently the authority on
+ * the state we are changing see if we can revert to one of our
+ * ancestors being the authority. */
+ if (layer == authority &&
+ _cogl_pipeline_layer_get_parent (authority) != NULL)
+ {
+ CoglPipelineLayer *parent =
+ _cogl_pipeline_layer_get_parent (authority);
+ CoglPipelineLayer *old_authority =
+ _cogl_pipeline_layer_get_authority (parent, change);
+
+ if (old_authority->target == target)
+ {
+ layer->differences &= ~change;
+
+ g_assert (layer->owner == pipeline);
+ if (layer->differences == 0)
+ _cogl_pipeline_prune_empty_layer_difference (pipeline,
+ layer);
+ goto changed;
+ }
+ }
+ }
+
+ layer->target = target;
+
+ /* If we weren't previously the authority on this state then we need
+ * to extended our differences mask and so it's possible that some
+ * of our ancestry will now become redundant, so we aim to reparent
+ * ourselves if that's true... */
+ if (layer != authority)
+ {
+ layer->differences |= change;
+ _cogl_pipeline_layer_prune_redundant_ancestry (layer);
+ }
+
+changed:
+
+ handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
+}
+
+static void
+_cogl_pipeline_set_layer_texture_data (CoglPipeline *pipeline,
+ int layer_index,
+ CoglHandle texture)
+{
+ CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
CoglPipelineLayer *layer;
CoglPipelineLayer *authority;
CoglPipelineLayer *new;
handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
}
+/* A convenience for querying the target of a given texture that
+ * notably returns 0 for NULL textures - so we can say that a layer
+ * with no associated CoglTexture will have a texture target of 0.
+ */
+static GLenum
+get_texture_target (CoglHandle texture)
+{
+ GLuint ignore_handle;
+ GLenum gl_target;
+
+ if (texture)
+ cogl_texture_get_gl_texture (texture, &ignore_handle, &gl_target);
+ else
+ return 0;/* XXX: An invalid GL target enum */
+
+ return gl_target;
+}
+
+void
+cogl_pipeline_set_layer_texture (CoglPipeline *pipeline,
+ int layer_index,
+ CoglHandle texture)
+{
+ /* For the convenience of fragend code we separate texture state
+ * into the "target" and the "data", and setting a layer texture
+ * updates both of these properties.
+ *
+ * One example for why this is helpful is that the fragends may
+ * cache programs they generate and want to re-use those programs
+ * with all pipelines having equivalent fragment processing state.
+ * For the sake of determining if pipelines have equivalent fragment
+ * processing state we don't need to compare that the same
+ * underlying texture objects are referenced by the pipelines but we
+ * do need to see if they use the same texture targets. Making this
+ * distinction is much simpler if they are in different state
+ * groups.
+ */
+ _cogl_pipeline_set_layer_texture_target (pipeline, layer_index,
+ get_texture_target (texture));
+ _cogl_pipeline_set_layer_texture_data (pipeline, layer_index, texture);
+}
+
typedef struct
{
int i;
}
static gboolean
-_cogl_pipeline_layer_texture_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1,
- CoglPipelineEvalFlags flags)
+_cogl_pipeline_layer_texture_target_equal (CoglPipelineLayer *authority0,
+ CoglPipelineLayer *authority1,
+ CoglPipelineEvalFlags flags)
+{
+ return authority0->target == authority1->target;
+}
+
+static gboolean
+_cogl_pipeline_layer_texture_data_equal (CoglPipelineLayer *authority0,
+ CoglPipelineLayer *authority1,
+ CoglPipelineEvalFlags flags)
{
GLuint gl_handle0, gl_handle1;
- GLenum gl_target0, gl_target1;
- cogl_texture_get_gl_texture (authority0->texture, &gl_handle0, &gl_target0);
- cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, &gl_target1);
+ cogl_texture_get_gl_texture (authority0->texture, &gl_handle0, NULL);
+ cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, NULL);
- if (flags & COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA)
- return (gl_target0 == gl_target1);
- else
- return (gl_handle0 == gl_handle1 && gl_target0 == gl_target1);
+ return gl_handle0 == gl_handle1;
}
/* Determine the mask of differences between two layers.
layers_difference,
authorities1);
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE)
+ if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET)
{
CoglPipelineLayerStateIndex state_index =
- COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX;
- if (!_cogl_pipeline_layer_texture_equal (authorities0[state_index],
- authorities1[state_index],
- flags))
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX;
+ if (!_cogl_pipeline_layer_texture_target_equal (authorities0[state_index],
+ authorities1[state_index],
+ flags))
+ return FALSE;
+ }
+
+ if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
+ {
+ CoglPipelineLayerStateIndex state_index =
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX;
+ if (!_cogl_pipeline_layer_texture_data_equal (authorities0[state_index],
+ authorities1[state_index],
+ flags))
return FALSE;
}
{
_cogl_pipeline_layer_unparent (COGL_PIPELINE_NODE (layer));
- if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE &&
+ if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA &&
layer->texture != COGL_INVALID_HANDLE)
cogl_handle_unref (layer->texture);
layer->unit_index = 0;
layer->texture = COGL_INVALID_HANDLE;
+ layer->target = 0;
layer->mag_filter = COGL_PIPELINE_FILTER_LINEAR;
layer->min_filter = COGL_PIPELINE_FILTER_LINEAR;
CoglPipelineLayer *layer;
CoglPipelineLayer *authority;
CoglPipelineLayer *new;
+ float color_as_floats[4];
g_return_if_fail (cogl_is_pipeline (pipeline));
* state we want to change */
authority = _cogl_pipeline_layer_get_authority (layer, state);
+ color_as_floats[0] = cogl_color_get_red_float (constant_color);
+ color_as_floats[1] = cogl_color_get_green_float (constant_color);
+ color_as_floats[2] = cogl_color_get_blue_float (constant_color);
+ color_as_floats[3] = cogl_color_get_alpha_float (constant_color);
+
if (memcmp (authority->big_state->texture_combine_constant,
- constant_color, sizeof (float) * 4) == 0)
+ color_as_floats, sizeof (float) * 4) == 0)
return;
new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, state);
CoglPipelineLayerBigState *old_big_state = old_authority->big_state;
if (memcmp (old_big_state->texture_combine_constant,
- constant_color, sizeof (float) * 4) == 0)
+ color_as_floats, sizeof (float) * 4) == 0)
{
layer->differences &= ~state;
}
}
- layer->big_state->texture_combine_constant[0] =
- cogl_color_get_red_float (constant_color);
- layer->big_state->texture_combine_constant[1] =
- cogl_color_get_green_float (constant_color);
- layer->big_state->texture_combine_constant[2] =
- cogl_color_get_blue_float (constant_color);
- layer->big_state->texture_combine_constant[3] =
- cogl_color_get_alpha_float (constant_color);
+ memcpy (layer->big_state->texture_combine_constant,
+ color_as_floats,
+ sizeof (color_as_floats));
/* If we weren't previously the authority on this state then we need
* to extended our differences mask and so it's possible that some
texture_authority =
_cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE);
+ COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
if (texture_authority->texture != COGL_INVALID_HANDLE)
{
}
static void
-_cogl_pipeline_layer_hash_texture_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
+_cogl_pipeline_layer_hash_texture_target_state (CoglPipelineLayer *authority,
+ CoglPipelineLayer **authorities,
+ HashState *state)
{
- GLuint gl_handle;
- GLenum gl_target;
- unsigned long hash = state->hash;
+ GLenum gl_target = authority->target;
- cogl_texture_get_gl_texture (authority->texture, &gl_handle, &gl_target);
+ state->hash =
+ _cogl_util_one_at_a_time_hash (state->hash, &gl_target, sizeof (gl_target));
+}
- hash = _cogl_util_one_at_a_time_hash (hash, &gl_target, sizeof (gl_target));
+static void
+_cogl_pipeline_layer_hash_texture_data_state (CoglPipelineLayer *authority,
+ CoglPipelineLayer **authorities,
+ HashState *state)
+{
+ GLuint gl_handle;
- if (!(state->flags & COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA))
- hash = _cogl_util_one_at_a_time_hash (hash, &gl_handle, sizeof (gl_handle));
+ cogl_texture_get_gl_texture (authority->texture, &gl_handle, NULL);
- state->hash = hash;
+ state->hash =
+ _cogl_util_one_at_a_time_hash (state->hash, &gl_handle, sizeof (gl_handle));
}
static void
n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_rgb_func);
for (i = 0; i < n_args; i++)
{
- if (b->texture_combine_rgb_src[i] == GL_CONSTANT_COLOR ||
- b->texture_combine_rgb_src[i] == GL_CONSTANT_ALPHA)
+ if (b->texture_combine_rgb_src[i] ==
+ COGL_PIPELINE_COMBINE_SOURCE_CONSTANT)
{
/* XXX: should we be careful to only hash the alpha
- * component in the GL_CONSTANT_ALPHA case? */
+ * component in the COGL_PIPELINE_COMBINE_OP_SRC_ALPHA case? */
need_hash = TRUE;
goto done;
}
n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_alpha_func);
for (i = 0; i < n_args; i++)
{
- if (b->texture_combine_alpha_src[i] == GL_CONSTANT_COLOR ||
- b->texture_combine_alpha_src[i] == GL_CONSTANT_ALPHA)
+ if (b->texture_combine_alpha_src[i] ==
+ COGL_PIPELINE_COMBINE_SOURCE_CONSTANT)
{
/* XXX: should we be careful to only hash the alpha
- * component in the GL_CONSTANT_ALPHA case? */
+ * component in the COGL_PIPELINE_COMBINE_OP_SRC_ALPHA case? */
need_hash = TRUE;
goto done;
}
CoglPipelineLayerStateIndex _index;
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_UNIT_INDEX] =
_cogl_pipeline_layer_hash_unit_state;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX] =
- _cogl_pipeline_layer_hash_texture_state;
+ layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX] =
+ _cogl_pipeline_layer_hash_texture_target_state;
+ layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX] =
+ _cogl_pipeline_layer_hash_texture_data_state;
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX] =
_cogl_pipeline_layer_hash_filters_state;
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX] =
_cogl_pipeline_layer_hash_point_sprite_state;
/* So we get a big error if we forget to update this code! */
- g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 8);
+ g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 9);
}
static gboolean
layer->unit_index);
}
- if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE)
+ if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
{
changes = TRUE;
g_string_append_printf (changes_label,
return FALSE;
}
-static gboolean
-layers_differ_for_find_equivalent (CoglPipelineLayerState layer_state,
- CoglPipelineFindEquivalentFlags flags,
- CoglPipelineLayer *layer0,
- CoglPipelineLayer *layer1)
-{
- unsigned long layer_differences;
-
- if (layer0 == layer1)
- return FALSE;
-
- layer_differences =
- _cogl_pipeline_layer_compare_differences (layer0, layer1);
-
- if (layer_differences & layer_state)
- return TRUE;
-
- /* When generating a shader we need to detect when the texture
- target changes but we don't care if the texture object
- changes so we have a flag to handle this special case */
- if ((flags & COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET) &&
- (layer_differences & COGL_PIPELINE_LAYER_STATE_TEXTURE))
- {
- CoglHandle tex0 = _cogl_pipeline_layer_get_texture (layer0);
- CoglHandle tex1 = _cogl_pipeline_layer_get_texture (layer1);
- GLenum gl_target0;
- GLenum gl_target1;
-
- cogl_texture_get_gl_texture (tex0, NULL, &gl_target0);
- cogl_texture_get_gl_texture (tex1, NULL, &gl_target1);
- if (gl_target0 != gl_target1)
- return TRUE;
- }
-
- return FALSE;
-}
-
/* This tries to find the oldest ancestor whose pipeline and layer
state matches the given flags. This is mostly used to detect code
gen authorities so that we can reduce the numer of programs
CoglPipeline *
_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
CoglPipelineState pipeline_state,
- CoglPipelineLayerState layer_state,
- CoglPipelineFindEquivalentFlags flags)
+ CoglPipelineLayerState layer_state)
{
CoglPipeline *authority0;
CoglPipeline *authority1;
&state);
for (i = 0; i < n_layers; i++)
- if (layers_differ_for_find_equivalent (layer_state, flags,
- authority0_layers[i],
- authority1_layers[i]))
- return authority0;
+ {
+ unsigned long layer_differences;
+
+ if (authority0_layers[i] == authority1_layers[i])
+ continue;
+
+ layer_differences =
+ _cogl_pipeline_layer_compare_differences (authority0_layers[i],
+ authority1_layers[i]);
+
+ if (layer_differences & layer_state)
+ return authority0;
+ }
/* Find the next ancestor after that, that also modifies state
* affecting codegen... */
--- /dev/null
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * 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/>.
+ */
+
+#ifndef __COGL_POINT_INT_POLYGON_PRIVATE_H
+#define __COGL_POINT_INT_POLYGON_PRIVATE_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+int
+_cogl_util_point_in_poly (float point_x,
+ float point_y,
+ void *vertices,
+ size_t stride,
+ int n_vertices);
+
+G_END_DECLS
+
+#endif /* __COGL_POINT_INT_POLYGON_PRIVATE_H */
+
--- /dev/null
+/*
+ * Point Inclusion in Polygon Test
+ *
+ * Copyright (c) 1970-2003, Wm. Randolph Franklin
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimers.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice in the documentation and/or other materials
+ * provided with the distribution.
+ * 3. The name of W. Randolph Franklin may not be used to endorse or
+ * promote products derived from this Software without specific
+ * prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Note:
+ * The algorithm for this point_in_poly() function was learnt from:
+ * http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+
+int
+_cogl_util_point_in_poly (float point_x,
+ float point_y,
+ void *vertices,
+ size_t stride,
+ int n_vertices)
+{
+ int i, j, c = 0;
+
+ for (i = 0, j = n_vertices - 1; i < n_vertices; j = i++)
+ {
+ float vert_xi = *(float *)((guint8 *)vertices + i * stride);
+ float vert_xj = *(float *)((guint8 *)vertices + j * stride);
+ float vert_yi = *(float *)((guint8 *)vertices + i * stride +
+ sizeof (float));
+ float vert_yj = *(float *)((guint8 *)vertices + j * stride +
+ sizeof (float));
+
+ if (((vert_yi > point_y) != (vert_yj > point_y)) &&
+ (point_x < (vert_xj - vert_xi) * (point_y - vert_yi) /
+ (vert_yj - vert_yi) + vert_xi) )
+ c = !c;
+ }
+
+ return c;
+}
+
#include "cogl-object-private.h"
#include "cogl-primitive.h"
#include "cogl-primitive-private.h"
-#include "cogl-vertex-attribute-private.h"
+#include "cogl-attribute-private.h"
#include <stdarg.h>
CoglPrimitive *
cogl_primitive_new_with_attributes_array (CoglVerticesMode mode,
int n_vertices,
- CoglVertexAttribute **attributes)
+ CoglAttribute **attributes)
{
CoglPrimitive *primitive = g_slice_new (CoglPrimitive);
int i;
primitive->n_vertices = n_vertices;
primitive->indices = NULL;
primitive->attributes =
- g_array_new (TRUE, FALSE, sizeof (CoglVertexAttribute *));
+ g_array_new (TRUE, FALSE, sizeof (CoglAttribute *));
primitive->immutable_ref = 0;
for (i = 0; attributes[i]; i++)
{
- CoglVertexAttribute *attribute = attributes[i];
+ CoglAttribute *attribute = attributes[i];
cogl_object_ref (attribute);
- g_return_val_if_fail (cogl_is_vertex_attribute (attribute), NULL);
+ g_return_val_if_fail (cogl_is_attribute (attribute), NULL);
g_array_append_val (primitive->attributes, attribute);
}
new_with_attributes that also unrefs the attributes. It is just
used for the builtin struct constructors */
static CoglPrimitive *
-_cogl_primitive_new_with_attributes_array_unref
- (CoglVerticesMode mode,
- int n_vertices,
- CoglVertexAttribute **attributes)
+_cogl_primitive_new_with_attributes_array_unref (CoglVerticesMode mode,
+ int n_vertices,
+ CoglAttribute **attributes)
{
CoglPrimitive *primitive;
int i;
{
va_list ap;
int n_attributes;
- CoglVertexAttribute **attributes;
+ CoglAttribute **attributes;
int i;
- CoglVertexAttribute *attribute;
+ CoglAttribute *attribute;
va_start (ap, n_vertices);
- for (n_attributes = 0; va_arg (ap, CoglVertexAttribute *); n_attributes++)
+ for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++)
;
va_end (ap);
- attributes = g_alloca (sizeof (CoglVertexAttribute *) * (n_attributes + 1));
+ attributes = g_alloca (sizeof (CoglAttribute *) * (n_attributes + 1));
attributes[n_attributes] = NULL;
va_start (ap, n_vertices);
- for (i = 0; (attribute = va_arg (ap, CoglVertexAttribute *)); i++)
+ for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++)
attributes[i] = attribute;
va_end (ap);
CoglPrimitive *
cogl_primitive_new_p2 (CoglVerticesMode mode,
int n_vertices,
- const CoglP2Vertex *data)
+ const CoglVertexP2 *data)
{
CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglP2Vertex), data);
- CoglVertexAttribute *attributes[2];
-
- attributes[0] =
- cogl_vertex_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglP2Vertex),
- offsetof (CoglP2Vertex, x),
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP2), data);
+ CoglAttribute *attributes[2];
+
+ attributes[0] = cogl_attribute_new (array,
+ "cogl_position_in",
+ sizeof (CoglVertexP2),
+ offsetof (CoglVertexP2, x),
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
attributes[1] = NULL;
cogl_object_unref (array);
CoglPrimitive *
cogl_primitive_new_p3 (CoglVerticesMode mode,
int n_vertices,
- const CoglP3Vertex *data)
+ const CoglVertexP3 *data)
{
CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglP3Vertex), data);
- CoglVertexAttribute *attributes[2];
-
- attributes[0] =
- cogl_vertex_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglP3Vertex),
- offsetof (CoglP3Vertex, x),
- 3,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP3), data);
+ CoglAttribute *attributes[2];
+
+ attributes[0] = cogl_attribute_new (array,
+ "cogl_position_in",
+ sizeof (CoglVertexP3),
+ offsetof (CoglVertexP3, x),
+ 3,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
attributes[1] = NULL;
cogl_object_unref (array);
CoglPrimitive *
cogl_primitive_new_p2c4 (CoglVerticesMode mode,
int n_vertices,
- const CoglP2C4Vertex *data)
+ const CoglVertexP2C4 *data)
{
CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglP2C4Vertex), data);
- CoglVertexAttribute *attributes[3];
-
- attributes[0] =
- cogl_vertex_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglP2C4Vertex),
- offsetof (CoglP2C4Vertex, x),
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] =
- cogl_vertex_attribute_new (array,
- "cogl_color_in",
- sizeof (CoglP2C4Vertex),
- offsetof (CoglP2C4Vertex, r),
- 4,
- COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
+ cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP2C4), data);
+ CoglAttribute *attributes[3];
+
+ attributes[0] = cogl_attribute_new (array,
+ "cogl_position_in",
+ sizeof (CoglVertexP2C4),
+ offsetof (CoglVertexP2C4, x),
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[1] = cogl_attribute_new (array,
+ "cogl_color_in",
+ sizeof (CoglVertexP2C4),
+ offsetof (CoglVertexP2C4, r),
+ 4,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
attributes[2] = NULL;
cogl_object_unref (array);
CoglPrimitive *
cogl_primitive_new_p3c4 (CoglVerticesMode mode,
int n_vertices,
- const CoglP3C4Vertex *data)
+ const CoglVertexP3C4 *data)
{
CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglP3C4Vertex), data);
- CoglVertexAttribute *attributes[3];
-
- attributes[0] =
- cogl_vertex_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglP3C4Vertex),
- offsetof (CoglP3C4Vertex, x),
- 3,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] =
- cogl_vertex_attribute_new (array,
- "cogl_color_in",
- sizeof (CoglP3C4Vertex),
- offsetof (CoglP3C4Vertex, r),
- 4,
- COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
+ cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP3C4), data);
+ CoglAttribute *attributes[3];
+
+ attributes[0] = cogl_attribute_new (array,
+ "cogl_position_in",
+ sizeof (CoglVertexP3C4),
+ offsetof (CoglVertexP3C4, x),
+ 3,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[1] = cogl_attribute_new (array,
+ "cogl_color_in",
+ sizeof (CoglVertexP3C4),
+ offsetof (CoglVertexP3C4, r),
+ 4,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
attributes[2] = NULL;
cogl_object_unref (array);
CoglPrimitive *
cogl_primitive_new_p2t2 (CoglVerticesMode mode,
int n_vertices,
- const CoglP2T2Vertex *data)
+ const CoglVertexP2T2 *data)
{
CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglP2T2Vertex), data);
- CoglVertexAttribute *attributes[3];
-
- attributes[0] =
- cogl_vertex_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglP2T2Vertex),
- offsetof (CoglP2T2Vertex, x),
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] =
- cogl_vertex_attribute_new (array,
- "cogl_tex_coord0_in",
- sizeof (CoglP2T2Vertex),
- offsetof (CoglP2T2Vertex, s),
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP2T2), data);
+ CoglAttribute *attributes[3];
+
+ attributes[0] = cogl_attribute_new (array,
+ "cogl_position_in",
+ sizeof (CoglVertexP2T2),
+ offsetof (CoglVertexP2T2, x),
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[1] = cogl_attribute_new (array,
+ "cogl_tex_coord0_in",
+ sizeof (CoglVertexP2T2),
+ offsetof (CoglVertexP2T2, s),
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
attributes[2] = NULL;
cogl_object_unref (array);
CoglPrimitive *
cogl_primitive_new_p3t2 (CoglVerticesMode mode,
int n_vertices,
- const CoglP3T2Vertex *data)
+ const CoglVertexP3T2 *data)
{
CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglP3T2Vertex), data);
- CoglVertexAttribute *attributes[3];
-
- attributes[0] =
- cogl_vertex_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglP3T2Vertex),
- offsetof (CoglP3T2Vertex, x),
- 3,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] =
- cogl_vertex_attribute_new (array,
- "cogl_tex_coord0_in",
- sizeof (CoglP3T2Vertex),
- offsetof (CoglP3T2Vertex, s),
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP3T2), data);
+ CoglAttribute *attributes[3];
+
+ attributes[0] = cogl_attribute_new (array,
+ "cogl_position_in",
+ sizeof (CoglVertexP3T2),
+ offsetof (CoglVertexP3T2, x),
+ 3,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[1] = cogl_attribute_new (array,
+ "cogl_tex_coord0_in",
+ sizeof (CoglVertexP3T2),
+ offsetof (CoglVertexP3T2, s),
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
attributes[2] = NULL;
cogl_object_unref (array);
CoglPrimitive *
cogl_primitive_new_p2t2c4 (CoglVerticesMode mode,
int n_vertices,
- const CoglP2T2C4Vertex *data)
+ const CoglVertexP2T2C4 *data)
{
CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglP2T2C4Vertex), data);
- CoglVertexAttribute *attributes[4];
-
- attributes[0] =
- cogl_vertex_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglP2T2C4Vertex),
- offsetof (CoglP2T2C4Vertex, x),
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] =
- cogl_vertex_attribute_new (array,
- "cogl_tex_coord0_in",
- sizeof (CoglP2T2C4Vertex),
- offsetof (CoglP2T2C4Vertex, s),
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
- attributes[2] =
- cogl_vertex_attribute_new (array,
- "cogl_color_in",
- sizeof (CoglP2T2C4Vertex),
- offsetof (CoglP2T2C4Vertex, r),
- 4,
- COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
+ cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP2T2C4), data);
+ CoglAttribute *attributes[4];
+
+ attributes[0] = cogl_attribute_new (array,
+ "cogl_position_in",
+ sizeof (CoglVertexP2T2C4),
+ offsetof (CoglVertexP2T2C4, x),
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[1] = cogl_attribute_new (array,
+ "cogl_tex_coord0_in",
+ sizeof (CoglVertexP2T2C4),
+ offsetof (CoglVertexP2T2C4, s),
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[2] = cogl_attribute_new (array,
+ "cogl_color_in",
+ sizeof (CoglVertexP2T2C4),
+ offsetof (CoglVertexP2T2C4, r),
+ 4,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
attributes[3] = NULL;
cogl_object_unref (array);
CoglPrimitive *
cogl_primitive_new_p3t2c4 (CoglVerticesMode mode,
int n_vertices,
- const CoglP3T2C4Vertex *data)
+ const CoglVertexP3T2C4 *data)
{
CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglP3T2C4Vertex), data);
- CoglVertexAttribute *attributes[4];
-
- attributes[0] =
- cogl_vertex_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglP3T2C4Vertex),
- offsetof (CoglP3T2C4Vertex, x),
- 3,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] =
- cogl_vertex_attribute_new (array,
- "cogl_tex_coord0_in",
- sizeof (CoglP3T2C4Vertex),
- offsetof (CoglP3T2C4Vertex, s),
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
- attributes[2] =
- cogl_vertex_attribute_new (array,
- "cogl_color_in",
- sizeof (CoglP3T2C4Vertex),
- offsetof (CoglP3T2C4Vertex, r),
- 4,
- COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
+ cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP3T2C4), data);
+ CoglAttribute *attributes[4];
+
+ attributes[0] = cogl_attribute_new (array,
+ "cogl_position_in",
+ sizeof (CoglVertexP3T2C4),
+ offsetof (CoglVertexP3T2C4, x),
+ 3,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[1] = cogl_attribute_new (array,
+ "cogl_tex_coord0_in",
+ sizeof (CoglVertexP3T2C4),
+ offsetof (CoglVertexP3T2C4, s),
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[2] = cogl_attribute_new (array,
+ "cogl_color_in",
+ sizeof (CoglVertexP3T2C4),
+ offsetof (CoglVertexP3T2C4, r),
+ 4,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
attributes[3] = NULL;
cogl_object_unref (array);
for (i = 0; i < primitive->attributes->len; i++)
{
- CoglVertexAttribute *attribute =
- g_array_index (primitive->attributes, CoglVertexAttribute *, i);
+ CoglAttribute *attribute =
+ g_array_index (primitive->attributes, CoglAttribute *, i);
cogl_object_unref (attribute);
}
g_array_set_size (primitive->attributes, 0);
void
cogl_primitive_set_attributes (CoglPrimitive *primitive,
- CoglVertexAttribute **attributes)
+ CoglAttribute **attributes)
{
int i;
for (i = 0; attributes[i]; i++)
{
cogl_object_ref (attributes[i]);
- g_return_if_fail (cogl_is_vertex_attribute (attributes[i]));
+ g_return_if_fail (cogl_is_attribute (attributes[i]));
g_array_append_val (primitive->attributes, attributes[i]);
}
}
for (i = 0; i < primitive->attributes->len; i++)
{
- CoglVertexAttribute *attribute =
- g_array_index (primitive->attributes, CoglVertexAttribute *, i);
- _cogl_vertex_attribute_immutable_ref (attribute);
+ CoglAttribute *attribute =
+ g_array_index (primitive->attributes, CoglAttribute *, i);
+ _cogl_attribute_immutable_ref (attribute);
}
return primitive;
for (i = 0; i < primitive->attributes->len; i++)
{
- CoglVertexAttribute *attribute =
- g_array_index (primitive->attributes, CoglVertexAttribute *, i);
- _cogl_vertex_attribute_immutable_unref (attribute);
+ CoglAttribute *attribute =
+ g_array_index (primitive->attributes, CoglAttribute *, i);
+ _cogl_attribute_immutable_unref (attribute);
}
}
void
cogl_primitive_draw (CoglPrimitive *primitive)
{
- CoglVertexAttribute **attributes =
- (CoglVertexAttribute **)primitive->attributes->data;
+ CoglAttribute **attributes =
+ (CoglAttribute **)primitive->attributes->data;
if (primitive->indices)
- cogl_draw_indexed_vertex_attributes_array (primitive->mode,
- primitive->first_vertex,
- primitive->n_vertices,
- primitive->indices,
- attributes);
+ cogl_draw_indexed_attributes_array (primitive->mode,
+ primitive->first_vertex,
+ primitive->n_vertices,
+ primitive->indices,
+ attributes);
else
- cogl_draw_vertex_attributes_array (primitive->mode,
- primitive->first_vertex,
- primitive->n_vertices,
- attributes);
+ cogl_draw_attributes_array (primitive->mode,
+ primitive->first_vertex,
+ primitive->n_vertices,
+ attributes);
}
#define __COGL_PRIMITIVE_H__
#include <cogl/cogl-vertex-buffer.h> /* for CoglVerticesMode */
-#include <cogl/cogl-vertex-attribute.h>
+#include <cogl/cogl-attribute.h>
G_BEGIN_DECLS
typedef struct _CoglPrimitive CoglPrimitive;
/**
- * CoglP2Vertex:
+ * CoglVertexP2:
* @x: The x component of a position attribute
* @y: The y component of a position attribute
*
typedef struct
{
float x, y;
-} CoglP2Vertex;
+} CoglVertexP2;
/**
- * CoglP3Vertex:
+ * CoglVertexP3:
* @x: The x component of a position attribute
* @y: The y component of a position attribute
* @z: The z component of a position attribute
typedef struct
{
float x, y, z;
-} CoglP3Vertex;
+} CoglVertexP3;
/**
- * CoglP2C4Vertex:
+ * CoglVertexP2C4:
* @x: The x component of a position attribute
* @y: The y component of a position attribute
* @r: The red component of a color attribute
{
float x, y;
guint8 r, g, b, a;
-} CoglP2C4Vertex;
+} CoglVertexP2C4;
/**
- * CoglP3C4Vertex:
+ * CoglVertexP3C4:
* @x: The x component of a position attribute
* @y: The y component of a position attribute
* @z: The z component of a position attribute
{
float x, y, z;
guint8 r, g, b, a;
-} CoglP3C4Vertex;
+} CoglVertexP3C4;
/**
- * CoglP2T2Vertex:
+ * CoglVertexP2T2:
* @x: The x component of a position attribute
* @y: The y component of a position attribute
* @s: The s component of a texture coordinate attribute
{
float x, y;
float s, t;
-} CoglP2T2Vertex;
+} CoglVertexP2T2;
/**
- * CoglP3T2Vertex:
+ * CoglVertexP3T2:
* @x: The x component of a position attribute
* @y: The y component of a position attribute
* @z: The z component of a position attribute
{
float x, y, z;
float s, t;
-} CoglP3T2Vertex;
+} CoglVertexP3T2;
/**
- * CoglP2T2C4Vertex:
+ * CoglVertexP2T2C4:
* @x: The x component of a position attribute
* @y: The y component of a position attribute
* @s: The s component of a texture coordinate attribute
float x, y;
float s, t;
guint8 r, g, b, a;
-} CoglP2T2C4Vertex;
+} CoglVertexP2T2C4;
/**
- * CoglP3T2C4Vertex:
+ * CoglVertexP3T2C4:
* @x: The x component of a position attribute
* @y: The y component of a position attribute
* @z: The z component of a position attribute
float x, y, z;
float s, t;
guint8 r, g, b, a;
-} CoglP3T2C4Vertex;
+} CoglVertexP3T2C4;
/**
* cogl_primitive_new:
* @n_vertices: The number of vertices to process when drawing
* @Varargs: A %NULL terminated list of attributes
*
- * Combines a set of #CoglVertexAttribute<!-- -->s with a specific draw @mode
+ * Combines a set of #CoglAttribute<!-- -->s with a specific draw @mode
* and defines a vertex count so a #CoglPrimitive object can be retained and
* drawn later with no addition information required.
*
CoglPrimitive *
cogl_primitive_new_with_attributes_array (CoglVerticesMode mode,
int n_vertices,
- CoglVertexAttribute **attributes);
+ CoglAttribute **attributes);
/**
* cogl_primitive_new_p2:
* @mode: A #CoglVerticesMode defining how to draw the vertices
* @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglP2Vertex vertices
+ * @data: An array of #CoglVertexP2 vertices
*
* Provides a convenient way to describe a primitive, such as a single
* triangle strip or a triangle fan, that will internally allocate the
* necessary #CoglVertexArray storage, describe the position
- * attribute with a #CoglVertexAttribute and upload your data.
+ * attribute with a #CoglAttribute and upload your data.
*
* For example to draw a convex polygon you can do:
* |[
- * CoglP2Vertex triangle[] =
+ * CoglVertexP2 triangle[] =
* {
* { 0, 300 },
* { 150, 0, },
CoglPrimitive *
cogl_primitive_new_p2 (CoglVerticesMode mode,
int n_vertices,
- const CoglP2Vertex *data);
+ const CoglVertexP2 *data);
/**
* cogl_primitive_new_p3:
* @mode: A #CoglVerticesMode defining how to draw the vertices
* @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglP3Vertex vertices
+ * @data: An array of #CoglVertexP3 vertices
*
* Provides a convenient way to describe a primitive, such as a single
* triangle strip or a triangle fan, that will internally allocate the
* necessary #CoglVertexArray storage, describe the position
- * attribute with a #CoglVertexAttribute and upload your data.
+ * attribute with a #CoglAttribute and upload your data.
*
* For example to draw a convex polygon you can do:
* |[
- * CoglP3Vertex triangle[] =
+ * CoglVertexP3 triangle[] =
* {
* { 0, 300, 0 },
* { 150, 0, 0 },
CoglPrimitive *
cogl_primitive_new_p3 (CoglVerticesMode mode,
int n_vertices,
- const CoglP3Vertex *data);
+ const CoglVertexP3 *data);
/**
* cogl_primitive_new_p2c4:
* @mode: A #CoglVerticesMode defining how to draw the vertices
* @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglP2C4Vertex vertices
+ * @data: An array of #CoglVertexP2C4 vertices
*
* Provides a convenient way to describe a primitive, such as a single
* triangle strip or a triangle fan, that will internally allocate the
* necessary #CoglVertexArray storage, describe the position
- * and color attributes with #CoglVertexAttribute<!-- -->s and upload
+ * and color attributes with #CoglAttribute<!-- -->s and upload
* your data.
*
* For example to draw a convex polygon with a linear gradient you
* can do:
* |[
- * CoglP2C4Vertex triangle[] =
+ * CoglVertexP2C4 triangle[] =
* {
* { 0, 300, 0xff, 0x00, 0x00, 0xff },
* { 150, 0, 0x00, 0xff, 0x00, 0xff },
CoglPrimitive *
cogl_primitive_new_p2c4 (CoglVerticesMode mode,
int n_vertices,
- const CoglP2C4Vertex *data);
+ const CoglVertexP2C4 *data);
/**
* cogl_primitive_new_p3c4:
* @mode: A #CoglVerticesMode defining how to draw the vertices
* @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglP3C4Vertex vertices
+ * @data: An array of #CoglVertexP3C4 vertices
*
* Provides a convenient way to describe a primitive, such as a single
* triangle strip or a triangle fan, that will internally allocate the
* necessary #CoglVertexArray storage, describe the position
- * and color attributes with #CoglVertexAttribute<!-- -->s and upload
+ * and color attributes with #CoglAttribute<!-- -->s and upload
* your data.
*
* For example to draw a convex polygon with a linear gradient you
* can do:
* |[
- * CoglP3C4Vertex triangle[] =
+ * CoglVertexP3C4 triangle[] =
* {
* { 0, 300, 0, 0xff, 0x00, 0x00, 0xff },
* { 150, 0, 0, 0x00, 0xff, 0x00, 0xff },
CoglPrimitive *
cogl_primitive_new_p3c4 (CoglVerticesMode mode,
int n_vertices,
- const CoglP3C4Vertex *data);
+ const CoglVertexP3C4 *data);
/**
* cogl_primitive_new_p2t2:
* @mode: A #CoglVerticesMode defining how to draw the vertices
* @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglP2T2Vertex vertices
+ * @data: An array of #CoglVertexP2T2 vertices
*
* Provides a convenient way to describe a primitive, such as a single
* triangle strip or a triangle fan, that will internally allocate the
* necessary #CoglVertexArray storage, describe the position and
- * texture coordinate attributes with #CoglVertexAttribute<!-- -->s and
+ * texture coordinate attributes with #CoglAttribute<!-- -->s and
* upload your data.
*
* For example to draw a convex polygon with texture mapping you can
* do:
* |[
- * CoglP2T2Vertex triangle[] =
+ * CoglVertexP2T2 triangle[] =
* {
* { 0, 300, 0.0, 1.0},
* { 150, 0, 0.5, 0.0},
CoglPrimitive *
cogl_primitive_new_p2t2 (CoglVerticesMode mode,
int n_vertices,
- const CoglP2T2Vertex *data);
+ const CoglVertexP2T2 *data);
/**
* cogl_primitive_new_p3t2:
* @mode: A #CoglVerticesMode defining how to draw the vertices
* @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglP3T2Vertex vertices
+ * @data: An array of #CoglVertexP3T2 vertices
*
* Provides a convenient way to describe a primitive, such as a single
* triangle strip or a triangle fan, that will internally allocate the
* necessary #CoglVertexArray storage, describe the position and
- * texture coordinate attributes with #CoglVertexAttribute<!-- -->s and
+ * texture coordinate attributes with #CoglAttribute<!-- -->s and
* upload your data.
*
* For example to draw a convex polygon with texture mapping you can
* do:
* |[
- * CoglP3T2Vertex triangle[] =
+ * CoglVertexP3T2 triangle[] =
* {
* { 0, 300, 0, 0.0, 1.0},
* { 150, 0, 0, 0.5, 0.0},
CoglPrimitive *
cogl_primitive_new_p3t2 (CoglVerticesMode mode,
int n_vertices,
- const CoglP3T2Vertex *data);
+ const CoglVertexP3T2 *data);
/**
* cogl_primitive_new_p2t2c4:
* @mode: A #CoglVerticesMode defining how to draw the vertices
* @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglP2T2C4Vertex vertices
+ * @data: An array of #CoglVertexP2T2C4 vertices
*
* Provides a convenient way to describe a primitive, such as a single
* triangle strip or a triangle fan, that will internally allocate the
* necessary #CoglVertexArray storage, describe the position, texture
- * coordinate and color attributes with #CoglVertexAttribute<!-- -->s and
+ * coordinate and color attributes with #CoglAttribute<!-- -->s and
* upload your data.
*
* For example to draw a convex polygon with texture mapping and a
* linear gradient you can do:
* |[
- * CoglP2T2C4Vertex triangle[] =
+ * CoglVertexP2T2C4 triangle[] =
* {
* { 0, 300, 0.0, 1.0, 0xff, 0x00, 0x00, 0xff},
* { 150, 0, 0.5, 0.0, 0x00, 0xff, 0x00, 0xff},
CoglPrimitive *
cogl_primitive_new_p2t2c4 (CoglVerticesMode mode,
int n_vertices,
- const CoglP2T2C4Vertex *data);
+ const CoglVertexP2T2C4 *data);
/**
* cogl_primitive_new_p3t2c4:
* @mode: A #CoglVerticesMode defining how to draw the vertices
* @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglP3T2C4Vertex vertices
+ * @data: An array of #CoglVertexP3T2C4 vertices
*
* Provides a convenient way to describe a primitive, such as a single
* triangle strip or a triangle fan, that will internally allocate the
* necessary #CoglVertexArray storage, describe the position, texture
- * coordinate and color attributes with #CoglVertexAttribute<!-- -->s and
+ * coordinate and color attributes with #CoglAttribute<!-- -->s and
* upload your data.
*
* For example to draw a convex polygon with texture mapping and a
* linear gradient you can do:
* |[
- * CoglP3T2C4Vertex triangle[] =
+ * CoglVertexP3T2C4 triangle[] =
* {
* { 0, 300, 0, 0.0, 1.0, 0xff, 0x00, 0x00, 0xff},
* { 150, 0, 0, 0.5, 0.0, 0x00, 0xff, 0x00, 0xff},
CoglPrimitive *
cogl_primitive_new_p3t2c4 (CoglVerticesMode mode,
int n_vertices,
- const CoglP3T2C4Vertex *data);
+ const CoglVertexP3T2C4 *data);
int
cogl_primitive_get_first_vertex (CoglPrimitive *primitive);
/**
* cogl_primitive_set_attributes:
* @primitive: A #CoglPrimitive object
- * @attributes: A %NULL terminated array of #CoglVertexAttribute
+ * @attributes: A %NULL terminated array of #CoglAttribute
* pointers
*
* Replaces all the attributes of the given #CoglPrimitive object.
*/
void
cogl_primitive_set_attributes (CoglPrimitive *primitive,
- CoglVertexAttribute **attributes);
+ CoglAttribute **attributes);
void
#include "cogl-pipeline-opengl-private.h"
#include "cogl-vertex-buffer-private.h"
#include "cogl-framebuffer-private.h"
-#include "cogl-vertex-attribute-private.h"
+#include "cogl-attribute-private.h"
#include <string.h>
#include <math.h>
const CoglTextureVertex *vertices;
int n_vertices;
int stride;
- CoglVertexAttribute **attributes;
+ CoglAttribute **attributes;
} TextureSlicedPolygonState;
static void
void *user_data)
{
TextureSlicedQuadState *state = user_data;
+ CoglFramebuffer *framebuffer = _cogl_get_framebuffer ();
CoglHandle texture_override;
float quad_coords[4];
else
texture_override = texture_handle;
- _cogl_journal_log_quad (quad_coords,
+ _cogl_journal_log_quad (framebuffer->journal,
+ quad_coords,
state->pipeline,
1, /* one layer */
texture_override, /* replace the layer0 texture */
int n_layers = cogl_pipeline_get_n_layers (pipeline);
ValidateTexCoordsState state;
float *final_tex_coords = alloca (sizeof (float) * 4 * n_layers);
+ CoglFramebuffer *framebuffer;
_COGL_GET_CONTEXT (ctx, FALSE);
if (state.override_pipeline)
pipeline = state.override_pipeline;
- _cogl_journal_log_quad (position,
+ framebuffer = _cogl_get_framebuffer ();
+ _cogl_journal_log_quad (framebuffer->journal,
+ position,
pipeline,
n_layers,
COGL_INVALID_HANDLE, /* no texture override */
x_2, y_2
};
CoglVertexArray *vertex_array;
- CoglVertexAttribute *attributes[2];
+ CoglAttribute *attributes[2];
vertex_array = cogl_vertex_array_new (sizeof (vertices), vertices);
- attributes[0] = cogl_vertex_attribute_new (vertex_array,
- "cogl_position_in",
- sizeof (float) * 2, /* stride */
- 0, /* offset */
- 2, /* n_components */
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ attributes[0] = cogl_attribute_new (vertex_array,
+ "cogl_position_in",
+ sizeof (float) * 2, /* stride */
+ 0, /* offset */
+ 2, /* n_components */
+ COGL_ATTRIBUTE_TYPE_FLOAT);
attributes[1] = NULL;
- _cogl_draw_vertex_attributes_array (COGL_VERTICES_MODE_TRIANGLE_STRIP,
- 0, /* first_index */
- 4, /* n_vertices */
- attributes);
+ _cogl_draw_attributes_array (COGL_VERTICES_MODE_TRIANGLE_STRIP,
+ 0, /* first_index */
+ 4, /* n_vertices */
+ attributes,
+ COGL_DRAW_SKIP_JOURNAL_FLUSH |
+ COGL_DRAW_SKIP_PIPELINE_VALIDATION |
+ COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH);
+
cogl_object_unref (attributes[0]);
cogl_object_unref (vertex_array);
ValidateState validate_state;
int n_layers;
int n_attributes;
- CoglVertexAttribute **attributes;
+ CoglAttribute **attributes;
int i;
unsigned int stride;
gsize stride_bytes;
n_layers = cogl_pipeline_get_n_layers (pipeline);
n_attributes = 1 + n_layers + (use_color ? 1 : 0);
- attributes = g_alloca (sizeof (CoglVertexAttribute *) * (n_attributes + 1));
+ attributes = g_alloca (sizeof (CoglAttribute *) * (n_attributes + 1));
attributes[n_attributes] = NULL;
/* Our data is arranged like:
vertex_array = cogl_vertex_array_new (n_vertices * stride_bytes, NULL);
- attributes[0] =
- cogl_vertex_attribute_new (vertex_array,
- "cogl_position_in",
- stride_bytes,
- 0,
- 3,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ attributes[0] = cogl_attribute_new (vertex_array,
+ "cogl_position_in",
+ stride_bytes,
+ 0,
+ 3,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
for (i = 0; i < n_layers; i++)
{
char *name = i < 8 ? (char *)names[i] :
g_strdup_printf ("cogl_tex_coord%d_in", i);
- attributes[i + 1] =
- cogl_vertex_attribute_new (vertex_array,
- name,
- stride_bytes,
- /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
- 12 + 8 * i,
- 2,
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ attributes[i + 1] = cogl_attribute_new (vertex_array,
+ name,
+ stride_bytes,
+ /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
+ 12 + 8 * i,
+ 2,
+ COGL_ATTRIBUTE_TYPE_FLOAT);
}
if (use_color)
{
attributes[n_attributes - 1] =
- cogl_vertex_attribute_new (vertex_array,
- "cogl_color_in",
- stride_bytes,
- /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
- 12 + 8 * n_layers,
- 4,
- COGL_VERTEX_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
+ cogl_attribute_new (vertex_array,
+ "cogl_color_in",
+ stride_bytes,
+ /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
+ 12 + 8 * n_layers,
+ 4,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
}
/* Convert the vertices into an array of float vertex attributes */
cogl_push_source (pipeline);
- cogl_draw_vertex_attributes_array (COGL_VERTICES_MODE_TRIANGLE_FAN,
- 0, n_vertices,
- attributes);
+ cogl_draw_attributes_array (COGL_VERTICES_MODE_TRIANGLE_FAN,
+ 0, n_vertices,
+ attributes);
cogl_pop_source ();
debug_option_getter (void *user_data)
{
unsigned int shift = GPOINTER_TO_UINT (user_data);
- return (cogl_debug_flags & (1 << shift)) ? TRUE : FALSE;
+ return COGL_DEBUG_ENABLED (shift);
}
static void
unsigned int shift = GPOINTER_TO_UINT (user_data);
if (value)
- cogl_debug_flags |= (1 << shift);
+ COGL_DEBUG_SET_FLAG (shift);
else
- cogl_debug_flags &= ~(1 << shift);
+ COGL_DEBUG_CLEAR_FLAG (shift);
}
static void
_cogl_uprof_context = uprof_context_new ("Cogl");
#define OPT(MASK_NAME, GROUP, NAME, NAME_FORMATTED, DESCRIPTION) \
G_STMT_START { \
- int shift; \
- for (shift = 0; (COGL_DEBUG_ ## MASK_NAME >> shift) != 1; shift++) \
- ; \
+ int shift = COGL_DEBUG_ ## MASK_NAME; \
uprof_context_add_boolean_option (_cogl_uprof_context, \
GROUP, \
NAME, \
#include "cogl-context.h"
#include "cogl-handle.h"
-#ifndef HAVE_COGL_GLES
-
-#include <string.h>
-
#include "cogl-shader-private.h"
#include "cogl-program-private.h"
+#include <string.h>
+
static void _cogl_program_free (CoglProgram *program);
COGL_HANDLE_DEFINE (Program, program);
uniform_no, size, count, transpose, value);
}
+#ifndef HAVE_COGL_GLES
+
/* ARBfp local parameters can be referenced like:
*
* "program.local[5]"
}
}
+#endif /* HAVE_COGL_GLES */
+
#ifdef HAVE_COGL_GL
static void
GLuint gl_program,
gboolean gl_program_changed)
{
+#ifdef HAVE_COGL_GLES
+
+ g_return_if_reached ();
+
+#else /* HAVE_COGL_GLES */
+
CoglProgramUniform *uniform;
int i;
uniform->dirty = FALSE;
}
}
-}
-
-#else /* HAVE_COGL_GLES */
-
-/* No support on regular OpenGL 1.1 */
-
-CoglHandle
-cogl_create_program (void)
-{
- return COGL_INVALID_HANDLE;
-}
-
-gboolean
-cogl_is_program (CoglHandle handle)
-{
- return FALSE;
-}
-
-CoglHandle
-cogl_program_ref (CoglHandle handle)
-{
- return COGL_INVALID_HANDLE;
-}
-
-void
-cogl_program_unref (CoglHandle handle)
-{
-}
-
-void
-cogl_program_attach_shader (CoglHandle program_handle,
- CoglHandle shader_handle)
-{
-}
-
-void
-cogl_program_link (CoglHandle program_handle)
-{
-}
-
-void
-cogl_program_use (CoglHandle program_handle)
-{
-}
-
-int
-cogl_program_get_uniform_location (CoglHandle program_handle,
- const char *uniform_name)
-{
- return 0;
-}
-
-void
-cogl_program_uniform_1f (int uniform_no,
- float value)
-{
-}
-
-void
-cogl_program_uniform_1i (int uniform_no,
- int value)
-{
-}
-
-void
-cogl_program_uniform_float (int uniform_no,
- int size,
- int count,
- const GLfloat *value)
-{
-}
-
-void
-cogl_program_uniform_int (int uniform_no,
- int size,
- int count,
- const int *value)
-{
-}
-void
-cogl_program_uniform_matrix (int uniform_no,
- int size,
- int count,
- gboolean transpose,
- const GLfloat *value)
-{
+#endif /* HAVE_COGL_GLES */
}
-#endif /* HAVE_COGL_GLES2 */
-
CoglShaderLanguage
_cogl_program_get_language (CoglHandle handle)
{
map->space_remaining -= rectangle_size;
#ifdef COGL_ENABLE_DEBUG
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DUMP_ATLAS_IMAGE))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DUMP_ATLAS_IMAGE)))
{
_cogl_rectangle_map_dump_image (map);
/* Dumping the rectangle map is really slow so we might as well
}
#ifdef COGL_ENABLE_DEBUG
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DUMP_ATLAS_IMAGE))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DUMP_ATLAS_IMAGE)))
{
_cogl_rectangle_map_dump_image (map);
/* Dumping the rectangle map is really slow so we might as well
#include "cogl.h"
+#ifndef HAVE_COGL_GLES2
+
#define _COGL_COMMON_SHADER_BOILERPLATE \
"#define COGL_VERSION 100\n" \
+ "\n" \
+ "#define cogl_modelview_matrix gl_ModelViewMatrix\n" \
+ "#define cogl_modelview_projection_matrix gl_ModelViewProjectionMatrix\n" \
+ "#define cogl_projection_matrix gl_ProjectionMatrix\n" \
+ "#define cogl_texture_matrix gl_TextureMatrix\n" \
"\n"
-#ifndef HAVE_COGL_GLES2
-
#define _COGL_VERTEX_SHADER_BOILERPLATE \
_COGL_COMMON_SHADER_BOILERPLATE \
"#define cogl_position_in gl_Vertex\n" \
"#define cogl_position_out gl_Position\n" \
"#define cogl_point_size_out gl_PointSize\n" \
"#define cogl_color_out gl_FrontColor\n" \
- "#define cogl_tex_coord_out gl_TexCoord\n" \
- "\n" \
- "#define cogl_modelview_matrix gl_ModelViewMatrix\n" \
- "#define cogl_modelview_projection_matrix gl_ModelViewProjectionMatrix\n" \
- "#define cogl_projection_matrix gl_ProjectionMatrix\n" \
- "#define cogl_texture_matrix gl_TextureMatrix\n"
+ "#define cogl_tex_coord_out gl_TexCoord\n"
#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
_COGL_COMMON_SHADER_BOILERPLATE \
#else /* HAVE_COGL_GLES2 */
+#define _COGL_COMMON_SHADER_BOILERPLATE \
+ "#define COGL_VERSION 100\n" \
+ "\n" \
+ "uniform mat4 cogl_modelview_matrix;\n" \
+ "uniform mat4 cogl_modelview_projection_matrix;\n" \
+ "uniform mat4 cogl_projection_matrix;\n" \
+ "uniform float cogl_point_size_in;\n"
+
/* This declares all of the variables that we might need. This is
working on the assumption that the compiler will optimise them out
if they are not actually used. The GLSL spec for GLES at least
"attribute vec4 cogl_color_in;\n" \
"attribute vec4 cogl_position_in;\n" \
"#define cogl_tex_coord_in cogl_tex_coord0_in;\n" \
- "attribute vec3 cogl_normal_in;\n" \
- "\n" \
- "uniform mat4 cogl_modelview_matrix;\n" \
- "uniform mat4 cogl_modelview_projection_matrix;\n" \
- "uniform mat4 cogl_projection_matrix;\n" \
- "uniform float cogl_point_size_in;\n"
+ "attribute vec3 cogl_normal_in;\n"
#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
_COGL_COMMON_SHADER_BOILERPLATE \
#define GET_CONTEXT(CTXVAR,RETVAL) G_STMT_START { } G_STMT_END
#endif
-#ifndef HAVE_COGL_GLES
-
static void _cogl_shader_free (CoglShader *shader);
COGL_HANDLE_DEFINE (Shader, shader);
static void
_cogl_shader_free (CoglShader *shader)
{
+#ifndef HAVE_COGL_GLES
+
/* Frees shader resources but its handle is not
released! Do that separately before this! */
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (shader->gl_handle)
GE (glDeleteShader (shader->gl_handle));
+#endif /* HAVE_COGL_GLES */
+
g_slice_free (CoglShader, shader);
}
static void
delete_shader (CoglShader *shader)
{
+#ifndef HAVE_COGL_GLES
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
#ifdef HAVE_COGL_GL
}
shader->gl_handle = 0;
+
+#endif /* HAVE_COGL_GLES */
}
void
const char **strings_in,
const GLint *lengths_in)
{
+#ifndef HAVE_COGL_GLES
+
static const char vertex_boilerplate[] = _COGL_VERTEX_SHADER_BOILERPLATE;
static const char fragment_boilerplate[] = _COGL_FRAGMENT_SHADER_BOILERPLATE;
}
count += count_in;
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_SHOW_SOURCE))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
{
GString *buf = g_string_new (NULL);
int i;
#ifdef HAVE_COGL_GLES2
g_free (tex_coord_declarations);
#endif
+
+#endif /* HAVE_COGL_GLES */
}
void
_cogl_shader_compile_real (CoglHandle handle,
int n_tex_coord_attribs)
{
+#ifndef HAVE_COGL_GLES
+
CoglShader *shader = handle;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
GE (glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle));
- if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_SHOW_SOURCE))
+ if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
g_message ("user ARBfp program:\n%s", shader->source);
#ifdef COGL_GL_DEBUG
}
#endif
}
+
+#endif /* HAVE_COGL_GLES */
}
char *
cogl_shader_get_info_log (CoglHandle handle)
{
+#ifdef HAVE_COGL_GLES
+
+ return NULL;
+
+#else /* HAVE_COGL_GLES */
+
CoglShader *shader;
GET_CONTEXT (ctx, NULL);
buffer[len] = '\0';
return g_strdup (buffer);
}
+
+#endif /* HAVE_COGL_GLES */
}
CoglShaderType
gboolean
cogl_shader_is_compiled (CoglHandle handle)
{
+#ifdef HAVE_COGL_GLES
+
+ return FALSE;
+
+#else /* HAVE_COGL_GLES */
+
GLint status;
CoglShader *shader;
else
return FALSE;
}
-}
-
-#else /* HAVE_COGL_GLES */
-
-/* No support on regular OpenGL 1.1 */
-
-CoglHandle
-cogl_create_shader (CoglShaderType type)
-{
- return COGL_INVALID_HANDLE;
-}
-
-gboolean
-cogl_is_shader (CoglHandle handle)
-{
- return FALSE;
-}
-
-CoglHandle
-cogl_shader_ref (CoglHandle handle)
-{
- return COGL_INVALID_HANDLE;
-}
-
-void
-cogl_shader_unref (CoglHandle handle)
-{
-}
-
-void
-cogl_shader_source (CoglHandle shader,
- const char *source)
-{
-}
-
-void
-cogl_shader_compile (CoglHandle shader_handle)
-{
-}
-
-char *
-cogl_shader_get_info_log (CoglHandle handle)
-{
- return NULL;
-}
-
-CoglShaderType
-cogl_shader_get_type (CoglHandle handle)
-{
- return COGL_SHADER_TYPE_VERTEX;
-}
-
-gboolean
-cogl_shader_is_compiled (CoglHandle handle)
-{
- return FALSE;
-}
#endif /* HAVE_COGL_GLES */
-
+}
sub_tex = g_new (CoglSubTexture, 1);
tex = COGL_TEXTURE (sub_tex);
- tex->vtable = &cogl_sub_texture_vtable;
+
+ _cogl_texture_init (tex, &cogl_sub_texture_vtable);
/* If the next texture is also a sub texture we can avoid one level
of indirection by referencing the full texture of that texture
{
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
- tex->vtable = &cogl_texture_2d_sliced_vtable;
+ _cogl_texture_init (tex, &cogl_texture_2d_sliced_vtable);
tex_2ds->slice_x_spans = NULL;
tex_2ds->slice_y_spans = NULL;
CoglTexture2D *tex_2d = g_new (CoglTexture2D, 1);
CoglTexture *tex = COGL_TEXTURE (tex_2d);
- tex->vtable = &cogl_texture_2d_vtable;
+ _cogl_texture_init (tex, &cogl_texture_2d_vtable);
tex_2d->width = width;
tex_2d->height = height;
CoglTexture3D *tex_3d = g_new (CoglTexture3D, 1);
CoglTexture *tex = COGL_TEXTURE (tex_3d);
- tex->vtable = &cogl_texture_3d_vtable;
+ _cogl_texture_init (tex, &cogl_texture_3d_vtable);
tex_3d->width = width;
tex_3d->height = height;
struct _CoglTexture
{
CoglHandleObject _parent;
+ GList *framebuffers;
const CoglTextureVtable *vtable;
};
};
void
+_cogl_texture_init (CoglTexture *texture,
+ const CoglTextureVtable *vtable);
+
+void
_cogl_texture_free (CoglTexture *texture);
/* This is used to register a type to the list of handle types that
unsigned int dst_height,
CoglBitmap *bmp);
+void
+_cogl_texture_associate_framebuffer (CoglHandle handle,
+ CoglFramebuffer *framebuffer);
+
+const GList *
+_cogl_texture_get_associated_framebuffers (CoglHandle handle);
+
+void
+_cogl_texture_flush_journal_rendering (CoglHandle handle);
+
#endif /* __COGL_TEXTURE_PRIVATE_H */
CoglTextureRectangle *tex_rect = g_new (CoglTextureRectangle, 1);
CoglTexture *tex = COGL_TEXTURE (tex_rect);
- tex->vtable = &cogl_texture_rectangle_vtable;
+ _cogl_texture_init (tex, &cogl_texture_rectangle_vtable);
tex_rect->width = width;
tex_rect->height = height;
#include "cogl-pipeline.h"
#include "cogl-context.h"
#include "cogl-handle.h"
+#include "cogl-object-private.h"
#include "cogl-primitives.h"
#include "cogl-framebuffer-private.h"
}
void
+_cogl_texture_init (CoglTexture *texture,
+ const CoglTextureVtable *vtable)
+{
+ texture->vtable = vtable;
+ texture->framebuffers = NULL;
+}
+
+void
_cogl_texture_free (CoglTexture *texture)
{
g_free (texture);
if (_cogl_texture_needs_premult_conversion (src_format,
dst_format))
{
- guint8 *src_data;
- guint8 *dst_data;
-
- if ((src_data = _cogl_bitmap_map (src_bmp,
- COGL_BUFFER_ACCESS_READ, 0)) == NULL)
- return NULL;
-
- dst_data = g_memdup (src_data,
- _cogl_bitmap_get_height (src_bmp) *
- _cogl_bitmap_get_rowstride (src_bmp));
-
- _cogl_bitmap_unmap (src_bmp);
-
- dst_bmp =
- _cogl_bitmap_new_from_data (dst_data,
- src_format,
- _cogl_bitmap_get_width (src_bmp),
- _cogl_bitmap_get_height (src_bmp),
- _cogl_bitmap_get_rowstride (src_bmp),
- (CoglBitmapDestroyNotify) g_free,
- NULL);
+ dst_bmp = _cogl_bitmap_copy (src_bmp);
if (!_cogl_bitmap_convert_premult_status (dst_bmp,
src_format ^
return byte_size;
}
+
+static void
+_cogl_texture_framebuffer_destroy_cb (void *user_data,
+ void *instance)
+{
+ CoglTexture *tex = user_data;
+ CoglFramebuffer *framebuffer = instance;
+
+ tex->framebuffers = g_list_remove (tex->framebuffers, framebuffer);
+}
+
+void
+_cogl_texture_associate_framebuffer (CoglHandle handle,
+ CoglFramebuffer *framebuffer)
+{
+ CoglTexture *tex = COGL_TEXTURE (handle);
+ static CoglUserDataKey framebuffer_destroy_notify_key;
+
+ /* Note: we don't take a reference on the framebuffer here because
+ * that would introduce a circular reference. */
+ tex->framebuffers = g_list_prepend (tex->framebuffers, framebuffer);
+
+ /* Since we haven't taken a reference on the framebuffer we setup
+ * some private data so we will be notified if it is destroyed... */
+ _cogl_object_set_user_data (COGL_OBJECT (framebuffer),
+ &framebuffer_destroy_notify_key,
+ tex,
+ _cogl_texture_framebuffer_destroy_cb);
+}
+
+const GList *
+_cogl_texture_get_associated_framebuffers (CoglHandle handle)
+{
+ CoglTexture *tex = COGL_TEXTURE (handle);
+ return tex->framebuffers;
+}
+
+void
+_cogl_texture_flush_journal_rendering (CoglHandle handle)
+{
+ CoglTexture *tex = COGL_TEXTURE (handle);
+ GList *l;
+
+ /* It could be that a referenced texture is part of a framebuffer
+ * which has an associated journal that must be flushed before it
+ * can be sampled from by the current primitive... */
+ for (l = tex->framebuffers; l; l = l->next)
+ _cogl_framebuffer_flush_journal (l->data);
+}
* @COGL_FEATURE_POINT_SPRITE: Whether
* cogl_material_set_layer_point_sprite_coords_enabled() is supported.
* @COGL_FEATURE_TEXTURE_3D: 3D texture support
+ * @COGL_FEATURE_MAP_BUFFER_FOR_READ: Whether cogl_buffer_map() is
+ * supported with CoglBufferAccess including read support.
+ * @COGL_FEATURE_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is
+ * supported with CoglBufferAccess including write support.
*
* Flags for the supported features.
*
COGL_FEATURE_TEXTURE_NPOT_REPEAT = (1 << 17),
COGL_FEATURE_POINT_SPRITE = (1 << 18),
COGL_FEATURE_TEXTURE_3D = (1 << 19),
- COGL_FEATURE_SHADERS_ARBFP = (1 << 20)
+ COGL_FEATURE_SHADERS_ARBFP = (1 << 20),
+ COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21),
+ COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22)
} CoglFeatureFlags;
/**
_cogl_error_quark (void);
/**
+ * CoglAttributeType:
+ * @COGL_ATTRIBUTE_TYPE_BYTE: Data is the same size of a byte
+ * @COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: Data is the same size of an
+ * unsigned byte
+ * @COGL_ATTRIBUTE_TYPE_SHORT: Data is the same size of a short integer
+ * @COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: Data is the same size of
+ * an unsigned short integer
+ * @COGL_ATTRIBUTE_TYPE_FLOAT: Data is the same size of a float
+ *
+ * Data types for the components of a vertex attribute.
+ *
+ * Since: 1.0
+ */
+typedef enum {
+ COGL_ATTRIBUTE_TYPE_BYTE = 0x1400,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE = 0x1401,
+ COGL_ATTRIBUTE_TYPE_SHORT = 0x1402,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT = 0x1403,
+ COGL_ATTRIBUTE_TYPE_FLOAT = 0x1406
+} CoglAttributeType;
+
+/**
* CoglIndicesType:
* @COGL_INDICES_TYPE_UNSIGNED_BYTE: Your indices are unsigned bytes
* @COGL_INDICES_TYPE_UNSIGNED_SHORT: Your indices are unsigned shorts
return hash;
}
+/* The 'ffs' function is part of C99 so it isn't always available */
+#ifndef HAVE_FFS
+
+int
+_cogl_util_ffs (int num)
+{
+ int i = 1;
+
+ if (num == 0)
+ return 0;
+
+ while ((num & 1) == 0)
+ {
+ num >>= 1;
+ i++;
+ }
+
+ return i;
+}
+
+#endif /* HAVE_FFS */
unsigned int
_cogl_util_one_at_a_time_mix (unsigned int hash);
+/* The 'ffs' function is part of C99 so it isn't always available */
+#ifdef HAVE_FFS
+#define _cogl_util_ffs ffs
+#else
+int
+_cogl_util_ffs (int num);
+#endif
+
#endif /* __COGL_UTIL_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * 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/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_VERTEX_ATTRIBUTE_PRIVATE_H
-#define __COGL_VERTEX_ATTRIBUTE_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-vertex-attribute.h"
-
-typedef enum
-{
- COGL_VERTEX_ATTRIBUTE_NAME_ID_POSITION_ARRAY,
- COGL_VERTEX_ATTRIBUTE_NAME_ID_COLOR_ARRAY,
- COGL_VERTEX_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY,
- COGL_VERTEX_ATTRIBUTE_NAME_ID_NORMAL_ARRAY,
- COGL_VERTEX_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY
-} CoglVertexAttributeNameID;
-
-struct _CoglVertexAttribute
-{
- CoglObject _parent;
-
- CoglVertexArray *array;
- char *name;
- CoglVertexAttributeNameID name_id;
- gsize stride;
- gsize offset;
- int n_components;
- CoglVertexAttributeType type;
- gboolean normalized;
- unsigned int texture_unit;
-
- int immutable_ref;
-};
-
-CoglVertexAttribute *
-_cogl_vertex_attribute_immutable_ref (CoglVertexAttribute *vertex_attribute);
-
-void
-_cogl_vertex_attribute_immutable_unref (CoglVertexAttribute *vertex_attribute);
-
-void
-_cogl_draw_vertex_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglVertexAttribute **attributes);
-
-void
-_cogl_draw_indexed_vertex_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglVertexAttribute **attributes);
-
-void
-_cogl_vertex_attribute_disable_cached_arrays (void);
-
-#endif /* __COGL_VERTEX_ATTRIBUTE_PRIVATE_H */
-
const void *pointer;
size_t vbo_offset;
} u;
- CoglVertexAttributeType type;
+ CoglAttributeType type;
size_t span_bytes;
guint16 stride;
guint8 n_components;
guint8 texture_unit;
int attribute_first;
- CoglVertexAttribute *attribute;
+ CoglAttribute *attribute;
} CoglVertexBufferAttrib;
* of all the submitted attributes
*
* Note: The CoglVertexBufferAttrib structs are deep copied, except the
- * internal CoglVertexAttribute pointer is set to NULL.
+ * internal CoglAttribute pointer is set to NULL.
*/
static GList *
copy_submitted_attributes_list (CoglVertexBuffer *buffer)
{
GList *l;
int n_attributes = 0;
- CoglVertexAttribute **attributes;
+ CoglAttribute **attributes;
int i;
if (!buffer->dirty_attributes)
g_return_if_fail (n_attributes > 0);
- attributes = g_alloca (sizeof (CoglVertexAttribute *) * n_attributes + 1);
+ attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes + 1);
i = 0;
for (l = buffer->submitted_vbos; l; l = l->next)
if (G_UNLIKELY (!attribute->attribute))
{
attribute->attribute =
- cogl_vertex_attribute_new (cogl_vbo->array,
- attribute->name_without_detail,
- attribute->stride,
- attribute->u.vbo_offset,
- attribute->n_components,
- attribute->type);
+ cogl_attribute_new (cogl_vbo->array,
+ attribute->name_without_detail,
+ attribute->stride,
+ attribute->u.vbo_offset,
+ attribute->n_components,
+ attribute->type);
}
attributes[i++] = attribute->attribute;
typedef struct
{
+ /* We have a ref-count on this private structure because we need to
+ refer to it both from the private data on a pipeline and any weak
+ pipelines that we create from it. If we didn't have the ref count
+ then we would depend on the order of destruction of a
+ CoglPipeline and the weak materials to avoid a crash */
+ unsigned int ref_count;
+
CoglPipeline *real_source;
} VertexBufferMaterialPrivate;
static void
+unref_pipeline_priv (VertexBufferMaterialPrivate *priv)
+{
+ if (--priv->ref_count < 1)
+ g_slice_free (VertexBufferMaterialPrivate, priv);
+}
+
+static void
weak_override_source_destroyed_cb (CoglPipeline *pipeline,
- void *user_data)
+ void *user_data)
{
VertexBufferMaterialPrivate *pipeline_priv = user_data;
pipeline_priv->real_source = NULL;
+ /* A reference was added when we copied the weak material so we need
+ to unref it here */
+ unref_pipeline_priv (pipeline_priv);
}
static gboolean
if (need_override_source)
{
if (pipeline_priv->real_source == pipeline)
- pipeline_priv->real_source = source =
- _cogl_pipeline_weak_copy (pipeline,
- weak_override_source_destroyed_cb,
- pipeline_priv);
+ {
+ pipeline_priv->ref_count++;
+ pipeline_priv->real_source = source =
+ _cogl_pipeline_weak_copy (pipeline,
+ weak_override_source_destroyed_cb,
+ pipeline_priv);
+ }
cogl_pipeline_set_layer_wrap_mode_s (source, layer_index, wrap_s);
cogl_pipeline_set_layer_wrap_mode_t (source, layer_index, wrap_t);
static void
destroy_pipeline_priv_cb (void *user_data)
{
- g_slice_free (VertexBufferMaterialPrivate, user_data);
+ unref_pipeline_priv (user_data);
}
static void
if (G_UNLIKELY (!pipeline_priv))
{
pipeline_priv = g_slice_new0 (VertexBufferMaterialPrivate);
+ pipeline_priv->ref_count = 1;
cogl_object_set_user_data (COGL_OBJECT (users_source),
&_cogl_vertex_buffer_pipeline_priv_key,
pipeline_priv,
cogl_vertex_buffer_get_n_vertices (CoglHandle handle);
/**
- * CoglAttributeType:
- * @COGL_ATTRIBUTE_TYPE_BYTE: Data is the same size of a byte
- * @COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: Data is the same size of an
- * unsigned byte
- * @COGL_ATTRIBUTE_TYPE_SHORT: Data is the same size of a short integer
- * @COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: Data is the same size of
- * an unsigned short integer
- * @COGL_ATTRIBUTE_TYPE_FLOAT: Data is the same size of a float
- *
- * Data types for the components of cogl_vertex_buffer_add()
- *
- * Since: 1.0
- */
-typedef enum {
- COGL_ATTRIBUTE_TYPE_BYTE = GL_BYTE,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE = GL_UNSIGNED_BYTE,
- COGL_ATTRIBUTE_TYPE_SHORT = GL_SHORT,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT = GL_UNSIGNED_SHORT,
- COGL_ATTRIBUTE_TYPE_FLOAT = GL_FLOAT
-} CoglAttributeType;
-
-/**
* cogl_vertex_buffer_add:
* @handle: A vertex buffer handle
* @attribute_name: The name of your attribute. It should be a valid GLSL
* must remain valid until you either call cogl_vertex_buffer_submit() or
* issue a draw call.
*
- * Adds an attribute to a buffer.
+ * Adds an attribute to a buffer, or replaces a previously added
+ * attribute with the same name.
*
* You either can use one of the built-in names such as "gl_Vertex", or
* "gl_MultiTexCoord0" to add standard attributes, like positions, colors
#include "cogl-bitmap-private.h"
#include "cogl-texture-private.h"
#include "cogl-texture-driver.h"
-#include "cogl-vertex-attribute-private.h"
+#include "cogl-attribute-private.h"
+#include "cogl-framebuffer-private.h"
#ifdef HAVE_COGL_GL
#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
return _cogl_check_extension (name, ext);
}
-/* This version of cogl_clear can be used internally as an alternative
- to avoid flushing the journal or the framebuffer state. This is
- needed when doing operations that may be called whiling flushing
- the journal */
-void
-_cogl_clear (const CoglColor *color, unsigned long buffers)
-{
- GLbitfield gl_buffers = 0;
-
- if (buffers & COGL_BUFFER_BIT_COLOR)
- {
- GE( glClearColor (cogl_color_get_red_float (color),
- cogl_color_get_green_float (color),
- cogl_color_get_blue_float (color),
- cogl_color_get_alpha_float (color)) );
- gl_buffers |= GL_COLOR_BUFFER_BIT;
- }
-
- if (buffers & COGL_BUFFER_BIT_DEPTH)
- gl_buffers |= GL_DEPTH_BUFFER_BIT;
-
- if (buffers & COGL_BUFFER_BIT_STENCIL)
- gl_buffers |= GL_STENCIL_BUFFER_BIT;
-
- if (!gl_buffers)
- {
- static gboolean shown = FALSE;
-
- if (!shown)
- {
- g_warning ("You should specify at least one auxiliary buffer "
- "when calling cogl_clear");
- }
-
- return;
- }
-
- GE (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;
- }
-}
-
+/* XXX: it's expected that we'll deprecated this with
+ * cogl_framebuffer_clear at some point. */
void
cogl_clear (const CoglColor *color, unsigned long buffers)
{
- COGL_NOTE (DRAW, "Clear begin");
-
- _cogl_journal_flush ();
-
- /* NB: _cogl_framebuffer_flush_state may disrupt various state (such
- * as the pipeline state) when flushing the clip stack, so should
- * always be done first when preparing to draw. */
- _cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0);
-
- _cogl_clear (color, buffers);;
-
- COGL_NOTE (DRAW, "Clear end");
+ _cogl_framebuffer_clear (_cogl_get_framebuffer (), buffers, color);
}
static gboolean
return;
/* Currently the journal can't track changes to backface culling state... */
- _cogl_journal_flush ();
+ _cogl_framebuffer_flush_journal (_cogl_get_framebuffer ());
ctx->enable_backface_culling = setting;
}
void
cogl_flush (void)
{
- _cogl_journal_flush ();
+ GList *l;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ for (l = ctx->framebuffers; l; l = l->next)
+ _cogl_framebuffer_flush_journal (l->data);
}
void
guint8 *pixels,
int rowstride)
{
- CoglFramebuffer *framebuffer;
+ CoglFramebuffer *framebuffer = _cogl_get_framebuffer ();
int framebuffer_height;
int bpp;
CoglBitmap *bmp;
g_return_if_fail (source == COGL_READ_PIXELS_COLOR_BUFFER);
- /* make sure any batched primitives get emitted to the GL driver before
- * issuing our read pixels... */
- cogl_flush ();
+ if (width == 1 && height == 1 && !framebuffer->clear_clip_dirty)
+ {
+ /* If everything drawn so far for this frame is still in the
+ * Journal then if all of the rectangles only have a flat
+ * opaque color we have a fast-path for reading a single pixel
+ * that avoids the relatively high cost of flushing primitives
+ * to be drawn on the GPU (considering how simple the geometry
+ * is in this case) and then blocking on the long GPU pipelines
+ * for the result.
+ */
+ if (_cogl_framebuffer_try_fast_read_pixel (framebuffer,
+ x, y, source, format,
+ pixels))
+ return;
+ }
- framebuffer = _cogl_get_framebuffer ();
+ /* make sure any batched primitives get emitted to the GL driver
+ * before issuing our read pixels...
+ *
+ * XXX: Note we currently use cogl_flush to ensure *all* journals
+ * are flushed here and not _cogl_journal_flush because we don't
+ * track the dependencies between framebuffers so we don't know if
+ * the current framebuffer depends on the contents of other
+ * framebuffers which could also have associated journal entries.
+ */
+ cogl_flush ();
_cogl_framebuffer_flush_state (framebuffer, 0);
_cogl_flush_face_winding ();
/* Disable any cached vertex arrays */
- _cogl_vertex_attribute_disable_cached_arrays ();
+ _cogl_attribute_disable_cached_arrays ();
}
void
return g_quark_from_static_string ("cogl-error-quark");
}
+/* Until Cogl becomes responsible for handling swap-buffer requests
+ * this API is used by Clutter to notify us when it issues a
+ * swap-buffer on our behalf. */
+void
+_cogl_swap_buffers_notify (void)
+{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ _cogl_framebuffer_swap_notify (_cogl_get_framebuffer ());
+}
#include <cogl/cogl-index-array.h>
#include <cogl/cogl-vertex-array.h>
#include <cogl/cogl-indices.h>
-#include <cogl/cogl-vertex-attribute.h>
+#include <cogl/cogl-attribute.h>
#include <cogl/cogl-primitive.h>
#include <cogl/cogl-pipeline.h>
#endif
void
_cogl_onscreen_clutter_backend_set_size (int width, int height);
+void
+_cogl_swap_buffers_notify (void);
+
G_END_DECLS
#undef __COGL_H_INSIDE__
#include "cogl-texture-private.h"
#include "cogl-primitives-private.h"
#include "cogl-private.h"
-#include "cogl-vertex-attribute-private.h"
+#include "cogl-attribute-private.h"
#include "tesselator/tesselator.h"
#include <string.h>
{
node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
- cogl_draw_vertex_attributes (COGL_VERTICES_MODE_LINE_STRIP,
+ cogl_draw_attributes (COGL_VERTICES_MODE_LINE_STRIP,
0, node->path_size,
data->stroke_vbo_attributes[path_num],
NULL);
_cogl_path_build_fill_vbo (path);
- _cogl_draw_indexed_vertex_attributes_array (COGL_VERTICES_MODE_TRIANGLES,
- 0, /* first_vertex */
- path->data->fill_vbo_n_indices,
- path->data->fill_vbo_indices,
- path->data->fill_vbo_attributes);
+ _cogl_draw_indexed_attributes_array
+ (COGL_VERTICES_MODE_TRIANGLES,
+ 0, /* first_vertex */
+ path->data->fill_vbo_n_indices,
+ path->data->fill_vbo_indices,
+ path->data->fill_vbo_attributes,
+ COGL_DRAW_SKIP_JOURNAL_FLUSH |
+ COGL_DRAW_SKIP_PIPELINE_VALIDATION |
+ COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH);
}
void
will have set up a scissor for the minimum bounding box of
all of the clips. That box will likely mean that this
_cogl_clear won't need to clear the entire
- buffer. _cogl_clear is used instead of cogl_clear because
+ buffer. _cogl_clear4f is used instead of cogl_clear because
it won't try to flush the journal */
- _cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL);
+ _cogl_clear4f (COGL_BUFFER_BIT_STENCIL, 0, 0, 0, 0);
else
{
/* Just clear the bounding box */
void
cogl2_path_fill (CoglPath *path)
{
+ CoglFramebuffer *framebuffer;
+
g_return_if_fail (cogl_is_path (path));
if (path->data->path_nodes->len == 0)
return;
- _cogl_journal_flush ();
+ framebuffer = _cogl_get_framebuffer ();
+
+ _cogl_framebuffer_flush_journal (framebuffer);
/* NB: _cogl_framebuffer_flush_state may disrupt various state (such
* as the pipeline state) when flushing the clip stack, so should
* always be done first when preparing to draw. */
- _cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0);
+ _cogl_framebuffer_flush_state (framebuffer, 0);
_cogl_path_fill_nodes (path);
}
g_array_free (tess.vertices, TRUE);
data->fill_vbo_attributes[0] =
- cogl_vertex_attribute_new (data->fill_vbo,
+ cogl_attribute_new (data->fill_vbo,
"cogl_position_in",
sizeof (CoglPathTesselatorVertex),
G_STRUCT_OFFSET (CoglPathTesselatorVertex, x),
2, /* n_components */
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ COGL_ATTRIBUTE_TYPE_FLOAT);
data->fill_vbo_attributes[1] =
- cogl_vertex_attribute_new (data->fill_vbo,
+ cogl_attribute_new (data->fill_vbo,
"cogl_tex_coord0_in",
sizeof (CoglPathTesselatorVertex),
G_STRUCT_OFFSET (CoglPathTesselatorVertex, s),
2, /* n_components */
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ COGL_ATTRIBUTE_TYPE_FLOAT);
/* NULL terminator */
data->fill_vbo_attributes[2] = NULL;
sizeof (floatVec2),
NULL);
- vbo_p = cogl_buffer_map (COGL_BUFFER (data->stroke_vbo),
- COGL_BUFFER_ACCESS_WRITE,
- COGL_BUFFER_MAP_HINT_DISCARD);
+ vbo_p =
+ _cogl_buffer_map_for_fill_or_fallback (COGL_BUFFER (data->stroke_vbo));
/* Copy the vertices in and count the number of sub paths. Each sub
path will form a separate attribute so we can paint the disjoint
n_attributes++;
}
- cogl_buffer_unmap (COGL_BUFFER (data->stroke_vbo));
+ _cogl_buffer_unmap_for_fill_or_fallback (COGL_BUFFER (data->stroke_vbo));
- data->stroke_vbo_attributes = g_new (CoglVertexAttribute *, n_attributes);
+ data->stroke_vbo_attributes = g_new (CoglAttribute *, n_attributes);
/* Now we can loop the sub paths again to create the attributes */
for (i = 0, path_start = 0;
node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
data->stroke_vbo_attributes[i] =
- cogl_vertex_attribute_new (data->stroke_vbo,
- "cogl_position_in",
- sizeof (floatVec2),
- path_start * sizeof (floatVec2),
- 2, /* n_components */
- COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT);
+ cogl_attribute_new (data->stroke_vbo,
+ "cogl_position_in",
+ sizeof (floatVec2),
+ path_start * sizeof (floatVec2),
+ 2, /* n_components */
+ COGL_ATTRIBUTE_TYPE_FLOAT);
}
data->stroke_vbo_n_attributes = n_attributes;
COGL_FEATURE_BEGIN (vbos, 1, 5,
"ARB\0",
"vertex_buffer_object\0",
- COGL_FEATURE_VBOS,
+ COGL_FEATURE_VBOS |
+ COGL_FEATURE_MAP_BUFFER_FOR_READ |
+ COGL_FEATURE_MAP_BUFFER_FOR_WRITE,
0)
COGL_FEATURE_FUNCTION (void, glGenBuffers,
(GLuint n,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const GLvoid* pixels))
COGL_FEATURE_END ()
+
+COGL_FEATURE_BEGIN (map_buffer, 255, 255,
+ "OES\0",
+ "mapbuffer\0",
+ COGL_FEATURE_MAP_BUFFER_FOR_WRITE,
+ 0)
+COGL_FEATURE_FUNCTION (void *, glMapBuffer,
+ (GLenum target,
+ GLenum access))
+COGL_FEATURE_FUNCTION (GLboolean, glUnmapBuffer,
+ (GLenum target))
+COGL_FEATURE_END ()
flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC;
#endif
- /* FIXME: HACK: We are in the process of overhauling the GLES 2 backend
- * and consolidating with a CoglMaterial GLSL backend. Currently though
- * use of CoglBuffers with GLES 2 is broken. */
-#ifndef HAVE_COGL_GLES2
flags |= COGL_FEATURE_VBOS;
-#endif
/* Both GLES 1.1 and GLES 2.0 support point sprites in core */
flags |= COGL_FEATURE_POINT_SPRITE;
_cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
}
+static CoglBitmap *
+prepare_bitmap_alignment_for_upload (CoglBitmap *src_bmp)
+{
+ CoglPixelFormat format = _cogl_bitmap_get_format (src_bmp);
+ int bpp = _cogl_get_format_bpp (format);
+ int src_rowstride = _cogl_bitmap_get_rowstride (src_bmp);
+ int width = _cogl_bitmap_get_width (src_bmp);
+ int alignment = 1;
+
+ if (src_rowstride == 0)
+ return cogl_object_ref (src_bmp);
+
+ /* Work out the alignment of the source rowstride */
+ alignment = 1 << (_cogl_util_ffs (src_rowstride) - 1);
+ alignment = MIN (alignment, 8);
+
+ /* If the aligned data equals the rowstride then we can upload from
+ the bitmap directly using GL_UNPACK_ALIGNMENT */
+ if (((width * bpp + alignment - 1) & ~(alignment - 1)) == src_rowstride)
+ return cogl_object_ref (src_bmp);
+ /* Otherwise we need to copy the bitmap to pack the alignment
+ because GLES has no GL_ROW_LENGTH */
+ else
+ return _cogl_bitmap_copy (src_bmp);
+}
+
void
_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
GLuint gl_handle,
CoglBitmap *slice_bmp;
int rowstride;
- /* NB: GLES doesn't support the GL_UNPACK_ROW_LENGTH,
- * GL_UNPACK_SKIP_PIXELS or GL_UNPACK_SKIP_ROWS pixel store options
- * so we can't directly source a sub-region from source_bmp, we need
- * to use a transient bitmap instead. */
-
- /* FIXME: optimize by not copying to intermediate slice bitmap when
- * source rowstride = bpp * width and the texture image is not
- * sliced */
-
- /* Setup temp bitmap for slice subregion */
- rowstride = bpp * width;
- slice_bmp = _cogl_bitmap_new_from_data (g_malloc (rowstride * height),
- source_format,
- width,
- height,
- rowstride,
- (CoglBitmapDestroyNotify)
- g_free,
- NULL);
+ /* If we are copying a sub region of the source bitmap then we need
+ to copy it because GLES does not support GL_UNPACK_ROW_LENGTH */
+ if (src_x != 0 || src_y != 0 ||
+ width != _cogl_bitmap_get_width (source_bmp) ||
+ height != _cogl_bitmap_get_height (source_bmp))
+ {
+ rowstride = bpp * width;
+ rowstride = (rowstride + 3) & ~3;
+ slice_bmp =
+ _cogl_bitmap_new_from_data (g_malloc (height * rowstride),
+ source_format,
+ width, height,
+ rowstride,
+ (CoglBitmapDestroyNotify) g_free,
+ NULL);
+ _cogl_bitmap_copy_subregion (source_bmp,
+ slice_bmp,
+ src_x, src_y,
+ 0, 0, /* dst_x/y */
+ width, height);
+ }
+ else
+ {
+ slice_bmp = prepare_bitmap_alignment_for_upload (source_bmp);
+ rowstride = _cogl_bitmap_get_rowstride (slice_bmp);
+ }
/* Setup gl alignment to match rowstride and top-left corner */
_cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
- /* Copy subregion data */
- _cogl_bitmap_copy_subregion (source_bmp,
- slice_bmp,
- src_x,
- src_y,
- 0, 0,
- width, height);
-
data = _cogl_bitmap_bind (slice_bmp, COGL_BUFFER_ACCESS_READ, 0);
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
GLuint source_gl_type)
{
int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
- int rowstride = _cogl_bitmap_get_rowstride (source_bmp);
+ int rowstride;
int bmp_width = _cogl_bitmap_get_width (source_bmp);
int bmp_height = _cogl_bitmap_get_height (source_bmp);
CoglBitmap *bmp;
guint8 *data;
- /* If the rowstride can't be specified with just GL_ALIGNMENT alone
- then we need to copy the bitmap because there is no GL_ROW_LENGTH */
- if (rowstride / bpp != bmp_width)
- {
- bmp = _cogl_bitmap_new_from_data (g_malloc (rowstride * bmp_height),
- _cogl_bitmap_get_format (source_bmp),
- bmp_width,
- bmp_height,
- rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- _cogl_bitmap_copy_subregion (source_bmp,
- bmp,
- 0, 0, 0, 0,
- bmp_width,
- bmp_height);
- }
- else
- bmp = cogl_object_ref (source_bmp);
+ bmp = prepare_bitmap_alignment_for_upload (source_bmp);
+ rowstride = _cogl_bitmap_get_rowstride (bmp);
/* Setup gl alignment to match rowstride and top-left corner */
_cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
_COGL_GET_CONTEXT (ctxt, COGL_INVALID_HANDLE);
- tex->vtable = &cogl_texture_pixmap_x11_vtable;
+ _cogl_texture_init (tex, &cogl_texture_pixmap_x11_vtable);
tex_pixmap->pixmap = pixmap;
tex_pixmap->image = NULL;
* a dummy, offscreen override-redirect window to which we can always
* fall back if no stage is available */
- xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
+ xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11);
if (xvisinfo == NULL)
{
g_critical ("Unable to find suitable GL visual.");
#endif /* COGL_HAS_XLIB_SUPPORT */
}
-static void
-clutter_backend_egl_redraw (ClutterBackend *backend,
- ClutterStage *stage)
-{
- ClutterStageWindow *impl;
-
- impl = _clutter_stage_get_window (stage);
- if (!impl)
- return;
-
- g_assert (CLUTTER_IS_STAGE_EGL (impl));
-
- _clutter_stage_egl_redraw (CLUTTER_STAGE_EGL (impl), stage);
-}
-
#ifndef COGL_HAS_XLIB_SUPPORT
static ClutterDeviceManager *
clutter_backend_egl_get_device_manager (ClutterBackend *backend)
static ClutterFeatureFlags
clutter_backend_egl_get_features (ClutterBackend *backend)
{
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
const gchar *egl_extensions = NULL;
const gchar *gl_extensions = NULL;
ClutterFeatureFlags flags;
g_assert (backend_egl->egl_context != NULL);
#ifdef COGL_HAS_XLIB_SUPPORT
- flags = clutter_backend_x11_get_features (backend);
- flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
+ {
+ ClutterBackendClass *parent_class;
+
+ parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
+ flags = parent_class->get_features (backend);
+ flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
+ }
#else
flags = CLUTTER_FEATURE_STAGE_STATIC;
#endif
{
#ifdef COGL_HAS_XLIB_SUPPORT
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterEventTranslator *translator;
ClutterStageWindow *stage;
ClutterStageX11 *stage_x11;
/* copy backend data into the stage */
stage_x11 = CLUTTER_STAGE_X11 (stage);
stage_x11->wrapper = wrapper;
+ stage_x11->backend = backend_x11;
+
+ translator = CLUTTER_EVENT_TRANSLATOR (stage_x11);
+ _clutter_backend_add_event_translator (backend, translator);
CLUTTER_NOTE (MISC, "EGLX stage created (display:%p, screen:%d, root:%u)",
backend_x11->xdpy,
backend_class->create_stage = clutter_backend_egl_create_stage;
backend_class->create_context = clutter_backend_egl_create_context;
backend_class->ensure_context = clutter_backend_egl_ensure_context;
- backend_class->redraw = clutter_backend_egl_redraw;
#ifdef COGL_HAS_XLIB_SUPPORT
backendx11_class->get_visual_info = clutter_backend_egl_get_visual_info;
clicked = FALSE;
}
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
}
/* Pop an event off the queue if any */
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
- CLUTTER_NOTE (BACKEND, "Unrealizing stage");
+ CLUTTER_NOTE (BACKEND, "Unrealizing EGL stage [%p]", stage_egl);
clutter_x11_trap_x_errors ();
- if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
- {
- XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
- stage_x11->xwin = None;
- }
- else
- stage_x11->xwin = None;
-
if (stage_egl->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (clutter_egl_get_egl_display (), stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
+ _clutter_stage_x11_destroy_window_untrapped (stage_x11);
+
XSync (backend_x11->xdpy, False);
clutter_x11_untrap_x_errors ();
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackend *backend;
ClutterBackendEGL *backend_egl;
- ClutterBackendX11 *backend_x11;
EGLDisplay edpy;
- CLUTTER_NOTE (BACKEND, "Realizing main stage");
+ CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]",
+ G_OBJECT_TYPE_NAME (stage_egl),
+ stage_egl);
backend = clutter_get_default_backend ();
backend_egl = CLUTTER_BACKEND_EGL (backend);
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
edpy = clutter_egl_get_egl_display ();
- if (stage_x11->xwin == None)
- {
- XSetWindowAttributes xattr;
- unsigned long mask;
- XVisualInfo *xvisinfo;
- gfloat width, height;
-
- CLUTTER_NOTE (MISC, "Creating stage X window");
-
- xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
- if (xvisinfo == NULL)
- {
- g_critical ("Unable to find suitable GL visual.");
- return FALSE;
- }
-
- /* window attributes */
- xattr.background_pixel = WhitePixel (backend_x11->xdpy,
- backend_x11->xscreen_num);
- xattr.border_pixel = 0;
- xattr.colormap = XCreateColormap (backend_x11->xdpy,
- backend_x11->xwin_root,
- xvisinfo->visual,
- AllocNone);
- mask = CWBorderPixel | CWColormap;
-
- /* Call get_size - this will either get the geometry size (which
- * before we create the window is set to 640x480), or if a size
- * is set, it will get that. This lets you set a size on the
- * stage before it's realized.
- */
- clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper),
- &width,
- &height);
- stage_x11->xwin_width = (gint)width;
- stage_x11->xwin_height = (gint)height;
-
- stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
- backend_x11->xwin_root,
- 0, 0,
- stage_x11->xwin_width,
- stage_x11->xwin_height,
- 0,
- xvisinfo->depth,
- InputOutput,
- xvisinfo->visual,
- mask, &xattr);
-
- CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
- stage_window,
- (unsigned int) stage_x11->xwin,
- stage_x11->xwin_width,
- stage_x11->xwin_height);
-
- XFree (xvisinfo);
- }
+ if (!_clutter_stage_x11_create_window (stage_x11))
+ return FALSE;
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
if (stage_egl->egl_surface == EGL_NO_SURFACE)
g_warning ("Unable to create an EGL surface");
- if (clutter_x11_has_event_retrieval ())
- {
- if (clutter_x11_has_xinput ())
- {
- XSelectInput (backend_x11->xdpy, stage_x11->xwin,
- StructureNotifyMask |
- FocusChangeMask |
- ExposureMask |
- EnterWindowMask | LeaveWindowMask |
- PropertyChangeMask);
-#ifdef USE_XINPUT
- _clutter_x11_select_events (stage_x11->xwin);
-#endif
- }
- else
- XSelectInput (backend_x11->xdpy, stage_x11->xwin,
- StructureNotifyMask |
- FocusChangeMask |
- ExposureMask |
- PointerMotionMask |
- KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask |
- EnterWindowMask | LeaveWindowMask |
- PropertyChangeMask);
- }
-
- /* no user resize... */
- clutter_stage_x11_fix_window_size (stage_x11,
- stage_x11->xwin_width,
- stage_x11->xwin_height);
- clutter_stage_x11_set_wm_protocols (stage_x11);
-
return clutter_stage_egl_parent_iface->realize (stage_window);
}
}
static void
-clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
+clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
{
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
+ ClutterBackend *backend = clutter_get_default_backend ();
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterActor *wrapper;
+ EGLSurface egl_surface;
+ gboolean may_use_clipped_redraw;
+ gboolean use_clipped_redraw;
#ifdef COGL_HAS_X11_SUPPORT
- clutter_stage_egl_parent_iface = g_type_interface_peek_parent (iface);
-
- iface->realize = clutter_stage_egl_realize;
- iface->unrealize = clutter_stage_egl_unrealize;
-
- /* the rest is inherited from ClutterStageX11 */
-
-#else /* COGL_HAS_X11_SUPPORT */
-
- iface->realize = clutter_stage_egl_realize;
- iface->unrealize = clutter_stage_egl_unrealize;
- iface->set_fullscreen = clutter_stage_egl_set_fullscreen;
- iface->set_title = clutter_stage_egl_set_title;
- iface->set_cursor_visible = clutter_stage_egl_set_cursor_visible;
- iface->get_wrapper = clutter_stage_egl_get_wrapper;
- iface->get_geometry = clutter_stage_egl_get_geometry;
- iface->resize = clutter_stage_egl_resize;
- iface->show = clutter_stage_egl_show;
- iface->hide = clutter_stage_egl_hide;
-
-#endif /* COGL_HAS_X11_SUPPORT */
-
- iface->add_redraw_clip = clutter_stage_egl_add_redraw_clip;
- iface->has_redraw_clips = clutter_stage_egl_has_redraw_clips;
- iface->ignoring_redraw_clips = clutter_stage_egl_ignoring_redraw_clips;
-}
-
-#ifdef COGL_HAS_X11_SUPPORT
-static void
-clutter_stage_egl_dispose (GObject *gobject)
-{
- G_OBJECT_CLASS (_clutter_stage_egl_parent_class)->dispose (gobject);
-}
-
-static void
-_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->dispose = clutter_stage_egl_dispose;
-}
-
-static void
-_clutter_stage_egl_init (ClutterStageEGL *stage)
-{
- stage->egl_surface = EGL_NO_SURFACE;
-}
-
-#else /* COGL_HAS_X11_SUPPORT */
-
-static void
-_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
-{
-}
-
-static void
-_clutter_stage_egl_init (ClutterStageEGL *stage)
-{
- /* Without X we only support one surface and that is associated
- * with the backend directly instead of the stage */
-}
-
-#endif /* COGL_HAS_X11_SUPPORT */
-
-void
-_clutter_stage_egl_redraw (ClutterStageEGL *stage_egl,
- ClutterStage *stage)
-{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
- ClutterActor *wrapper;
- EGLSurface egl_surface;
- gboolean may_use_clipped_redraw;
- gboolean use_clipped_redraw;
-#ifdef COGL_HAS_X11_SUPPORT
- ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
+ ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
egl_surface = stage_egl->egl_surface;
stage_egl->bounding_redraw_clip.y,
stage_egl->bounding_redraw_clip.width,
stage_egl->bounding_redraw_clip.height);
- _clutter_stage_do_paint (stage, &stage_egl->bounding_redraw_clip);
+ _clutter_stage_do_paint (CLUTTER_STAGE (wrapper),
+ &stage_egl->bounding_redraw_clip);
cogl_clip_pop ();
}
else
- _clutter_stage_do_paint (stage, NULL);
+ _clutter_stage_do_paint (CLUTTER_STAGE (wrapper), NULL);
if (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS &&
may_use_clipped_redraw)
cogl_push_matrix ();
cogl_matrix_init_identity (&modelview);
- _clutter_actor_apply_modelview_transform (CLUTTER_ACTOR (stage),
- &modelview);
+ _clutter_actor_apply_modelview_transform (wrapper, &modelview);
cogl_set_modelview_matrix (&modelview);
cogl_set_source (outline);
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINE_LOOP,
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
eglSwapBuffers (backend_egl->edpy, egl_surface);
CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
+ _cogl_swap_buffers_notify ();
}
/* reset the redraw clipping for the next paint... */
stage_egl->frame_count++;
}
+
+static void
+clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
+{
+#ifdef COGL_HAS_X11_SUPPORT
+ clutter_stage_egl_parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->realize = clutter_stage_egl_realize;
+ iface->unrealize = clutter_stage_egl_unrealize;
+
+ /* the rest is inherited from ClutterStageX11 */
+
+#else /* COGL_HAS_X11_SUPPORT */
+
+ iface->realize = clutter_stage_egl_realize;
+ iface->unrealize = clutter_stage_egl_unrealize;
+ iface->set_fullscreen = clutter_stage_egl_set_fullscreen;
+ iface->set_title = clutter_stage_egl_set_title;
+ iface->set_cursor_visible = clutter_stage_egl_set_cursor_visible;
+ iface->get_wrapper = clutter_stage_egl_get_wrapper;
+ iface->get_geometry = clutter_stage_egl_get_geometry;
+ iface->resize = clutter_stage_egl_resize;
+ iface->show = clutter_stage_egl_show;
+ iface->hide = clutter_stage_egl_hide;
+
+#endif /* COGL_HAS_X11_SUPPORT */
+
+ iface->add_redraw_clip = clutter_stage_egl_add_redraw_clip;
+ iface->has_redraw_clips = clutter_stage_egl_has_redraw_clips;
+ iface->ignoring_redraw_clips = clutter_stage_egl_ignoring_redraw_clips;
+ iface->redraw = clutter_stage_egl_redraw;
+}
+
+#ifdef COGL_HAS_X11_SUPPORT
+static void
+clutter_stage_egl_dispose (GObject *gobject)
+{
+ G_OBJECT_CLASS (_clutter_stage_egl_parent_class)->dispose (gobject);
+}
+
+static void
+_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = clutter_stage_egl_dispose;
+}
+
+static void
+_clutter_stage_egl_init (ClutterStageEGL *stage)
+{
+ stage->egl_surface = EGL_NO_SURFACE;
+}
+
+#else /* COGL_HAS_X11_SUPPORT */
+
+static void
+_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
+{
+}
+
+static void
+_clutter_stage_egl_init (ClutterStageEGL *stage)
+{
+ /* Without X we only support one surface and that is associated
+ * with the backend directly instead of the stage */
+}
+
+#endif /* COGL_HAS_X11_SUPPORT */
#include "clutter-egl-headers.h"
#include "clutter-backend-egl.h"
+G_BEGIN_DECLS
#define CLUTTER_TYPE_STAGE_EGL (_clutter_stage_egl_get_type ())
#define CLUTTER_STAGE_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_EGL, ClutterStageEGL))
GType _clutter_stage_egl_get_type (void) G_GNUC_CONST;
-void _clutter_stage_egl_redraw (ClutterStageEGL *stage_egl,
- ClutterStage *stage);
+G_END_DECLS
#endif /* __CLUTTER_STAGE_EGL_H__ */
static void
queue_event (ClutterEvent *event)
{
- ClutterMainContext *context;
-
if (event == NULL)
return;
- context = _clutter_context_get_default ();
- g_queue_push_head (context->events_queue, event);
+ _clutter_event_push (event, FALSE);
}
static void
cogl_flush ();
eglWaitGL();
eglSwapBuffers (backend_egl->edpy, stage_egl->egl_surface);
+ _cogl_swap_buffers_notify ();
}
static ClutterActor *
#include <GL/gl.h>
#include "clutter-backend-glx.h"
-#include "clutter-event-glx.h"
#include "clutter-stage-glx.h"
#include "clutter-glx.h"
#include "clutter-profile.h"
#include "clutter-debug.h"
+#include "clutter-event-translator.h"
#include "clutter-event.h"
#include "clutter-main.h"
#include "clutter-private.h"
#include "cogl/cogl.h"
+#define clutter_backend_glx_get_type _clutter_backend_glx_get_type
-G_DEFINE_TYPE (ClutterBackendGLX, _clutter_backend_glx, CLUTTER_TYPE_BACKEND_X11);
+G_DEFINE_TYPE (ClutterBackendGLX, clutter_backend_glx, CLUTTER_TYPE_BACKEND_X11);
/* singleton object */
static ClutterBackendGLX *backend_singleton = NULL;
clutter_backend_glx_pre_parse (ClutterBackend *backend,
GError **error)
{
+ ClutterBackendClass *parent_class =
+ CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
const gchar *env_string;
env_string = g_getenv ("CLUTTER_VBLANK");
env_string = NULL;
}
- return clutter_backend_x11_pre_parse (backend, error);
+ return parent_class->pre_parse (backend, error);
}
static gboolean
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
- ClutterBackendClass *backend_class =
- CLUTTER_BACKEND_CLASS (_clutter_backend_glx_parent_class);
+ ClutterBackendClass *parent_class =
+ CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
int glx_major, glx_minor;
- if (!backend_class->post_parse (backend, error))
+ if (!parent_class->post_parse (backend, error))
return FALSE;
if (!glXQueryExtension (backend_x11->xdpy,
/* XXX: Technically we should require >= GLX 1.3 support but for a long
* time Mesa has exported a hybrid GLX, exporting extensions specified
* to require GLX 1.3, but still reporting 1.2 via glXQueryVersion. */
- if (!glXQueryVersion (backend_x11->xdpy, &glx_major, &glx_minor)
- || !(glx_major == 1 && glx_minor >= 2))
+ if (!glXQueryVersion (backend_x11->xdpy, &glx_major, &glx_minor) ||
+ !(glx_major == 1 && glx_minor >= 2))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
clutter_backend_glx_add_options (ClutterBackend *backend,
GOptionGroup *group)
{
+ ClutterBackendClass *parent_class =
+ CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
+
g_option_group_add_entries (group, entries);
- clutter_backend_x11_add_options (backend, group);
+
+ parent_class->add_options (backend, group);
}
static void
if (backend_singleton)
backend_singleton = NULL;
- G_OBJECT_CLASS (_clutter_backend_glx_parent_class)->finalize (gobject);
+ G_OBJECT_CLASS (clutter_backend_glx_parent_class)->finalize (gobject);
}
static void
backend_glx->dummy_xwin = None;
}
- G_OBJECT_CLASS (_clutter_backend_glx_parent_class)->dispose (gobject);
+ G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject);
}
static GObject *
if (!backend_singleton)
{
- parent_class = G_OBJECT_CLASS (_clutter_backend_glx_parent_class);
+ parent_class = G_OBJECT_CLASS (clutter_backend_glx_parent_class);
retval = parent_class->constructor (gtype, n_params, params);
backend_singleton = CLUTTER_BACKEND_GLX (retval);
clutter_backend_glx_get_features (ClutterBackend *backend)
{
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
+ ClutterBackendClass *parent_class;
const gchar *glx_extensions = NULL;
const gchar *gl_extensions = NULL;
ClutterFeatureFlags flags;
gboolean use_dri = FALSE;
- flags = clutter_backend_x11_get_features (backend);
+ parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
+
+ flags = parent_class->get_features (backend);
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
/* this will make sure that the GL context exists */
void
_clutter_backend_glx_blit_sub_buffer (ClutterBackendGLX *backend_glx,
- GLXDrawable drawable,
- int x, int y, int width, int height)
+ GLXDrawable drawable,
+ int x,
+ int y,
+ int width,
+ int height)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend_glx);
}
}
-/*
- * FIXME: we should remove backend_class->redraw() and just
- * have stage_window_iface->redraw()
- */
-static void
-clutter_backend_glx_redraw (ClutterBackend *backend,
- ClutterStage *stage)
-{
- ClutterStageWindow *impl = _clutter_stage_get_window (stage);
-
- if (G_UNLIKELY (impl == NULL))
- {
- CLUTTER_NOTE (BACKEND, "Stage [%p] has no implementation", stage);
- return;
- }
-
- g_assert (CLUTTER_IS_STAGE_GLX (impl));
-
- _clutter_stage_glx_redraw (CLUTTER_STAGE_GLX (impl),
- stage);
-}
-
static ClutterStageWindow *
clutter_backend_glx_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterEventTranslator *translator;
ClutterStageWindow *stage_window;
ClutterStageX11 *stage_x11;
/* copy backend data into the stage */
stage_x11 = CLUTTER_STAGE_X11 (stage_window);
stage_x11->wrapper = wrapper;
+ stage_x11->backend = backend_x11;
+
+ translator = CLUTTER_EVENT_TRANSLATOR (stage_x11);
+ _clutter_backend_add_event_translator (backend, translator);
CLUTTER_NOTE (BACKEND,
"GLX stage created[%p] (dpy:%p, screen:%d, root:%u, wrap:%p)",
}
static void
-_clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
+clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
backend_class->create_stage = clutter_backend_glx_create_stage;
backend_class->add_options = clutter_backend_glx_add_options;
backend_class->get_features = clutter_backend_glx_get_features;
- backend_class->redraw = clutter_backend_glx_redraw;
backend_class->create_context = clutter_backend_glx_create_context;
backend_class->ensure_context = clutter_backend_glx_ensure_context;
backendx11_class->get_visual_info = clutter_backend_glx_get_visual_info;
- backendx11_class->handle_event = _clutter_backend_glx_handle_event;
}
static void
-_clutter_backend_glx_init (ClutterBackendGLX *backend_glx)
+clutter_backend_glx_init (ClutterBackendGLX *backend_glx)
{
-
}
/* every backend must implement this function */
+++ /dev/null
-/* Clutter.
- * An OpenGL based 'interactive canvas' library.
- * Authored By Matthew Allum <mallum@openedhand.com>
- * Copyright (C) 2006-2007 OpenedHand
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "clutter-x11.h"
-#include "clutter-stage-x11.h"
-#include "clutter-backend-x11.h"
-#include "clutter-stage-glx.h"
-#include "clutter-backend-glx.h"
-
-#include "clutter-private.h"
-#include "clutter-stage-private.h"
-
-#include <clutter/clutter-backend.h>
-#include <clutter/clutter-stage-manager.h>
-
-#include <X11/Xlib.h>
-
-#include <GL/glxext.h>
-
-#include <glib.h>
-
-gboolean
-_clutter_backend_glx_handle_event (ClutterBackendX11 *backend_x11,
- XEvent *xevent)
-{
-#ifdef GLX_INTEL_swap_event
- ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
- ClutterStageManager *stage_manager;
- GLXBufferSwapComplete *swap_complete_event;
- const GSList *l;
-
- if (xevent->type != (backend_glx->event_base + GLX_BufferSwapComplete))
- return FALSE; /* Unhandled */
-
- swap_complete_event = (GLXBufferSwapComplete *)xevent;
-
-#if 0
- {
- const char *event_name;
- if (swap_complete_event->event_type == GLX_EXCHANGE_COMPLETE_INTEL)
- event_name = "GLX_EXCHANGE_COMPLETE";
- else if (swap_complete_event->event_type == GLX_BLIT_COMPLETE_INTEL)
- event_name = "GLX_BLIT_COMPLETE";
- else
- {
- g_assert (swap_complete_event->event_type == GLX_FLIP_COMPLETE_INTEL);
- event_name = "GLX_FLIP_COMPLETE";
- }
-
- g_print ("XXX: clutter_backend_glx_event_handle event = %s\n",
- event_name);
- }
-#endif
-
- stage_manager = clutter_stage_manager_get_default ();
-
- for (l = clutter_stage_manager_peek_stages (stage_manager); l; l = l->next)
- {
- ClutterStageWindow *stage_win = _clutter_stage_get_window (l->data);
- ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_win);
- ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_win);
-
- if (stage_x11->xwin == swap_complete_event->drawable)
- {
- /* Early versions of the swap_event implementation in Mesa
- * deliver BufferSwapComplete event when not selected for,
- * so if we get a swap event we aren't expecting, just ignore it.
- *
- * https://bugs.freedesktop.org/show_bug.cgi?id=27962
- */
- if (stage_glx->pending_swaps > 0)
- stage_glx->pending_swaps--;
-
- return TRUE;
- }
- }
-
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
* may use the extension if it is possible.
*/
-
-
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
+
+#include "clutter-glx-texture-pixmap.h"
#include <string.h>
-#include "../x11/clutter-x11-texture-pixmap.h"
-#include "clutter-glx-texture-pixmap.h"
+#include <GL/glx.h>
+
+#include "x11/clutter-x11-texture-pixmap.h"
#include "cogl/winsys/cogl-texture-pixmap-x11.h"
G_DEFINE_TYPE (ClutterGLXTexturePixmap, \
clutter_glx_texture_pixmap, \
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
-
static void
clutter_glx_texture_pixmap_init (ClutterGLXTexturePixmap *self)
{
* GLX_EXT_texture_from_pixmap OpenGL extension or falling back to the
* slower software mechanism.
*
+ * Deprecated: 1.6: Use cogl_texture_pixmap_x11_is_using_tfp_extension()
+ * on the texture handle instead.
+ *
* Since: 0.8
*/
gboolean
* Return value: A new #ClutterGLXTexturePixmap bound to the given X Pixmap
*
* Since: 0.8
+ *
+ * Deprecated: 1.6: Use clutter_x11_texture_pixmap_new_with_pixmap() instead
*/
ClutterActor *
clutter_glx_texture_pixmap_new_with_pixmap (Pixmap pixmap)
* Return value: A new #ClutterGLXTexturePixmap bound to the given X window
*
* Since: 0.8
- **/
+ *
+ * Deprecated: 1.6: Use clutter_x11_texture_pixmap_new_with_window() instead
+ */
ClutterActor *
clutter_glx_texture_pixmap_new_with_window (Window window)
{
* Return value: A new #ClutterGLXTexturePixmap
*
* Since: 0.8
+ *
+ * Deprecated: 1.6: Use clutter_x11_texture_pixmap_new() instead
*/
ClutterActor *
clutter_glx_texture_pixmap_new (void)
#ifndef __CLUTTER_GLX_TEXTURE_PIXMAP_H__
#define __CLUTTER_GLX_TEXTURE_PIXMAP_H__
-#include <glib.h>
-#include <glib-object.h>
#include <clutter/x11/clutter-x11-texture-pixmap.h>
-#include <GL/glx.h>
+#if !defined(CLUTTER_COMPILATION) || defined(CLUTTER_DISABLE_DEPRECATED)
G_BEGIN_DECLS
* The #ClutterGLXTexturePixmapClass structure contains only private data
*
* Since: 0.8
+ *
+ * Deprecated: 1.6: Use #ClutterX11TexturePixmapClass instead
*/
struct _ClutterGLXTexturePixmapClass
{
* The #ClutterGLXTexturePixmap structure contains only private data
*
* Since: 0.8
+ *
+ * Deprecated: 1.6: Use #ClutterX11TexturePixmap instead
*/
struct _ClutterGLXTexturePixmap
{
G_END_DECLS
-#endif
+#endif /* !CLUTTER_DISABLE_DEPRECATED || CLUTTER_COMPILATION */
+
+#endif /* __CLUTTER_GLX_TEXTURE_PIXMAP_H__ */
#include "clutter-actor-private.h"
#include "clutter-debug.h"
+#include "clutter-device-manager.h"
#include "clutter-event.h"
#include "clutter-enum-types.h"
#include "clutter-feature.h"
#include <drm.h>
#endif
-static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
+static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
+static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
-static ClutterStageWindowIface *clutter_stage_glx_parent_iface = NULL;
+static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
+static ClutterEventTranslatorIface *clutter_event_translator_parent_iface = NULL;
+
+#define clutter_stage_glx_get_type _clutter_stage_glx_get_type
G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX,
- _clutter_stage_glx,
+ clutter_stage_glx,
CLUTTER_TYPE_STAGE_X11,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
- clutter_stage_window_iface_init));
+ clutter_stage_window_iface_init)
+ G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
+ clutter_event_translator_iface_init));
static void
clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
/* Note unrealize should free up any backend stage related resources */
- CLUTTER_NOTE (BACKEND, "Unrealizing stage");
+ CLUTTER_NOTE (BACKEND, "Unrealizing GLX stage [%p]", stage_glx);
clutter_x11_trap_x_errors ();
stage_glx->glxwin = None;
}
- if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
- {
- XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
- stage_x11->xwin = None;
- }
- else
- stage_x11->xwin = None;
+ _clutter_stage_x11_destroy_window_untrapped (stage_x11);
XSync (backend_x11->xdpy, False);
clutter_x11_untrap_x_errors ();
-
- CLUTTER_MARK ();
}
static gboolean
ClutterBackendX11 *backend_x11;
ClutterBackendGLX *backend_glx;
ClutterBackend *backend;
- int event_flags;
CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]",
G_OBJECT_TYPE_NAME (stage_window),
backend_glx = CLUTTER_BACKEND_GLX (backend);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
- if (stage_x11->xwin == None)
- {
- XSetWindowAttributes xattr;
- unsigned long mask;
- XVisualInfo *xvisinfo;
- gfloat width, height;
-
- CLUTTER_NOTE (MISC, "Creating stage X window");
-
- xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
- if (xvisinfo == NULL)
- {
- g_critical ("Unable to find suitable GL visual.");
- return FALSE;
- }
-
- /* window attributes */
- xattr.background_pixel = WhitePixel (backend_x11->xdpy,
- backend_x11->xscreen_num);
- xattr.border_pixel = 0;
- xattr.colormap = XCreateColormap (backend_x11->xdpy,
- backend_x11->xwin_root,
- xvisinfo->visual,
- AllocNone);
- mask = CWBorderPixel | CWColormap;
-
- /* Call get_size - this will either get the geometry size (which
- * before we create the window is set to 640x480), or if a size
- * is set, it will get that. This lets you set a size on the
- * stage before it's realized.
- */
- clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper),
- &width,
- &height);
- stage_x11->xwin_width = (gint)width;
- stage_x11->xwin_height = (gint)height;
-
- stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
- backend_x11->xwin_root,
- 0, 0,
- stage_x11->xwin_width,
- stage_x11->xwin_height,
- 0,
- xvisinfo->depth,
- InputOutput,
- xvisinfo->visual,
- mask, &xattr);
-
- CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
- stage_window,
- (unsigned int) stage_x11->xwin,
- stage_x11->xwin_width,
- stage_x11->xwin_height);
-
- XFree (xvisinfo);
- }
+ if (!_clutter_stage_x11_create_window (stage_x11))
+ return FALSE;
if (stage_glx->glxwin == None)
{
/* Try and create a GLXWindow to use with extensions dependent on
* GLX versions >= 1.3 that don't accept regular X Windows as GLX
- * drawables. */
+ * drawables.
+ */
if (glXQueryVersion (backend_x11->xdpy, &major, &minor) &&
major == 1 && minor >= 3 &&
_clutter_backend_glx_get_fbconfig (backend_glx, &config))
}
}
- /* the masks for the events we want to select on a stage window;
- * KeyPressMask and KeyReleaseMask are necessary even with XI1
- * because key events are broken with that extension, and will
- * be fixed by XI2
- */
- event_flags = StructureNotifyMask
- | FocusChangeMask
- | ExposureMask
- | PropertyChangeMask
- | EnterWindowMask
- | LeaveWindowMask
- | KeyPressMask
- | KeyReleaseMask;
-
- /* if we don't use XI1 then we also want core pointer events */
- if (!clutter_x11_has_xinput ())
- event_flags |= (ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
-#ifdef HAVE_XINPUT
- else
- _clutter_x11_select_events (stage_x11->xwin);
-#endif
-
- /* we unconditionally select input events even with event retrieval
- * disabled because we need to guarantee that the Clutter internal
- * state is maintained when calling clutter_x11_handle_event() without
- * requiring applications or embedding toolkits to select events
- * themselves. if we did that, we'd have to document the events to be
- * selected, and also update applications and embedding toolkits each
- * time we added a new mask, or a new class of events.
- *
- * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=998
- * for the rationale of why we did conditional selection. it is now
- * clear that a compositor should clear out the input region, since
- * it cannot assume a perfectly clean slate coming from us.
- *
- * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=2228
- * for an example of things that break if we do conditional event
- * selection.
- */
- XSelectInput (backend_x11->xdpy, stage_x11->xwin, event_flags);
-
#ifdef GLX_INTEL_swap_event
if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
{
- GLXDrawable drawable =
- stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin;
+ GLXDrawable drawable = stage_glx->glxwin
+ ? stage_glx->glxwin
+ : stage_x11->xwin;
- /* similarly to above, we unconditionally select this event
- * because we rely on it to advance the master clock, and
- * drive redraw/relayout, animations and event handling.
+ /* we unconditionally select this event because we rely on it to
+ * advance the master clock, and drive redraw/relayout, animations
+ * and event handling.
*/
glXSelectEvent (backend_x11->xdpy,
drawable,
}
#endif /* GLX_INTEL_swap_event */
- /* no user resize.. */
- clutter_stage_x11_fix_window_size (stage_x11,
- stage_x11->xwin_width,
- stage_x11->xwin_height);
- clutter_stage_x11_set_wm_protocols (stage_x11);
-
- CLUTTER_NOTE (BACKEND, "Successfully realized stage");
-
/* chain up to the StageX11 implementation */
- return clutter_stage_glx_parent_iface->realize (stage_window);
+ return clutter_stage_window_parent_iface->realize (stage_window);
}
static int
}
static void
-clutter_stage_glx_dispose (GObject *gobject)
-{
- G_OBJECT_CLASS (_clutter_stage_glx_parent_class)->dispose (gobject);
-}
-
-static void
-_clutter_stage_glx_class_init (ClutterStageGLXClass *klass)
+clutter_stage_glx_class_init (ClutterStageGLXClass *klass)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->dispose = clutter_stage_glx_dispose;
}
static void
-_clutter_stage_glx_init (ClutterStageGLX *stage)
+clutter_stage_glx_init (ClutterStageGLX *stage)
{
}
stage_glx->initialized_redraw_clip = TRUE;
}
-static void
-clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
-{
- clutter_stage_glx_parent_iface = g_type_interface_peek_parent (iface);
-
- iface->realize = clutter_stage_glx_realize;
- iface->unrealize = clutter_stage_glx_unrealize;
- iface->get_pending_swaps = clutter_stage_glx_get_pending_swaps;
-
- iface->add_redraw_clip = clutter_stage_glx_add_redraw_clip;
- iface->has_redraw_clips = clutter_stage_glx_has_redraw_clips;
- iface->ignoring_redraw_clips = clutter_stage_glx_ignoring_redraw_clips;
-
- /* the rest is inherited from ClutterStageX11 */
-}
-
#ifdef HAVE_DRM
static int
drm_wait_vblank(int fd, drm_wait_vblank_t *vbl)
}
}
-void
-_clutter_stage_glx_redraw (ClutterStageGLX *stage_glx,
- ClutterStage *stage)
+static void
+clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
{
- ClutterBackend *backend;
ClutterBackendX11 *backend_x11;
ClutterBackendGLX *backend_glx;
- ClutterStageX11 *stage_x11;
- GLXDrawable drawable;
- unsigned int video_sync_count;
- gboolean may_use_clipped_redraw;
- gboolean use_clipped_redraw;
+ ClutterStageX11 *stage_x11;
+ ClutterStageGLX *stage_glx;
+ GLXDrawable drawable;
+ unsigned int video_sync_count;
+ gboolean may_use_clipped_redraw;
+ gboolean use_clipped_redraw;
+
CLUTTER_STATIC_TIMER (painting_timer,
"Redrawing", /* parent */
"Painting actors",
"The time spent in _glx_blit_sub_buffer",
0 /* no application private data */);
- backend = clutter_get_default_backend ();
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
- backend_glx = CLUTTER_BACKEND_GLX (backend);
+ stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+ if (stage_x11->xwin == None)
+ return;
- stage_x11 = CLUTTER_STAGE_X11 (stage_glx);
+ stage_glx = CLUTTER_STAGE_GLX (stage_window);
+
+ backend_x11 = stage_x11->backend;
+ backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer);
* artefacts. See clutter-event-x11.c:event_translate for a
* detailed explanation */
G_LIKELY (stage_x11->clipped_redraws_cool_off == 0))
- may_use_clipped_redraw = TRUE;
+ {
+ may_use_clipped_redraw = TRUE;
+ }
else
may_use_clipped_redraw = FALSE;
stage_glx->bounding_redraw_clip.y,
stage_glx->bounding_redraw_clip.width,
stage_glx->bounding_redraw_clip.height);
- _clutter_stage_do_paint (stage, &stage_glx->bounding_redraw_clip);
+ _clutter_stage_do_paint (stage_x11->wrapper,
+ &stage_glx->bounding_redraw_clip);
cogl_clip_pop ();
}
else
- _clutter_stage_do_paint (stage, NULL);
+ _clutter_stage_do_paint (stage_x11->wrapper, NULL);
- if (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS &&
- may_use_clipped_redraw)
+ if (may_use_clipped_redraw &&
+ G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
{
- ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
static CoglMaterial *outline = NULL;
+ ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
+ ClutterActor *actor = CLUTTER_ACTOR (stage_x11->wrapper);
CoglHandle vbo;
float x_1 = clip->x;
float x_2 = clip->x + clip->width;
cogl_push_matrix ();
cogl_matrix_init_identity (&modelview);
- _clutter_actor_apply_modelview_transform (CLUTTER_ACTOR (stage),
- &modelview);
+ _clutter_actor_apply_modelview_transform (actor, &modelview);
cogl_set_modelview_matrix (&modelview);
cogl_set_source (outline);
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINE_LOOP,
cogl_flush ();
CLUTTER_TIMER_STOP (_clutter_uprof_context, painting_timer);
- if (stage_x11->xwin == None)
- return;
-
- drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin;
+ drawable = stage_glx->glxwin
+ ? stage_glx->glxwin
+ : stage_x11->xwin;
/* If we might ever use _clutter_backend_glx_blit_sub_buffer then we
* always need to keep track of the video_sync_count so that we can
{
ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
ClutterGeometry copy_area;
+ ClutterActor *actor;
CLUTTER_NOTE (BACKEND,
"_glx_blit_sub_buffer (window: 0x%lx, "
* in this case a full redraw should be queued by the resize
* anyway so it should only exhibit temporary artefacts.
*/
- copy_area.y = clutter_actor_get_height (CLUTTER_ACTOR (stage))
- - clip->y - clip->height;
+ actor = CLUTTER_ACTOR (stage_x11->wrapper);
+ copy_area.y = clutter_actor_get_height (actor)
+ - clip->y
+ - clip->height;
copy_area.x = clip->x;
copy_area.width = clip->width;
copy_area.height = clip->height;
* See where we call glXSwapBuffers for more details.
*/
glFinish ();
- wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
+ wait_for_vblank (backend_glx);
}
else if (backend_glx->get_video_sync)
{
* any waits if we can see that the video sync count has
* already progressed. */
if (backend_glx->last_video_sync_count == video_sync_count)
- wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
+ wait_for_vblank (backend_glx);
}
else
- wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
+ wait_for_vblank (backend_glx);
CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer);
_clutter_backend_glx_blit_sub_buffer (backend_glx,
copy_area.width,
copy_area.height);
CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer);
+
+ /* NB: unlike glXSwapBuffers, glXCopySubBuffer and
+ * glBlitFramebuffer don't issue an implicit glFlush() so we
+ * have to flush ourselves if we want the request to complete in
+ * finite amount of time since otherwise the driver can batch
+ * the command indefinitely. */
+ glFlush ();
}
else
{
*/
glFinish ();
- wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
+ wait_for_vblank (backend_glx);
}
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
glXSwapBuffers (backend_x11->xdpy, drawable);
CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
+
+ _cogl_swap_buffers_notify ();
}
backend_glx->last_video_sync_count = video_sync_count;
stage_glx->frame_count++;
}
+static void
+clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
+{
+ clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->realize = clutter_stage_glx_realize;
+ iface->unrealize = clutter_stage_glx_unrealize;
+ iface->get_pending_swaps = clutter_stage_glx_get_pending_swaps;
+
+ iface->add_redraw_clip = clutter_stage_glx_add_redraw_clip;
+ iface->has_redraw_clips = clutter_stage_glx_has_redraw_clips;
+ iface->ignoring_redraw_clips = clutter_stage_glx_ignoring_redraw_clips;
+ iface->redraw = clutter_stage_glx_redraw;
+
+ /* the rest is inherited from ClutterStageX11 */
+}
+
+static ClutterTranslateReturn
+clutter_stage_glx_translate_event (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *event)
+{
+#ifdef GLX_INTEL_swap_event
+ ClutterBackendGLX *backend_glx;
+ XEvent *xevent = native;
+
+ backend_glx = CLUTTER_BACKEND_GLX (clutter_get_default_backend ());
+
+ if (xevent->type == (backend_glx->event_base + GLX_BufferSwapComplete))
+ {
+ ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (translator);
+ ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (translator);
+ GLXBufferSwapComplete *swap_complete_event;
+
+ swap_complete_event = (GLXBufferSwapComplete *) xevent;
+
+ if (stage_x11->xwin == swap_complete_event->drawable)
+ {
+ /* Early versions of the swap_event implementation in Mesa
+ * deliver BufferSwapComplete event when not selected for,
+ * so if we get a swap event we aren't expecting, just ignore it.
+ *
+ * https://bugs.freedesktop.org/show_bug.cgi?id=27962
+ */
+ if (stage_glx->pending_swaps > 0)
+ stage_glx->pending_swaps--;
+
+ return CLUTTER_TRANSLATE_REMOVE;
+ }
+ }
+#endif
+
+ /* chain up to the common X11 implementation */
+ return clutter_event_translator_parent_iface->translate_event (translator,
+ native,
+ event);
+}
+
+static void
+clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface)
+{
+ clutter_event_translator_parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->translate_event = clutter_stage_glx_translate_event;
+}
GType _clutter_stage_glx_get_type (void) G_GNUC_CONST;
-void _clutter_stage_glx_redraw (ClutterStageGLX *stage_glx,
- ClutterStage *stage);
-
G_END_DECLS
#endif /* __CLUTTER_STAGE_H__ */
*
* Copyright (C) 2007-2008 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
+ * Copyright (C) 2011 Crystalnix <vgachkaylo@crystalnix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "clutter-osx.h"
#include "clutter-backend-osx.h"
+#include "clutter-device-manager-osx.h"
#include "clutter-stage-osx.h"
#include "clutter-debug.h"
CLUTTER_OSX_POOL_ALLOC();
- impl = clutter_stage_osx_new (backend, wrapper);
+ impl = _clutter_stage_osx_new (backend, wrapper);
CLUTTER_NOTE (BACKEND, "create_stage: impl=%p", impl);
return impl;
}
+static inline void
+clutter_backend_osx_create_device_manager (ClutterBackendOSX *backend_osx)
+{
+ if (backend_osx->device_manager != NULL)
+ return;
+
+ backend_osx->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_OSX,
+ "backend", CLUTTER_BACKEND(backend_osx),
+ NULL);
+}
+
+static ClutterDeviceManager *
+clutter_backend_osx_get_device_manager (ClutterBackend *backend)
+{
+ ClutterBackendOSX *backend_osx = CLUTTER_BACKEND_OSX (backend);
+
+ clutter_backend_osx_create_device_manager (backend_osx);
+
+ return backend_osx->device_manager;
+}
+
static void
clutter_backend_osx_init_events (ClutterBackend *backend)
{
+ ClutterBackendOSX *backend_osx = CLUTTER_BACKEND_OSX (backend);
+
+ if (backend_osx->device_manager != NULL)
+ return;
+
CLUTTER_NOTE (BACKEND, "init_events");
+ clutter_backend_osx_create_device_manager (backend_osx);
_clutter_events_osx_init ();
}
CLUTTER_OSX_POOL_RELEASE();
}
-static void
-clutter_backend_osx_redraw (ClutterBackend *backend, ClutterStage *wrapper)
-{
- ClutterStageWindow *impl = _clutter_stage_get_window (wrapper);
- ClutterStageOSX *stage_osx = CLUTTER_STAGE_OSX (impl);
-
- CLUTTER_OSX_POOL_ALLOC();
-
- [stage_osx->view setNeedsDisplay: YES];
-
- CLUTTER_OSX_POOL_RELEASE();
-}
-
/*************************************************************************/
static void
object_class->dispose = clutter_backend_osx_dispose;
- backend_class->post_parse = clutter_backend_osx_post_parse;
- backend_class->get_features = clutter_backend_osx_get_features;
- backend_class->create_stage = clutter_backend_osx_create_stage;
- backend_class->create_context = clutter_backend_osx_create_context;
- backend_class->ensure_context = clutter_backend_osx_ensure_context;
- backend_class->init_events = clutter_backend_osx_init_events;
- backend_class->redraw = clutter_backend_osx_redraw;
+ backend_class->post_parse = clutter_backend_osx_post_parse;
+ backend_class->get_features = clutter_backend_osx_get_features;
+ backend_class->create_stage = clutter_backend_osx_create_stage;
+ backend_class->create_context = clutter_backend_osx_create_context;
+ backend_class->ensure_context = clutter_backend_osx_ensure_context;
+ backend_class->init_events = clutter_backend_osx_init_events;
+ backend_class->get_device_manager = clutter_backend_osx_get_device_manager;
}
GType
*
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
+ * Copyright (C) 2011 Crystalnix <vgachkaylo@crystalnix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#define __CLUTTER_BACKEND_OSX_H__
#include "clutter-backend-private.h"
+#include "clutter-device-manager.h"
@class NSOpenGLPixelFormat, NSOpenGLContext;
{
ClutterBackend parent;
- NSOpenGLPixelFormat *pixel_format;
- NSOpenGLContext *context;
+ NSOpenGLPixelFormat *pixel_format;
+ NSOpenGLContext *context;
+ ClutterDeviceManager *device_manager;
};
struct _ClutterBackendOSXClass
--- /dev/null
+/*
+ * 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>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "clutter-backend-osx.h"
+#include "clutter-device-manager-osx.h"
+#include "clutter-device-manager-osx.h"
+#include "clutter-stage-osx.h"
+
+#include "clutter-backend.h"
+#include "clutter-debug.h"
+#include "clutter-device-manager-private.h"
+#include "clutter-private.h"
+
+enum
+{
+ PROP_0
+};
+
+G_DEFINE_TYPE (ClutterDeviceManagerOSX,
+ clutter_device_manager_osx,
+ CLUTTER_TYPE_DEVICE_MANAGER);
+
+static void
+clutter_device_manager_osx_constructed (GObject *gobject)
+{
+ ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (gobject);
+ ClutterDeviceManagerOSX *manager_osx;
+ ClutterInputDevice *device;
+
+ device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
+ "id", 0,
+ "name", "Core Pointer",
+ "device-type", CLUTTER_POINTER_DEVICE,
+ "device-mode", CLUTTER_INPUT_MODE_MASTER,
+ "has-cursor", TRUE,
+ "enabled", TRUE,
+ NULL);
+ CLUTTER_NOTE (BACKEND, "Added core pointer device");
+ _clutter_device_manager_add_device (manager, device);
+
+ device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
+ "id", 1,
+ "name", "Core Keyboard",
+ "device-type", CLUTTER_KEYBOARD_DEVICE,
+ "device-mode", CLUTTER_INPUT_MODE_MASTER,
+ "enabled", TRUE,
+ NULL);
+ CLUTTER_NOTE (BACKEND, "Added core keyboard device");
+ _clutter_device_manager_add_device (manager, device);
+
+ manager_osx = CLUTTER_DEVICE_MANAGER_OSX (manager);
+
+ _clutter_input_device_set_associated_device (manager_osx->core_pointer,
+ manager_osx->core_keyboard);
+ _clutter_input_device_set_associated_device (manager_osx->core_keyboard,
+ manager_osx->core_pointer);
+}
+
+static void
+clutter_device_manager_osx_add_device (ClutterDeviceManager *manager,
+ ClutterInputDevice *device)
+{
+ ClutterDeviceManagerOSX *manager_osx = CLUTTER_DEVICE_MANAGER_OSX (manager);
+ ClutterInputDeviceType device_type;
+ gboolean is_pointer, is_keyboard;
+
+ device_type = clutter_input_device_get_device_type (device);
+ is_pointer = (device_type == CLUTTER_POINTER_DEVICE) ? TRUE : FALSE;
+ is_keyboard = (device_type == CLUTTER_KEYBOARD_DEVICE) ? TRUE : FALSE;
+
+ manager_osx->devices = g_slist_prepend (manager_osx->devices, device);
+
+ if (is_pointer && manager_osx->core_pointer == NULL)
+ manager_osx->core_pointer = device;
+
+ if (is_keyboard && manager_osx->core_keyboard == NULL)
+ manager_osx->core_keyboard = device;
+}
+
+static void
+clutter_device_manager_osx_remove_device (ClutterDeviceManager *manager,
+ ClutterInputDevice *device)
+{
+ ClutterDeviceManagerOSX *manager_osx = CLUTTER_DEVICE_MANAGER_OSX (manager);
+
+ manager_osx->devices = g_slist_remove (manager_osx->devices, device);
+}
+
+static const GSList *
+clutter_device_manager_osx_get_devices (ClutterDeviceManager *manager)
+{
+ return CLUTTER_DEVICE_MANAGER_OSX (manager)->devices;
+}
+
+static ClutterInputDevice *
+clutter_device_manager_osx_get_core_device (ClutterDeviceManager *manager,
+ ClutterInputDeviceType type)
+{
+ ClutterDeviceManagerOSX *manager_osx;
+
+ manager_osx = CLUTTER_DEVICE_MANAGER_OSX (manager);
+
+ switch (type)
+ {
+ case CLUTTER_POINTER_DEVICE:
+ return manager_osx->core_pointer;
+
+ case CLUTTER_KEYBOARD_DEVICE:
+ return manager_osx->core_keyboard;
+
+ case CLUTTER_EXTENSION_DEVICE:
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static ClutterInputDevice *
+clutter_device_manager_osx_get_device (ClutterDeviceManager *manager,
+ gint id)
+{
+ ClutterDeviceManagerOSX *manager_osx = CLUTTER_DEVICE_MANAGER_OSX (manager);
+ GSList *l;
+
+ for (l = manager_osx->devices; l != NULL; l = l->next)
+ {
+ ClutterInputDevice *device = l->data;
+
+ if (clutter_input_device_get_device_id (device) == id)
+ return device;
+ }
+
+ return NULL;
+}
+
+static void
+clutter_device_manager_osx_class_init (ClutterDeviceManagerOSXClass *klass)
+{
+ ClutterDeviceManagerClass *manager_class;
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ gobject_class->constructed = clutter_device_manager_osx_constructed;
+
+ manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
+ manager_class->add_device = clutter_device_manager_osx_add_device;
+ manager_class->remove_device = clutter_device_manager_osx_remove_device;
+ manager_class->get_devices = clutter_device_manager_osx_get_devices;
+ manager_class->get_core_device = clutter_device_manager_osx_get_core_device;
+ manager_class->get_device = clutter_device_manager_osx_get_device;
+}
+
+static void
+clutter_device_manager_osx_init (ClutterDeviceManagerOSX *self)
+{
+}
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright (C) 2010 Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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>
+ */
+
+#ifndef __CLUTTER_DEVICE_MANAGER_OSX_H__
+#define __CLUTTER_DEVICE_MANAGER_OSX_H__
+
+#include <clutter/clutter-device-manager.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_DEVICE_MANAGER_OSX (clutter_device_manager_osx_get_type ())
+#define CLUTTER_DEVICE_MANAGER_OSX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_OSX, ClutterDeviceManagerOSX))
+#define CLUTTER_IS_DEVICE_MANAGER_OSX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_OSX))
+#define CLUTTER_DEVICE_MANAGER_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_OSX, ClutterDeviceManagerOSXClass))
+#define CLUTTER_IS_DEVICE_MANAGER_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_OSX))
+#define CLUTTER_DEVICE_MANAGER_OSX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_OSX, ClutterDeviceManagerOSXClass))
+
+typedef struct _ClutterDeviceManagerOSX ClutterDeviceManagerOSX;
+typedef struct _ClutterDeviceManagerOSXClass ClutterDeviceManagerOSXClass;
+
+struct _ClutterDeviceManagerOSX
+{
+ ClutterDeviceManager parent_instance;
+
+ GSList *devices;
+
+ ClutterInputDevice *core_pointer;
+ ClutterInputDevice *core_keyboard;
+};
+
+struct _ClutterDeviceManagerOSXClass
+{
+ ClutterDeviceManagerClass parent_class;
+};
+
+GType clutter_device_manager_osx_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __CLUTTER_DEVICE_MANAGER_OSX_H__ */
--- /dev/null
+/* source code taken from gtk+-2.22.1/gdk/quartz/gdkeventloop-quartz.c */
+/* Clutter - An OpenGL based 'interactive canvas' library.
+ * OSX backend - event loop
+ *
+ * Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2011 Crystalnix <vgachkaylo@crystalnix.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#include "config.h"
+
+#include "clutter-osx.h"
+#include "clutter-stage-osx.h"
+
+#import <AppKit/AppKit.h>
+#include <glib.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <clutter/clutter-debug.h>
+
+/*
+ * This file implementations integration between the GLib main loop and
+ * the native system of the Core Foundation run loop and Cocoa event
+ * handling. There are basically two different cases that we need to
+ * handle: either the GLib main loop is in control (the application
+ * has called gtk_main(), or is otherwise iterating the main loop), or
+ * CFRunLoop is in control (we are in a modal operation such as window
+ * resizing or drag-and-drop.)
+ *
+ * When the GLib main loop is in control we integrate in native event
+ * handling in two ways: first we add a GSource that handles checking
+ * whether there are native events available, translating native events
+ * to clutter events, and dispatching GDK events. Second we replace the
+ * "poll function" of the GLib main loop with our own version that knows
+ * how to wait for both the file descriptors and timeouts that GLib is
+ * interested in and also for incoming native events.
+ *
+ * When CFRunLoop is in control, we integrate in GLib main loop handling
+ * by adding a "run loop observer" that gives us notification at various
+ * points in the run loop cycle. We map these points onto the corresponding
+ * stages of the GLib main loop (prepare, check, dispatch), and make the
+ * appropriate calls into GLib.
+ *
+ * Both cases share a single problem: the OS X API's don't allow us to
+ * wait simultaneously for file descriptors and for events. So when we
+ * need to do a blocking wait that includes file descriptor activity, we
+ * push the actual work of calling select() to a helper thread (the
+ * "select thread") and wait for native events in the main thread.
+ *
+ * The main known limitation of this code is that if a callback is triggered
+ * via the OS X run loop while we are "polling" (in either case described
+ * above), iteration of the GLib main loop is not possible from within
+ * that callback. If the programmer tries to do so explicitly, then they
+ * will get a warning from GLib "main loop already active in another thread".
+ */
+
+/******* State for run loop iteration *******/
+
+/* Count of number of times we've gotten an "Entry" notification for
+ * our run loop observer.
+ */
+static int current_loop_level = 0;
+
+/* Run loop level at which we acquired ownership of the GLib main
+ * loop. See note in run_loop_entry(). -1 means that we don't have
+ * ownership
+ */
+static int acquired_loop_level = -1;
+
+/* Between run_loop_before_waiting() and run_loop_after_waiting();
+ * whether we we need to call select_thread_collect_poll()
+ */
+static gboolean run_loop_polling_async = FALSE;
+
+/* Between run_loop_before_waiting() and run_loop_after_waiting();
+ * max_prioritiy to pass to g_main_loop_check()
+ */
+static gint run_loop_max_priority;
+
+/* Timer that we've added to wake up the run loop when a GLib timeout
+ */
+static CFRunLoopTimerRef run_loop_timer = NULL;
+
+/* These are the file descriptors that are we are polling out of
+ * the run loop. (We keep the array around and reuse it to avoid
+ * constant allocations.)
+ */
+#define RUN_LOOP_POLLFDS_INITIAL_SIZE 16
+static GPollFD *run_loop_pollfds;
+static guint run_loop_pollfds_size; /* Allocated size of the array */
+static guint run_loop_n_pollfds; /* Number of file descriptors in the array */
+
+/******* Other global variables *******/
+
+/* Since we count on replacing the GLib main loop poll function as our
+ * method of integrating Cocoa event handling into the GLib main loop
+ * we need to make sure that the poll function is always called even
+ * when there are no file descriptors that need to be polled. To do
+ * this, we add a dummy GPollFD to our event source with a file
+ * descriptor of '-1'. Then any time that GLib is polling the event
+ * source, it will call our poll function.
+ */
+static GPollFD event_poll_fd;
+
+/* Current NSEvents that we've gotten from Cocoa but haven't yet converted
+ * to GdkEvents. We wait until our dispatch() function to do the conversion
+ * since the conversion can conceivably cause signals to be emmitted
+ * or other things that shouldn't happen inside a poll function.
+ */
+static GQueue *current_events;
+
+/* The default poll function for GLib; we replace this with our own
+ * Cocoa-aware version and then call the old version to do actual
+ * file descriptor polling. There's no actual need to chain to the
+ * old one; we could reimplement the same functionality from scratch,
+ * but since the default implementation does the right thing, why
+ * bother.
+ */
+static GPollFunc old_poll_func = NULL;
+
+/* Reference to the run loop of the main thread. (There is a unique
+ * CFRunLoop per thread.)
+ */
+static CFRunLoopRef main_thread_run_loop;
+
+/* Normally the Cocoa main loop maintains an NSAutoReleasePool and frees
+ * it on every iteration. Since we are replacing the main loop we have
+ * to provide this functionality ourself. We free and replace the
+ * auto-release pool in our sources prepare() function.
+ */
+static NSAutoreleasePool *autorelease_pool;
+
+/* Flag when we've called nextEventMatchingMask ourself; this triggers
+ * a run loop iteration, so we need to detect that and avoid triggering
+ * our "run the GLib main looop while the run loop is active machinery.
+ */
+static gboolean getting_events;
+
+/************************************************************
+ ********* Select Thread *********
+ ************************************************************/
+
+/* The states in our state machine, see comments in select_thread_func()
+ * for descriptiions of each state
+ */
+typedef enum {
+ BEFORE_START,
+ WAITING,
+ POLLING_QUEUED,
+ POLLING_RESTART,
+ POLLING_DESCRIPTORS,
+} SelectThreadState;
+
+static const char *const state_names[] = {
+ "BEFORE_START",
+ "WAITING",
+ "POLLING_QUEUED",
+ "POLLING_RESTART",
+ "POLLING_DESCRIPTORS"
+};
+
+static SelectThreadState select_thread_state = BEFORE_START;
+
+static pthread_t select_thread;
+static pthread_mutex_t select_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t select_thread_cond = PTHREAD_COND_INITIALIZER;
+
+#define SELECT_THREAD_LOCK() pthread_mutex_lock (&select_thread_mutex)
+#define SELECT_THREAD_UNLOCK() pthread_mutex_unlock (&select_thread_mutex)
+#define SELECT_THREAD_SIGNAL() pthread_cond_signal (&select_thread_cond)
+#define SELECT_THREAD_WAIT() pthread_cond_wait (&select_thread_cond, &select_thread_mutex)
+
+/* These are the file descriptors that the select thread is currently
+ * polling.
+ */
+static GPollFD *current_pollfds;
+static guint current_n_pollfds;
+
+/* These are the file descriptors that the select thread should pick
+ * up and start polling when it has a chance.
+ */
+static GPollFD *next_pollfds;
+static guint next_n_pollfds;
+
+/* Pipe used to wake up the select thread */
+static gint select_thread_wakeup_pipe[2];
+
+/* Run loop source used to wake up the main thread */
+static CFRunLoopSourceRef select_main_thread_source;
+
+/* Events */
+typedef enum {
+ CLUTTER_OSX_EVENT_SUBTYPE_EVENTLOOP
+} ClutterOSXEventSubType;
+
+static void
+select_thread_set_state (SelectThreadState new_state)
+{
+ gboolean old_state;
+
+ if (select_thread_state == new_state)
+ return;
+
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Select thread state: %s => %s\n", state_names[select_thread_state], state_names[new_state]);
+
+ old_state = select_thread_state;
+ select_thread_state = new_state;
+ if (old_state == WAITING && new_state != WAITING)
+ SELECT_THREAD_SIGNAL ();
+}
+
+static void
+signal_main_thread (void)
+{
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Waking up main thread\n");
+
+ /* If we are in nextEventMatchingMask, then we need to make sure an
+ * event gets queued, otherwise it's enough to simply wake up the
+ * main thread run loop
+ */
+ if (!run_loop_polling_async)
+ CFRunLoopSourceSignal (select_main_thread_source);
+
+ if (CFRunLoopIsWaiting (main_thread_run_loop))
+ CFRunLoopWakeUp (main_thread_run_loop);
+}
+
+static void *
+select_thread_func (void *arg)
+{
+ char c;
+
+ SELECT_THREAD_LOCK ();
+
+ while (TRUE)
+ {
+ switch (select_thread_state)
+ {
+ case BEFORE_START:
+ /* The select thread has not been started yet
+ */
+ g_assert_not_reached ();
+
+ case WAITING:
+ /* Waiting for a set of file descriptors to be submitted by the main thread
+ *
+ * => POLLING_QUEUED: main thread thread submits a set of file descriptors
+ */
+ SELECT_THREAD_WAIT ();
+ break;
+
+ case POLLING_QUEUED:
+ /* Waiting for a set of file descriptors to be submitted by the main thread
+ *
+ * => POLLING_DESCRIPTORS: select thread picks up the file descriptors to begin polling
+ */
+ if (current_pollfds)
+ g_free (current_pollfds);
+
+ current_pollfds = next_pollfds;
+ current_n_pollfds = next_n_pollfds;
+
+ next_pollfds = NULL;
+ next_n_pollfds = 0;
+
+ select_thread_set_state (POLLING_DESCRIPTORS);
+ break;
+
+ case POLLING_RESTART:
+ /* Select thread is currently polling a set of file descriptors, main thread has
+ * began a new iteration with the same set of file descriptors. We don't want to
+ * wake the select thread up and wait for it to restart immediately, but to avoid
+ * a race (described below in select_thread_start_polling()) we need to recheck after
+ * polling completes.
+ *
+ * => POLLING_DESCRIPTORS: select completes, main thread rechecks by polling again
+ * => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
+ */
+ select_thread_set_state (POLLING_DESCRIPTORS);
+ break;
+
+ case POLLING_DESCRIPTORS:
+ /* In the process of polling the file descriptors
+ *
+ * => WAITING: polling completes when a file descriptor becomes active
+ * => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
+ * => POLLING_RESTART: main thread begins a new iteration with the same set file descriptors
+ */
+ SELECT_THREAD_UNLOCK ();
+ old_poll_func (current_pollfds, current_n_pollfds, -1);
+ SELECT_THREAD_LOCK ();
+
+ read (select_thread_wakeup_pipe[0], &c, 1);
+
+ if (select_thread_state == POLLING_DESCRIPTORS)
+ {
+ signal_main_thread ();
+ select_thread_set_state (WAITING);
+ }
+ break;
+ }
+ }
+}
+
+static void
+got_fd_activity (void *info)
+{
+ NSEvent *event;
+
+ /* Post a message so we'll break out of the message loop */
+ event = [NSEvent otherEventWithType: NSApplicationDefined
+ location: NSZeroPoint
+ modifierFlags: 0
+ timestamp: 0
+ windowNumber: 0
+ context: nil
+ subtype: CLUTTER_OSX_EVENT_SUBTYPE_EVENTLOOP
+ data1: 0
+ data2: 0];
+
+ [NSApp postEvent:event atStart:YES];
+}
+
+static void
+select_thread_start (void)
+{
+ g_return_if_fail (select_thread_state == BEFORE_START);
+
+ pipe (select_thread_wakeup_pipe);
+ fcntl (select_thread_wakeup_pipe[0], F_SETFL, O_NONBLOCK);
+
+ CFRunLoopSourceContext source_context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, got_fd_activity };
+ select_main_thread_source = CFRunLoopSourceCreate (NULL, 0, &source_context);
+
+ CFRunLoopAddSource (main_thread_run_loop, select_main_thread_source, kCFRunLoopCommonModes);
+
+ select_thread_state = WAITING;
+
+ while (TRUE)
+ {
+ if (pthread_create (&select_thread, NULL, select_thread_func, NULL) == 0)
+ break;
+
+ g_warning ("Failed to create select thread, sleeping and trying again");
+ sleep (1);
+ }
+}
+
+#ifdef G_ENABLE_DEBUG
+static void
+dump_poll_result (GPollFD *ufds,
+ guint nfds)
+{
+ gint i;
+
+ for (i = 0; i < nfds; i++)
+ {
+ if (ufds[i].fd >= 0 && ufds[i].revents)
+ {
+ g_print (" %d:", ufds[i].fd);
+ if (ufds[i].revents & G_IO_IN)
+ g_print (" in");
+ if (ufds[i].revents & G_IO_OUT)
+ g_print (" out");
+ if (ufds[i].revents & G_IO_PRI)
+ g_print (" pri");
+ g_print ("\n");
+ }
+ }
+}
+#endif
+
+gboolean
+pollfds_equal (GPollFD *old_pollfds,
+ guint old_n_pollfds,
+ GPollFD *new_pollfds,
+ guint new_n_pollfds)
+{
+ gint i;
+
+ if (old_n_pollfds != new_n_pollfds)
+ return FALSE;
+
+ for (i = 0; i < old_n_pollfds; i++)
+ {
+ if (old_pollfds[i].fd != new_pollfds[i].fd ||
+ old_pollfds[i].events != new_pollfds[i].events)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Begins a polling operation with the specified GPollFD array; the
+ * timeout is used only to tell if the polling operation is blocking
+ * or non-blocking.
+ *
+ * Return value:
+ * -1: No file descriptors ready, began asynchronous poll
+ * 0: No file descriptors ready, asynchronous poll not needed
+ * > 0: Number of file descriptors ready
+ */
+static gint
+select_thread_start_poll (GPollFD *ufds,
+ guint nfds, gint timeout)
+{
+ gint n_ready;
+ gboolean have_new_pollfds = FALSE;
+ gint poll_fd_index = -1;
+ gint i;
+
+ for (i = 0; i < nfds; i++)
+ if (ufds[i].fd == -1)
+ {
+ poll_fd_index = i;
+ break;
+ }
+
+ if (nfds == 0 ||
+ (nfds == 1 && poll_fd_index >= 0))
+ {
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Nothing to poll\n");
+ return 0;
+ }
+
+ /* If we went immediately to an async poll, then we might decide to
+ * dispatch idle functions when higher priority file descriptor sources
+ * are ready to be dispatched. So we always need to first check
+ * check synchronously with a timeout of zero, and only when no
+ * sources are immediately ready, go to the asynchronous poll.
+ *
+ * Of course, if the timeout passed in is 0, then the synchronous
+ * check is sufficient and we never need to do the asynchronous poll.
+ */
+ n_ready = old_poll_func (ufds, nfds, 0);
+ if (n_ready > 0 || timeout == 0)
+ {
+#ifdef G_ENABLE_DEBUG
+ if (CLUTTER_HAS_DEBUG(EVENTLOOP) && n_ready > 0)
+ {
+ g_print ("EventLoop: Found ready file descriptors before waiting\n");
+ dump_poll_result (ufds, nfds);
+ }
+#endif
+
+ return n_ready;
+ }
+
+ SELECT_THREAD_LOCK ();
+
+ if (select_thread_state == BEFORE_START)
+ {
+ select_thread_start ();
+ }
+
+ if (select_thread_state == POLLING_QUEUED)
+ {
+ /* If the select thread hasn't picked up the set of file descriptors yet
+ * then we can simply replace an old stale set with a new set.
+ */
+ if (!pollfds_equal (ufds, nfds, next_pollfds, next_n_pollfds - 1))
+ {
+ g_free (next_pollfds);
+ next_pollfds = NULL;
+ next_n_pollfds = 0;
+
+ have_new_pollfds = TRUE;
+ }
+ }
+ else if (select_thread_state == POLLING_RESTART || select_thread_state == POLLING_DESCRIPTORS)
+ {
+ /* If we are already in the process of polling the right set of file descriptors,
+ * there's no need for us to immediately force the select thread to stop polling
+ * and then restart again. And avoiding doing so increases the efficiency considerably
+ * in the common case where we have a set of basically inactive file descriptors that
+ * stay unchanged present as we process many events.
+ *
+ * However, we have to be careful that we don't hit the following race condition
+ * Select Thread Main Thread
+ * ----------------- ---------------
+ * Polling Completes
+ * Reads data or otherwise changes file descriptor state
+ * Checks if polling is current
+ * Does nothing (*)
+ * Releases lock
+ * Acquires lock
+ * Marks polling as complete
+ * Wakes main thread
+ * Receives old stale file descriptor state
+ *
+ * To avoid this, when the new set of poll descriptors is the same as the current
+ * one, we transition to the POLLING_RESTART stage at the point marked (*). When
+ * the select thread wakes up from the poll because a file descriptor is active, if
+ * the state is POLLING_RESTART it immediately begins polling same the file descriptor
+ * set again. This normally will just return the same set of active file descriptors
+ * as the first time, but in sequence described above will properly update the
+ * file descriptor state.
+ *
+ * Special case: this RESTART logic is not needed if the only FD is the internal GLib
+ * "wakeup pipe" that is presented when threads are initialized.
+ *
+ * P.S.: The harm in the above sequence is mostly that sources can be signalled
+ * as ready when they are no longer ready. This may prompt a blocking read
+ * from a file descriptor that hangs.
+ */
+ if (!pollfds_equal (ufds, nfds, current_pollfds, current_n_pollfds - 1))
+ have_new_pollfds = TRUE;
+ else
+ {
+ if (!((nfds == 1 && poll_fd_index < 0 && g_thread_supported ()) ||
+ (nfds == 2 && poll_fd_index >= 0 && g_thread_supported ())))
+ select_thread_set_state (POLLING_RESTART);
+ }
+ }
+ else
+ have_new_pollfds = TRUE;
+
+ if (have_new_pollfds)
+ {
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Submitting a new set of file descriptor to the select thread\n");
+
+ g_assert (next_pollfds == NULL);
+
+ next_n_pollfds = nfds + 1;
+ next_pollfds = g_new (GPollFD, nfds + 1);
+ memcpy (next_pollfds, ufds, nfds * sizeof (GPollFD));
+
+ next_pollfds[nfds].fd = select_thread_wakeup_pipe[0];
+ next_pollfds[nfds].events = G_IO_IN;
+
+ if (select_thread_state != POLLING_QUEUED && select_thread_state != WAITING)
+ {
+ if (select_thread_wakeup_pipe[1])
+ {
+ char c = 'A';
+ write (select_thread_wakeup_pipe[1], &c, 1);
+ }
+ }
+
+ select_thread_set_state (POLLING_QUEUED);
+ }
+
+ SELECT_THREAD_UNLOCK ();
+
+ return -1;
+}
+
+/* End an asynchronous polling operation started with
+ * select_thread_collect_poll(). This must be called if and only if
+ * select_thread_start_poll() return -1. The GPollFD array passed
+ * in must be identical to the one passed to select_thread_start_poll().
+ *
+ * The results of the poll are written into the GPollFD array passed in.
+ *
+ * Return Value: number of file descriptors ready
+ */
+static int
+select_thread_collect_poll (GPollFD *ufds, guint nfds)
+{
+ gint i;
+ gint n_ready = 0;
+
+ SELECT_THREAD_LOCK ();
+
+ if (select_thread_state == WAITING) /* The poll completed */
+ {
+ for (i = 0; i < nfds; i++)
+ {
+ if (ufds[i].fd == -1)
+ continue;
+
+ g_assert (ufds[i].fd == current_pollfds[i].fd);
+ g_assert (ufds[i].events == current_pollfds[i].events);
+
+ if (current_pollfds[i].revents)
+ {
+ ufds[i].revents = current_pollfds[i].revents;
+ n_ready++;
+ }
+ }
+
+#ifdef G_ENABLE_DEBUG
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTLOOP)
+ {
+ g_print ("EventLoop: Found ready file descriptors after waiting\n");
+ dump_poll_result (ufds, nfds);
+ }
+#endif
+ }
+
+ SELECT_THREAD_UNLOCK ();
+
+ return n_ready;
+}
+
+/************************************************************
+ ********* Main Loop Source *********
+ ************************************************************/
+
+gboolean
+_clutter_osx_event_loop_check_pending (void)
+{
+ return current_events && current_events->head;
+}
+
+NSEvent*
+_clutter_osx_event_loop_get_pending (void)
+{
+ NSEvent *event = NULL;
+
+ if (current_events)
+ event = g_queue_pop_tail (current_events);
+
+ return event;
+}
+
+void
+_clutter_osx_event_loop_release_event (NSEvent *event)
+{
+ [event release];
+}
+
+static gboolean
+clutter_event_prepare (GSource *source,
+ gint *timeout)
+{
+ gboolean retval;
+
+ clutter_threads_enter ();
+
+ *timeout = -1;
+
+ retval = (clutter_events_pending () || _clutter_osx_event_loop_check_pending ());
+
+ clutter_threads_leave ();
+
+ return retval;
+}
+
+static gboolean
+clutter_event_check (GSource *source)
+{
+ gboolean retval;
+
+ clutter_threads_enter ();
+
+ /* XXX: This check isn't right it won't handle a recursive GLib main
+ * loop run within an outer CFRunLoop run. Such loops will pile up
+ * memory. Fixing this requires setting a flag *only* when we call
+ * g_main_context_check() from within the run loop iteraton code,
+ * and also maintaining our own stack of run loops... allocating and
+ * releasing NSAutoReleasePools not properly nested with CFRunLoop
+ * runs seems to cause problems.
+ */
+ if (current_loop_level == 0)
+ {
+ if (autorelease_pool)
+ [autorelease_pool release];
+ autorelease_pool = [[NSAutoreleasePool alloc] init];
+ }
+
+ retval = (clutter_events_pending () || _clutter_osx_event_loop_check_pending ());
+
+ clutter_threads_leave ();
+
+ return retval;
+}
+
+static gboolean
+clutter_event_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ NSEvent *nsevent;
+ ClutterEvent *event;
+
+ clutter_threads_enter ();
+
+ nsevent = _clutter_osx_event_loop_get_pending ();
+ if (nsevent) {
+ clutter_threads_leave ();
+ [NSApp sendEvent:nsevent];
+ clutter_threads_enter ();
+
+ _clutter_osx_event_loop_release_event (nsevent);
+ }
+
+ event = clutter_event_get ();
+
+ if (event)
+ {
+ /* forward the event into clutter for emission etc. */
+ clutter_do_event (event);
+ clutter_event_free (event);
+ }
+
+ clutter_threads_leave ();
+
+ return TRUE;
+}
+
+static GSourceFuncs event_funcs = {
+ clutter_event_prepare,
+ clutter_event_check,
+ clutter_event_dispatch,
+ NULL
+};
+
+/************************************************************
+ ********* Our Poll Function *********
+ ************************************************************/
+
+static gint
+poll_func (GPollFD *ufds,
+ guint nfds,
+ gint timeout_)
+{
+ NSEvent *event;
+ NSDate *limit_date;
+ gint n_ready;
+
+ n_ready = select_thread_start_poll (ufds, nfds, timeout_);
+ if (n_ready > 0)
+ timeout_ = 0;
+
+ if (timeout_ == -1)
+ limit_date = [NSDate distantFuture];
+ else if (timeout_ == 0)
+ limit_date = [NSDate distantPast];
+ else
+ limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0];
+
+ getting_events = TRUE;
+ event = [NSApp nextEventMatchingMask: NSAnyEventMask
+ untilDate: limit_date
+ inMode: NSDefaultRunLoopMode
+ dequeue: YES];
+ getting_events = FALSE;
+
+ if (n_ready < 0)
+ n_ready = select_thread_collect_poll (ufds, nfds);
+
+ if (event &&
+ [event type] == NSApplicationDefined &&
+ [event subtype] == CLUTTER_OSX_EVENT_SUBTYPE_EVENTLOOP)
+ {
+ /* Just used to wake us up; if an event and a FD arrived at the same
+ * time; could have come from a previous iteration in some cases,
+ * but the spurious wake up is harmless if a little inefficient.
+ */
+ event = NULL;
+ }
+
+ if (event)
+ {
+ if (!current_events)
+ current_events = g_queue_new ();
+ g_queue_push_head (current_events, [event retain]);
+ }
+
+ return n_ready;
+}
+
+/************************************************************
+ ********* Running the main loop out of CFRunLoop *********
+ ************************************************************/
+
+/* Wrapper around g_main_context_query() that handles reallocating
+ * run_loop_pollfds up to the proper size
+ */
+static gint
+query_main_context (GMainContext *context,
+ int max_priority,
+ int *timeout)
+{
+ gint nfds;
+
+ if (!run_loop_pollfds)
+ {
+ run_loop_pollfds_size = RUN_LOOP_POLLFDS_INITIAL_SIZE;
+ run_loop_pollfds = g_new (GPollFD, run_loop_pollfds_size);
+ }
+
+ while ((nfds = g_main_context_query (context, max_priority, timeout,
+ run_loop_pollfds,
+ run_loop_pollfds_size)) > run_loop_pollfds_size)
+ {
+ g_free (run_loop_pollfds);
+ run_loop_pollfds_size = nfds;
+ run_loop_pollfds = g_new (GPollFD, nfds);
+ }
+
+ return nfds;
+}
+
+static void
+run_loop_entry (void)
+{
+ current_loop_level++;
+
+ if (acquired_loop_level == -1)
+ {
+ if (g_main_context_acquire (NULL))
+ {
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Beginning tracking run loop activity\n");
+ acquired_loop_level = current_loop_level;
+ }
+ else
+ {
+ /* If we fail to acquire the main context, that means someone is iterating
+ * the main context in a different thread; we simply wait until this loop
+ * exits and then try again at next entry. In general, iterating the loop
+ * from a different thread is rare: it is only possible when GDK threading
+ * is initialized and is not frequently used even then. So, we hope that
+ * having GLib main loop iteration blocked in the combination of that and
+ * a native modal operation is a minimal problem. We could imagine using a
+ * thread that does g_main_context_wait() and then wakes us back up, but
+ * the gain doesn't seem worth the complexity.
+ */
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Can't acquire main loop; skipping tracking run loop activity\n");
+ }
+ }
+}
+
+static void
+run_loop_before_timers (void)
+{
+}
+
+static void
+run_loop_before_sources (void)
+{
+ GMainContext *context = g_main_context_default ();
+ gint max_priority;
+ gint nfds;
+
+ /* Before we let the CFRunLoop process sources, we want to check if there
+ * are any pending GLib main loop sources more urgent than
+ * G_PRIORITY_DEFAULT that need to be dispatched. (We consider all activity
+ * from the CFRunLoop to have a priority of G_PRIORITY_DEFAULT.) If no
+ * sources are processed by the CFRunLoop, then processing will continue
+ * on to the BeforeWaiting stage where we check for lower priority sources.
+ */
+
+ g_main_context_prepare (context, &max_priority);
+ max_priority = MIN (max_priority, G_PRIORITY_DEFAULT);
+
+ /* We ignore the timeout that query_main_context () returns since we'll
+ * always query again before waiting.
+ */
+ nfds = query_main_context (context, max_priority, NULL);
+
+ if (nfds)
+ old_poll_func (run_loop_pollfds, nfds, 0);
+
+ if (g_main_context_check (context, max_priority, run_loop_pollfds, nfds))
+ {
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Dispatching high priority sources\n");
+ g_main_context_dispatch (context);
+ }
+}
+
+static void
+dummy_timer_callback (CFRunLoopTimerRef timer,
+ void *info)
+{
+ /* Nothing; won't normally even be called */
+}
+
+static void
+run_loop_before_waiting (void)
+{
+ GMainContext *context = g_main_context_default ();
+ gint timeout;
+ gint n_ready;
+
+ /* At this point, the CFRunLoop is ready to wait. We start a GMain loop
+ * iteration by calling the check() and query() stages. We start a
+ * poll, and if it doesn't complete immediately we let the run loop
+ * go ahead and sleep. Before doing that, if there was a timeout from
+ * GLib, we set up a CFRunLoopTimer to wake us up.
+ */
+
+ g_main_context_prepare (context, &run_loop_max_priority);
+
+ run_loop_n_pollfds = query_main_context (context, run_loop_max_priority, &timeout);
+
+ n_ready = select_thread_start_poll (run_loop_pollfds, run_loop_n_pollfds, timeout);
+
+ if (n_ready > 0 || timeout == 0)
+ {
+ /* We have stuff to do, no sleeping allowed! */
+ CFRunLoopWakeUp (main_thread_run_loop);
+ }
+ else if (timeout > 0)
+ {
+ /* We need to get the run loop to break out of it's wait when our timeout
+ * expires. We do this by adding a dummy timer that we'll remove immediately
+ * after the wait wakes up.
+ */
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Adding timer to wake us up in %d milliseconds\n", timeout);
+
+ run_loop_timer = CFRunLoopTimerCreate (NULL, /* allocator */
+ CFAbsoluteTimeGetCurrent () + timeout / 1000.,
+ 0, /* interval (0=does not repeat) */
+ 0, /* flags */
+ 0, /* order (priority) */
+ dummy_timer_callback,
+ NULL);
+
+ CFRunLoopAddTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
+ }
+
+ run_loop_polling_async = n_ready < 0;
+}
+
+static void
+run_loop_after_waiting (void)
+{
+ GMainContext *context = g_main_context_default ();
+
+ /* After sleeping, we finish of the GMain loop iteratin started in before_waiting()
+ * by doing the check() and dispatch() stages.
+ */
+
+ if (run_loop_timer)
+ {
+ CFRunLoopRemoveTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
+ CFRelease (run_loop_timer);
+ run_loop_timer = NULL;
+ }
+
+ if (run_loop_polling_async)
+ {
+ select_thread_collect_poll (run_loop_pollfds, run_loop_n_pollfds);
+ run_loop_polling_async = FALSE;
+ }
+
+ if (g_main_context_check (context, run_loop_max_priority, run_loop_pollfds, run_loop_n_pollfds))
+ {
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Dispatching after waiting\n");
+ g_main_context_dispatch (context);
+ }
+}
+
+static void
+run_loop_exit (void)
+{
+ g_return_if_fail (current_loop_level > 0);
+
+ if (current_loop_level == acquired_loop_level)
+ {
+ g_main_context_release (NULL);
+ acquired_loop_level = -1;
+ CLUTTER_NOTE (EVENTLOOP, "EventLoop: Ended tracking run loop activity\n");
+ }
+
+ current_loop_level--;
+}
+
+static void
+run_loop_observer_callback (CFRunLoopObserverRef observer,
+ CFRunLoopActivity activity,
+ void *info)
+{
+ if (getting_events) /* Activity we triggered */
+ return;
+
+ switch (activity)
+ {
+ case kCFRunLoopEntry:
+ run_loop_entry ();
+ break;
+ case kCFRunLoopBeforeTimers:
+ run_loop_before_timers ();
+ break;
+ case kCFRunLoopBeforeSources:
+ run_loop_before_sources ();
+ break;
+ case kCFRunLoopBeforeWaiting:
+ run_loop_before_waiting ();
+ break;
+ case kCFRunLoopAfterWaiting:
+ run_loop_after_waiting ();
+ break;
+ case kCFRunLoopExit:
+ run_loop_exit ();
+ break;
+ default:
+ break;
+ }
+}
+
+/************************************************************/
+
+void
+_clutter_osx_event_loop_init (void)
+{
+ GSource *source;
+ CFRunLoopObserverRef observer;
+
+ g_assert (old_poll_func == NULL);
+
+ /* Hook into the GLib main loop */
+
+ event_poll_fd.events = G_IO_IN;
+ event_poll_fd.fd = -1;
+
+ source = g_source_new (&event_funcs, sizeof (GSource));
+ g_source_set_name (source, "Clutter OS X event source");
+ g_source_add_poll (source, &event_poll_fd);
+ g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
+ g_source_set_can_recurse (source, TRUE);
+ g_source_attach (source, NULL);
+
+ old_poll_func = g_main_context_get_poll_func (NULL);
+ g_main_context_set_poll_func (NULL, poll_func);
+
+ /* Hook into the the CFRunLoop for the main thread */
+
+ main_thread_run_loop = CFRunLoopGetCurrent ();
+
+ observer = CFRunLoopObserverCreate (NULL, /* default allocator */
+ kCFRunLoopAllActivities,
+ true, /* repeats: not one-shot */
+ 0, /* order (priority) */
+ run_loop_observer_callback,
+ NULL);
+
+ CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
+
+ /* Initialize our autorelease pool */
+
+ autorelease_pool = [[NSAutoreleasePool alloc] init];
+}
-/* Clutter.
- * An OpenGL based 'interactive canvas' library.
- * Copyright (C) 2009 Intel Corporation.
+/* Clutter - An OpenGL based 'interactive canvas' library.
+ * OSX backend - event loop
+ *
+ * Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2011 Crystalnix <vgachkaylo@crystalnix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
*
*
*/
-
-#ifndef __CLUTTER_EVENT_GLX_H__
-#define __CLUTTER_EVENT_GLX_H__
-
-#include <glib.h>
-#include <clutter/clutter-event.h>
-#include <clutter/clutter-backend.h>
-#include <X11/Xlib.h>
+#ifndef __CLUTTER_EVENT_LOOP_OSX_H__
+#define __CLUTTER_EVENT_LOOP_OSX_H__
G_BEGIN_DECLS
-gboolean
-_clutter_backend_glx_handle_event (ClutterBackendX11 *backend,
- XEvent *xevent);
+/* Initialization */
+void _clutter_osx_event_loop_init (void);
G_END_DECLS
-#endif /* __CLUTTER_EVENT_GLX_H__ */
-
+#endif
*
* Copyright (C) 2007-2008 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
+ * Copyright (C) 2011 Crystalnix <vgachkaylo@crystalnix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "config.h"
#include "clutter-osx.h"
+
+#include "clutter-device-manager-osx.h"
#include "clutter-stage-osx.h"
#import <AppKit/AppKit.h>
#include <glib.h>
#include <clutter/clutter-debug.h>
-#include <clutter/clutter-private.h>
+#include <clutter/clutter-device-manager.h>
#include <clutter/clutter-keysyms.h>
+#include <clutter/clutter-private.h>
+#include <clutter/clutter-stage-private.h>
-/* Overriding the poll function because the events are not delivered over file
- * descriptors and setting up a GSource would just introduce polling.
- */
+#include "clutter-event-loop-osx.h"
-static GPollFunc old_poll_func = NULL;
+#define WHEEL_DELTA 1
/*************************************************************************/
@interface NSEvent (Clutter)
@end
/*************************************************************************/
+
+static void
+take_and_queue_event (ClutterEvent *event)
+{
+ _clutter_event_push (event, FALSE);
+}
+
+static void
+process_scroll_event (ClutterEvent *event,
+ gboolean isVertical)
+{
+ ClutterStageWindow *impl;
+ ClutterStageOSX *stage_osx;
+
+ impl = _clutter_stage_get_window (event->any.stage);
+ stage_osx = CLUTTER_STAGE_OSX (impl);
+
+ gfloat *scroll_pos = isVertical ? &(stage_osx->scroll_pos_y) : &(stage_osx->scroll_pos_x);
+
+ while (abs (*scroll_pos) >= WHEEL_DELTA)
+ {
+ ClutterEvent *event_gen = clutter_event_new (CLUTTER_SCROLL);
+
+ event_gen->scroll.time = event->any.time;
+ event_gen->scroll.modifier_state = event->scroll.modifier_state;
+ event_gen->any.stage = event->any.stage;
+
+ event_gen->scroll.x = event->scroll.x;
+ event_gen->scroll.y = event->scroll.y;
+
+ if (*scroll_pos > 0)
+ {
+ event_gen->scroll.direction = isVertical ? CLUTTER_SCROLL_UP : CLUTTER_SCROLL_RIGHT;
+ *scroll_pos -= WHEEL_DELTA;
+ }
+ else
+ {
+ event_gen->scroll.direction = isVertical ? CLUTTER_SCROLL_DOWN : CLUTTER_SCROLL_LEFT;
+ *scroll_pos += WHEEL_DELTA;
+ }
+
+ clutter_event_set_device (event_gen, clutter_event_get_device (event));
+
+ take_and_queue_event (event_gen);
+
+ CLUTTER_NOTE (EVENT, "scroll %s at %f,%f",
+ (event_gen->scroll.direction == CLUTTER_SCROLL_UP) ? "UP" :
+ (
+ (event_gen->scroll.direction == CLUTTER_SCROLL_DOWN) ? "DOWN" :
+ (
+ (event_gen->scroll.direction == CLUTTER_SCROLL_RIGHT) ? "RIGHT" : "LEFT")),
+ event->scroll.x, event->scroll.y);
+ }
+}
+
static gboolean
-clutter_event_osx_translate (NSEvent *nsevent, ClutterEvent *event)
+clutter_event_osx_translate (NSEvent *nsevent,
+ ClutterEvent *event)
{
+ ClutterDeviceManagerOSX *manager_osx;
+ ClutterStageOSX *stage_osx;
+ ClutterStageWindow *impl;
+ ClutterStage *stage;
+
+ stage = event->any.stage;
+ impl = _clutter_stage_get_window (event->any.stage);
+ stage_osx = CLUTTER_STAGE_OSX (impl);
+ manager_osx = CLUTTER_DEVICE_MANAGER_OSX (clutter_device_manager_get_default ());
+
event->any.time = [nsevent clutterTime];
switch ([nsevent type])
event->button.click_count = [nsevent clickCount];
event->motion.modifier_state = [nsevent clutterModifierState];
[nsevent clutterX:&(event->button.x) y:&(event->button.y)];
+ clutter_event_set_device (event, manager_osx->core_pointer);
CLUTTER_NOTE (EVENT, "button %d %s at %f,%f clicks=%d",
(int)[nsevent buttonNumber],
event->type == CLUTTER_BUTTON_PRESS ? "press" : "release",
- (float)event->button.x, (float)event->button.y,
+ event->button.x, event->button.y,
event->button.click_count);
return TRUE;
[nsevent clutterX:&(event->motion.x) y:&(event->motion.y)];
event->motion.modifier_state = [nsevent clutterModifierState];
+ clutter_event_set_device (event, manager_osx->core_pointer);
CLUTTER_NOTE (EVENT, "motion %d at %f,%f",
(int)[nsevent buttonNumber],
- (float)event->button.x, (float)event->button.y);
+ event->button.x, event->button.y);
+ return TRUE;
+
+ case NSMouseEntered:
+ event->type = CLUTTER_ENTER;
+
+ [nsevent clutterX:&(event->crossing.x) y:&(event->crossing.y)];
+ event->crossing.related = NULL;
+ event->crossing.source = CLUTTER_ACTOR (stage);
+ clutter_event_set_device (event, manager_osx->core_pointer);
+
+ _clutter_stage_add_device (stage, manager_osx->core_pointer);
+
+ CLUTTER_NOTE (EVENT, "enter at %f,%f",
+ event->crossing.x, event->crossing.y);
return TRUE;
+ case NSMouseExited:
+ event->type = CLUTTER_LEAVE;
+
+ [nsevent clutterX:&(event->crossing.x) y:&(event->crossing.y)];
+ event->crossing.related = NULL;
+ event->crossing.source = CLUTTER_ACTOR (stage);
+ clutter_event_set_device (event, manager_osx->core_pointer);
+
+ _clutter_stage_remove_device (stage, manager_osx->core_pointer);
+
+ CLUTTER_NOTE (EVENT, "exit at %f,%f",
+ event->crossing.x, event->crossing.y);
+ return TRUE;
+
+ case NSScrollWheel:
+ stage_osx->scroll_pos_x += [nsevent deltaX];
+ stage_osx->scroll_pos_y += [nsevent deltaY];
+
+ [nsevent clutterX:&(event->scroll.x) y:&(event->scroll.y)];
+ event->scroll.modifier_state = [nsevent clutterModifierState];
+ clutter_event_set_device (event, manager_osx->core_pointer);
+
+ process_scroll_event (event, TRUE);
+ process_scroll_event (event, FALSE);
+ break;
+
case NSKeyDown:
event->type = CLUTTER_KEY_PRESS;
/* fall through */
event->key.modifier_state = [nsevent clutterModifierState];
event->key.keyval = [nsevent clutterKeyVal];
event->key.unicode_value = [[nsevent characters] characterAtIndex:0];
+ clutter_event_set_device (event, manager_osx->core_keyboard);
CLUTTER_NOTE (EVENT, "key %d (%s) (%s) %s, keyval %d",
[nsevent keyCode],
}
void
-_clutter_event_osx_put (NSEvent *nsevent, ClutterStage *wrapper)
+_clutter_event_osx_put (NSEvent *nsevent,
+ ClutterStage *wrapper)
{
- ClutterEvent event = { 0, };
-
- event.any.stage = wrapper;
+ ClutterEvent *event = clutter_event_new (CLUTTER_NOTHING);
- if (clutter_event_osx_translate (nsevent, &event))
- {
- g_assert (event.type != CLUTTER_NOTHING);
- clutter_event_put (&event);
- }
-}
-
-typedef struct {
- CFSocketRef sock;
- CFRunLoopSourceRef source;
-
- gushort revents;
-} SocketInfo;
-
-static void
-socket_activity_cb (CFSocketRef sock,
- CFSocketCallBackType cbtype,
- CFDataRef address,
- const void *data,
- void *info)
-{
- SocketInfo *si = info;
-
- if (cbtype & kCFSocketReadCallBack)
- si->revents |= G_IO_IN;
- if (cbtype & kCFSocketWriteCallBack)
- si->revents |= G_IO_OUT;
-}
-
-static gint
-clutter_event_osx_poll_func (GPollFD *ufds, guint nfds, gint timeout)
-{
- NSDate *until_date;
- NSEvent *nsevent;
- SocketInfo *sockets = NULL;
- gint n_active = 0;
-
- CLUTTER_OSX_POOL_ALLOC();
-
- if (timeout == -1)
- until_date = [NSDate distantFuture];
- else if (timeout == 0)
- until_date = [NSDate distantPast];
- else
- until_date = [NSDate dateWithTimeIntervalSinceNow:timeout/1000.0];
-
- /* File descriptors appear to be similar enough to sockets so that they can
- * be used in CFRunLoopSource.
- *
- * We could also launch a thread to call old_poll_func and signal the main
- * thread. No idea which way is better.
- */
- if (nfds > 0)
- {
- CFRunLoopRef run_loop;
-
- run_loop = [[NSRunLoop currentRunLoop] getCFRunLoop];
- sockets = g_new (SocketInfo, nfds);
-
- int i;
- for (i = 0; i < nfds; i++)
- {
- SocketInfo *si = &sockets[i];
- CFSocketCallBackType cbtype;
-
- cbtype = 0;
- if (ufds[i].events & G_IO_IN)
- cbtype |= kCFSocketReadCallBack;
- if (ufds[i].events & G_IO_OUT)
- cbtype |= kCFSocketWriteCallBack;
- /* FIXME: how to handle G_IO_HUP and G_IO_ERR? */
-
- const CFSocketContext ctxt = {
- 0, si, NULL, NULL, NULL
- };
- si->sock = CFSocketCreateWithNative (NULL, ufds[i].fd, cbtype, socket_activity_cb, &ctxt);
- si->source = CFSocketCreateRunLoopSource (NULL, si->sock, 0);
- si->revents = 0;
-
- CFRunLoopAddSource (run_loop, si->source, kCFRunLoopCommonModes);
- }
- }
-
- nsevent = [NSApp nextEventMatchingMask: NSAnyEventMask
- untilDate: until_date
- inMode: NSDefaultRunLoopMode
- dequeue: YES];
-
- /* Push the events to NSApplication which will do some magic(?) and forward
- * interesting events to our view. While we could do event translation here
- * we'd also need to filter out clicks on titlebar, and perhaps do special
- * handling for the first click (couldn't figure it out - always ended up
- * missing a screen refresh) and maybe other things.
- */
- [NSApp sendEvent:nsevent];
+ /* common fields */
+ event->any.stage = wrapper;
+ event->any.time = [nsevent clutterTime];
- if (nfds > 0)
+ if (clutter_event_osx_translate (nsevent, event))
{
- int i;
- for (i = 0; i < nfds; i++)
- {
- SocketInfo *si = &sockets[i];
-
- if ((ufds[i].revents = si->revents) != 0)
- n_active++;
-
- /* Invalidating the source also removes it from run loop and
- * guarantees the callback is never called again.
- * CFRunLoopRemoveSource removes the source from the loop, but might
- * still call the callback which would be badly timed.
- */
- CFRunLoopSourceInvalidate (si->source);
- CFRelease (si->source);
- CFRelease (si->sock);
- }
+ g_assert (event->type != CLUTTER_NOTHING);
- g_free (sockets);
+ _clutter_event_push (event, FALSE);
}
-
- /* FIXME this could result in infinite loop */
- ClutterEvent *event = clutter_event_get ();
- while (event)
- {
- clutter_do_event (event);
- clutter_event_free (event);
- event = clutter_event_get ();
- }
-
- CLUTTER_OSX_POOL_RELEASE();
-
- return n_active;
+ else
+ clutter_event_free (event);
}
void
_clutter_events_osx_init (void)
{
- g_assert (old_poll_func == NULL);
-
- old_poll_func = g_main_context_get_poll_func (NULL);
- g_main_context_set_poll_func (NULL, clutter_event_osx_poll_func);
+ _clutter_osx_event_loop_init ();
}
void
_clutter_events_osx_uninit (void)
{
- if (old_poll_func)
- {
- g_main_context_set_poll_func (NULL, old_poll_func);
- old_poll_func = NULL;
- }
+ g_assert_not_reached ();
}
*
* Copyright (C) 2007-2008 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
+ * Copyright (C) 2011 Crystalnix <vgachkaylo@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
+#define clutter_stage_osx_get_type _clutter_stage_osx_get_type
+
G_DEFINE_TYPE_WITH_CODE (ClutterStageOSX,
clutter_stage_osx,
G_TYPE_OBJECT,
clutter_stage_osx_state_update (ClutterStageOSX *self,
ClutterStageState unset_flags,
ClutterStageState set_flags);
+
static ClutterActor *
clutter_stage_osx_get_wrapper (ClutterStageWindow *stage_window);
@interface ClutterGLView : NSOpenGLView
{
ClutterStageOSX *stage_osx;
+ NSTrackingRectTag tracking_rect;
}
- (void) drawRect: (NSRect) bounds;
@end
if ((self = [super initWithFrame:aFrame pixelFormat:aFormat]) != nil)
{
self->stage_osx = aStage;
+ tracking_rect = [self addTrackingRect:[self bounds] owner:self userData:NULL assumeInside:NO];
}
return self;
_clutter_stage_do_paint (CLUTTER_STAGE (self->stage_osx->wrapper), NULL);
cogl_flush ();
[[self openGLContext] flushBuffer];
+ _cogl_swap_buffers_notify ();
}
/* In order to receive key events */
stage_osx->requisition_height = [self bounds].size.height;
clutter_actor_set_size (CLUTTER_ACTOR (self->stage_osx->wrapper),
(int)[self bounds].size.width, (int)[self bounds].size.height);
+
+ [self removeTrackingRect:tracking_rect];
+ tracking_rect = [self addTrackingRect:[self bounds] owner:self userData:NULL assumeInside:NO];
}
/* Simply forward all events that reach our view to clutter. */
}
static void
+clutter_stage_osx_redraw (ClutterStageWindow *stage_window)
+{
+ ClutterStageOSX *stage_osx = CLUTTER_STAGE_OSX (stage_window);
+
+ CLUTTER_OSX_POOL_ALLOC();
+
+ if (stage_osx->view != NULL)
+ [stage_osx->view setNeedsDisplay: YES];
+
+ CLUTTER_OSX_POOL_RELEASE();
+}
+
+static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
iface->get_wrapper = clutter_stage_osx_get_wrapper;
iface->set_cursor_visible = clutter_stage_osx_set_cursor_visible;
iface->set_user_resizable = clutter_stage_osx_set_user_resizable;
iface->set_accept_focus = clutter_stage_osx_set_accept_focus;
+ iface->redraw = clutter_stage_osx_redraw;
}
/*************************************************************************/
ClutterStageWindow *
-clutter_stage_osx_new (ClutterBackend *backend,
- ClutterStage *wrapper)
+_clutter_stage_osx_new (ClutterBackend *backend,
+ ClutterStage *wrapper)
{
ClutterStageOSX *self;
G_BEGIN_DECLS
/* convenience macros */
-#define CLUTTER_TYPE_STAGE_OSX (clutter_stage_osx_get_type())
+#define CLUTTER_TYPE_STAGE_OSX (_clutter_stage_osx_get_type())
#define CLUTTER_STAGE_OSX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),CLUTTER_TYPE_STAGE_OSX,ClutterStageOSX))
#define CLUTTER_STAGE_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),CLUTTER_TYPE_STAGE_OSX,ClutterStage))
#define CLUTTER_IS_STAGE_OSX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),CLUTTER_TYPE_STAGE_OSX))
struct _ClutterStageOSX
{
- ClutterGroup parent;
+ GObject parent;
ClutterBackend *backend;
ClutterStage *wrapper;
ClutterStageState stage_state;
gboolean acceptFocus;
+
+ gfloat scroll_pos_x;
+ gfloat scroll_pos_y;
};
struct _ClutterStageOSXClass
{
- ClutterGroupClass parent_class;
+ GObjectClass parent_class;
};
-GType clutter_stage_osx_get_type (void) G_GNUC_CONST;
+GType _clutter_stage_osx_get_type (void) G_GNUC_CONST;
-ClutterStageWindow* clutter_stage_osx_new (ClutterBackend *backend,
- ClutterStage *wrapper);
+ClutterStageWindow * _clutter_stage_osx_new (ClutterBackend *backend,
+ ClutterStage *wrapper);
G_END_DECLS
{
ClutterInputDeviceWayland *device = data;
ClutterStageWayland *stage_wayland = device->pointer_focus;
- ClutterMainContext *clutter_context;
ClutterEvent *event;
event = clutter_event_new (CLUTTER_MOTION);
device->x = x;
device->y = y;
- clutter_context = _clutter_context_get_default ();
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
}
static void
{
ClutterInputDeviceWayland *device = data;
ClutterStageWayland *stage_wayland = device->pointer_focus;
- ClutterMainContext *clutter_context;
ClutterEvent *event;
ClutterEventType type;
break;
}
- clutter_context = _clutter_context_get_default ();
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
}
static void
{
ClutterInputDeviceWayland *device = data;
ClutterStageWayland *stage_wayland = device->keyboard_focus;
- ClutterMainContext *clutter_context;
ClutterEvent *event;
event = _clutter_key_event_new_from_evdev ((ClutterInputDevice *) device,
_time, key, state,
&device->modifier_state);
- clutter_context = _clutter_context_get_default ();
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
}
static void
{
ClutterInputDeviceWayland *device = data;
ClutterStageWayland *stage_wayland;
- ClutterMainContext *clutter_context;
ClutterEvent *event;
if (device->pointer_focus)
event->crossing.source = CLUTTER_ACTOR (stage_wayland->wrapper);
event->crossing.device = CLUTTER_INPUT_DEVICE (device);
- clutter_context = _clutter_context_get_default ();
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
device->pointer_focus = NULL;
_clutter_input_device_set_stage (CLUTTER_INPUT_DEVICE (device), NULL);
event->motion.source = CLUTTER_ACTOR (stage_wayland->wrapper);
event->motion.device = CLUTTER_INPUT_DEVICE (device);
- clutter_context = _clutter_context_get_default ();
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
device->surface_x = sx;
device->surface_y = sy;
{
ClutterInputDeviceWayland *device = data;
ClutterStageWayland *stage_wayland;
- ClutterMainContext *clutter_context;
ClutterEvent *event;
uint32_t *k, *end;
event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
event->stage_state.new_state = 0;
- clutter_context = _clutter_context_get_default ();
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
}
if (surface)
for (k = keys->data; k < end; k++)
device->modifier_state |= device->xkb->map->modmap[*k];
- clutter_context = _clutter_context_get_default ();
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
}
}
wl_display_frame_callback (backend_wayland->wayland_display,
wayland_frame_callback,
stage_wayland);
+
+ _cogl_swap_buffers_notify ();
}
static void
}
}
-static void
-clutter_backend_win32_redraw (ClutterBackend *backend,
- ClutterStage *stage)
-{
- ClutterStageWin32 *stage_win32;
- ClutterStageWindow *impl;
-
- impl = _clutter_stage_get_window (stage);
- if (impl == NULL)
- return;
-
- g_return_if_fail (CLUTTER_IS_STAGE_WIN32 (impl));
-
- stage_win32 = CLUTTER_STAGE_WIN32 (impl);
-
- /* this will cause the stage implementation to be painted */
- _clutter_stage_do_paint (stage, NULL);
- cogl_flush ();
-
- if (stage_win32->client_dc)
- SwapBuffers (stage_win32->client_dc);
-}
-
static ClutterStageWindow *
clutter_backend_win32_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
backend_class->create_stage = clutter_backend_win32_create_stage;
backend_class->add_options = clutter_backend_win32_add_options;
backend_class->get_features = clutter_backend_win32_get_features;
- backend_class->redraw = clutter_backend_win32_redraw;
backend_class->create_context = clutter_backend_win32_create_context;
backend_class->ensure_context = clutter_backend_win32_ensure_context;
backend_class->get_device_manager = clutter_backend_win32_get_device_manager;
clutter_device_manager_win32_constructed (GObject *gobject)
{
ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (gobject);
+ ClutterDeviceManagerWin32 *manager_win32;
ClutterInputDevice *device;
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
"id", 0,
"name", "Core Pointer",
"device-type", CLUTTER_POINTER_DEVICE,
+ "device-mode", CLUTTER_INPUT_MODE_MASTER,
+ "has-cursor", TRUE,
+ "enabled", TRUE,
NULL);
CLUTTER_NOTE (BACKEND, "Added core pointer device");
_clutter_device_manager_add_device (manager, device);
"id", 1,
"name", "Core Keyboard",
"device-type", CLUTTER_KEYBOARD_DEVICE,
+ "device-mode", CLUTTER_INPUT_MODE_MASTER,
+ "enabled", TRUE,
NULL);
CLUTTER_NOTE (BACKEND, "Added core keyboard device");
_clutter_device_manager_add_device (manager, device);
+
+ manager_win32 = CLUTTER_DEVICE_MANAGER_WIN32 (manager);
+
+ _clutter_input_device_set_associated_device (manager_win32->core_pointer,
+ manager_win32->core_keyboard);
+ _clutter_input_device_set_associated_device (manager_win32->core_keyboard,
+ manager_win32->core_pointer);
}
static void
{ VK_LCONTROL, CLUTTER_KEY_Control_L },
{ VK_RCONTROL, CLUTTER_KEY_Control_R }
};
-#define CLUTTER_WIN32_KEY_MAP_SIZE (sizeof (clutter_win32_key_map) \
- / sizeof (clutter_win32_key_map[0]))
+
+#define CLUTTER_WIN32_KEY_MAP_SIZE (G_N_ELEMENTS (clutter_win32_key_map))
static GSource *
clutter_event_source_new (ClutterBackend *backend)
event_source->backend = backend;
+ g_source_set_name (source, "Clutter Win32 Event Source");
+
return source;
}
return ret;
}
-static void
+static inline void
take_and_queue_event (ClutterEvent *event)
{
- ClutterMainContext *clutter_context;
-
- clutter_context = _clutter_context_get_default ();
-
/* The event is added directly to the queue instead of using
clutter_event_put so that it can avoid a copy. This takes
ownership of the event */
- g_queue_push_head (clutter_context->events_queue, event);
+ _clutter_event_push (event, FALSE);
}
static inline void
ClutterEvent *event = clutter_event_new (release ?
CLUTTER_BUTTON_RELEASE :
CLUTTER_BUTTON_PRESS);
+
+ event->any.stage = stage;
+
event->button.time = msg->time;
event->button.x = GET_X_LPARAM (msg->lParam);
event->button.y = GET_Y_LPARAM (msg->lParam);
event->button.modifier_state = get_modifier_state (msg->wParam);
event->button.button = button;
event->button.click_count = click_count;
- event->button.device = device;
- event->any.stage = stage;
+ clutter_event_set_device (event, device);
take_and_queue_event (event);
}
event->scroll.time = msg->time;
event->scroll.modifier_state =
get_modifier_state (LOWORD (msg->wParam));
- event->scroll.device = core_pointer;
event->any.stage = stage;
+ clutter_event_set_device (event, core_pointer);
+
/* conversion to window coordinates is required */
pt.x = GET_X_LPARAM (msg->lParam);
pt.y = GET_Y_LPARAM (msg->lParam);
event->motion.x = GET_X_LPARAM (msg->lParam);
event->motion.y = GET_Y_LPARAM (msg->lParam);
event->motion.modifier_state = get_modifier_state (msg->wParam);
- event->motion.device = core_pointer;
event->any.stage = stage;
+ clutter_event_set_device (event, core_pointer);
+
/* We need to start tracking when the mouse enters the stage if
we're not already */
if (!stage_win32->tracking_mouse)
{
+ ClutterEvent *crossing = clutter_event_new (CLUTTER_ENTER);
TRACKMOUSEEVENT tmevent;
tmevent.cbSize = sizeof (tmevent);
tmevent.hwndTrack = stage_win32->hwnd;
TrackMouseEvent (&tmevent);
+ event->crossing.time = msg->time;
+ event->crossing.x = event->motion.x;
+ event->crossing.y = event->motion.y;
+ event->crossing.stage = stage;
+ event->crossing.source = CLUTTER_ACTOR (stage);
+ event->crossing.related = NULL;
+
+ clutter_event_set_device (event, core_pointer);
+
/* we entered the stage */
- _clutter_input_device_set_stage (event->motion.device, stage);
+ _clutter_stage_add_device (stage, event->crossing.device);
+
+ take_and_queue_event (crossing);
stage_win32->tracking_mouse = TRUE;
}
event->crossing.time = msg->time;
event->crossing.x = msg->pt.x;
event->crossing.y = msg->pt.y;
- event->crossing.device = core_pointer;
- event->any.stage = stage;
+ event->crossing.stage = stage;
+ event->crossing.source = CLUTTER_ACTOR (stage);
+ event->crossing.related = NULL;
+
+ clutter_event_set_device (event, core_pointer);
/* we left the stage */
- _clutter_input_device_set_stage (event->crossing.device, NULL);
+ _clutter_stage_remove_device (stage, core_pointer);
/* When we get a leave message the mouse tracking is
automatically cancelled so we'll need to start it again when
event->key.time = msg->time;
event->key.modifier_state = get_key_modifier_state (key_states);
event->key.hardware_keycode = scan_code;
- event->key.device = core_keyboard;
event->any.stage = stage;
+ clutter_event_set_device (event, core_keyboard);
+
take_and_queue_event (event);
}
break;
}
static void
+clutter_stage_win32_redraw (ClutterStageWindow *stage_window)
+{
+ ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
+
+ /* this will cause the stage implementation to be painted */
+ _clutter_stage_do_paint (stage_win32->wrapper, NULL);
+ cogl_flush ();
+
+ if (stage_win32->client_dc)
+ {
+ SwapBuffers (stage_win32->client_dc);
+ _cogl_swap_buffers_notify ();
+ }
+}
+
+static void
clutter_stage_win32_dispose (GObject *gobject)
{
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (gobject);
iface->get_geometry = clutter_stage_win32_get_geometry;
iface->realize = clutter_stage_win32_realize;
iface->unrealize = clutter_stage_win32_unrealize;
+ iface->redraw = clutter_stage_win32_redraw;
}
/**
#include <errno.h>
#include "clutter-backend-x11.h"
-#include "clutter-device-manager-x11.h"
-#include "clutter-input-device-x11.h"
+#include "clutter-device-manager-core-x11.h"
+#include "clutter-device-manager-xi2.h"
#include "clutter-settings-x11.h"
#include "clutter-stage-x11.h"
#include "clutter-x11.h"
#include <X11/extensions/XInput.h>
#endif
+#if HAVE_XINPUT_2
+#include <X11/extensions/XInput2.h>
+#endif
+
#include "cogl/cogl.h"
#include "cogl/cogl-internal.h"
#include "clutter-backend.h"
#include "clutter-debug.h"
-#include "clutter-device-manager.h"
+#include "clutter-device-manager-private.h"
#include "clutter-event.h"
#include "clutter-main.h"
#include "clutter-private.h"
+#define clutter_backend_x11_get_type _clutter_backend_x11_get_type
+
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
/* atoms; remember to add the code that assigns the atom value to
return CLUTTER_X11_FILTER_CONTINUE;
}
+static ClutterX11FilterReturn
+cogl_xlib_filter (XEvent *xevent,
+ ClutterEvent *event,
+ gpointer data)
+{
+ ClutterX11FilterReturn retval;
+ CoglXlibFilterReturn ret;
+
+ ret = _cogl_xlib_handle_event (xevent);
+ switch (ret)
+ {
+ case COGL_XLIB_FILTER_REMOVE:
+ retval = CLUTTER_X11_FILTER_REMOVE;
+ break;
+
+ case COGL_XLIB_FILTER_CONTINUE:
+ default:
+ retval = CLUTTER_X11_FILTER_CONTINUE;
+ break;
+ }
+
+ return retval;
+}
+
static void
clutter_backend_x11_xsettings_notify (const char *name,
XSettingsAction action,
g_object_thaw_notify (G_OBJECT (settings));
}
+static void
+clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
+{
+ if (G_UNLIKELY (backend_x11->device_manager == NULL))
+ {
+ ClutterEventTranslator *translator;
+ ClutterBackend *backend;
+
+#if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
+ if (clutter_enable_xinput)
+ {
+ int event_base, first_event, first_error;
+
+ if (XQueryExtension (backend_x11->xdpy, "XInputExtension",
+ &event_base,
+ &first_event,
+ &first_error))
+ {
+#ifdef HAVE_XINPUT_2
+ int major = 2;
+ int minor = 0;
+
+ if (XIQueryVersion (backend_x11->xdpy, &major, &minor) != BadRequest)
+ {
+ CLUTTER_NOTE (BACKEND, "Creating XI2 device manager");
+ backend_x11->has_xinput = TRUE;
+ backend_x11->device_manager =
+ g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_XI2,
+ "backend", backend_x11,
+ "opcode", event_base,
+ NULL);
+ }
+ else
+#endif /* HAVE_XINPUT_2 */
+ {
+ CLUTTER_NOTE (BACKEND, "Creating Core+XI device manager");
+ backend_x11->has_xinput = TRUE;
+ backend_x11->device_manager =
+ g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
+ "backend", backend_x11,
+ "event-base", first_event,
+ NULL);
+
+ }
+ }
+ }
+ else
+#endif /* HAVE_XINPUT || HAVE_XINPUT_2 */
+ {
+ CLUTTER_NOTE (BACKEND, "Creating Core device manager");
+ backend_x11->has_xinput = FALSE;
+ backend_x11->device_manager =
+ g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
+ "backend", backend_x11,
+ NULL);
+ }
+
+ backend = CLUTTER_BACKEND (backend_x11);
+ translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->device_manager);
+ _clutter_backend_add_event_translator (backend, translator);
+ }
+}
+
+static void
+clutter_backend_x11_create_keymap (ClutterBackendX11 *backend_x11)
+{
+ if (backend_x11->keymap == NULL)
+ {
+ ClutterEventTranslator *translator;
+ ClutterBackend *backend;
+
+ backend_x11->keymap =
+ g_object_new (CLUTTER_TYPE_KEYMAP_X11,
+ "backend", backend_x11,
+ NULL);
+
+ backend = CLUTTER_BACKEND (backend_x11);
+ translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->keymap);
+ _clutter_backend_add_event_translator (backend, translator);
+ }
+}
+
gboolean
-clutter_backend_x11_pre_parse (ClutterBackend *backend,
- GError **error)
+_clutter_backend_x11_pre_parse (ClutterBackend *backend,
+ GError **error)
{
const gchar *env_string;
env_string = NULL;
}
+ env_string = g_getenv ("CLUTTER_ENABLE_XINPUT");
+ if (env_string)
+ {
+ clutter_enable_xinput = TRUE;
+ env_string = NULL;
+ }
+
return TRUE;
}
gboolean
-clutter_backend_x11_post_parse (ClutterBackend *backend,
- GError **error)
+_clutter_backend_x11_post_parse (ClutterBackend *backend,
+ GError **error)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
CoglTexturePixmapX11 */
_cogl_xlib_set_display (backend_x11->xdpy);
+ /* add event filter for Cogl events */
+ clutter_x11_add_filter (cogl_xlib_filter, NULL);
+
if (clutter_screen == -1)
backend_x11->xscreen = DefaultScreenOfDisplay (backend_x11->xdpy);
else
clutter_screen);
backend_x11->xscreen_num = XScreenNumberOfScreen (backend_x11->xscreen);
+ backend_x11->xscreen_width = WidthOfScreen (backend_x11->xscreen);
+ backend_x11->xscreen_height = HeightOfScreen (backend_x11->xscreen);
backend_x11->xwin_root = RootWindow (backend_x11->xdpy,
backend_x11->xscreen_num);
g_object_set (settings, "font-dpi", (int) dpi * 1024, NULL);
- /* register input devices */
- backend_x11->device_manager =
- g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
- "use-xinput-1", clutter_enable_xinput,
- "backend", backend_x11,
- NULL);
+ /* create the device manager */
+ clutter_backend_x11_create_device_manager (backend_x11);
/* register keymap */
- backend_x11->keymap =
- g_object_new (CLUTTER_TYPE_KEYMAP_X11,
- "backend", backend_x11,
- NULL);
+ clutter_backend_x11_create_keymap (backend_x11);
/* create XSETTINGS client */
backend_x11->xsettings =
NULL,
backend_x11);
+ /* add event filter for XSETTINGS events */
clutter_x11_add_filter (xsettings_filter, backend_x11);
if (clutter_synchronise)
G_OPTION_ARG_NONE, &clutter_synchronise,
N_("Make X calls synchronous"), NULL
},
-#ifdef HAVE_XINPUT
+#if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
{
"enable-xinput", 0,
0,
{ NULL }
};
-void
+static void
clutter_backend_x11_add_options (ClutterBackend *backend,
GOptionGroup *group)
{
g_free (backend_x11->display_name);
+ clutter_x11_remove_filter (cogl_xlib_filter, NULL);
+
clutter_x11_remove_filter (xsettings_filter, backend_x11);
_clutter_xsettings_client_destroy (backend_x11->xsettings);
GObjectClass *parent_class;
GObject *retval;
- if (!backend_singleton)
+ if (backend_singleton == NULL)
{
parent_class = G_OBJECT_CLASS (clutter_backend_x11_parent_class);
retval = parent_class->constructor (gtype, n_params, params);
return g_object_ref (backend_singleton);
}
-ClutterFeatureFlags
+static ClutterFeatureFlags
clutter_backend_x11_get_features (ClutterBackend *backend)
{
return CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR;
_clutter_event_x11_free (event_x11);
}
-gboolean
-clutter_backend_x11_handle_event (ClutterBackendX11 *backend_x11,
- XEvent *xevent)
+static ClutterDeviceManager *
+clutter_backend_x11_get_device_manager (ClutterBackend *backend)
{
- return FALSE;
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+
+ clutter_backend_x11_create_device_manager (backend_x11);
+
+ return backend_x11->device_manager;
}
-static ClutterDeviceManager *
-clutter_backend_x11_get_device_manager (ClutterBackend *backend)
+static void
+update_last_event_time (ClutterBackendX11 *backend_x11,
+ XEvent *xevent)
+{
+ Time current_time = CurrentTime;
+ Time last_time = backend_x11->last_event_time;
+
+ switch (xevent->type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ current_time = xevent->xkey.time;
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ current_time = xevent->xbutton.time;
+ break;
+
+ case MotionNotify:
+ current_time = xevent->xmotion.time;
+ break;
+
+ case EnterNotify:
+ case LeaveNotify:
+ current_time = xevent->xcrossing.time;
+ break;
+
+ case PropertyNotify:
+ current_time = xevent->xproperty.time;
+ break;
+
+ default:
+ break;
+ }
+
+ /* only change the current event time if it's after the previous event
+ * time, or if it is at least 30 seconds earlier - in case the system
+ * clock was changed
+ */
+ if ((current_time != CurrentTime) &&
+ (current_time > last_time || (last_time - current_time > (30 * 1000))))
+ backend_x11->last_event_time = current_time;
+}
+
+static gboolean
+clutter_backend_x11_translate_event (ClutterBackend *backend,
+ gpointer native,
+ ClutterEvent *event)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendClass *parent_class;
+ XEvent *xevent = native;
- if (G_UNLIKELY (backend_x11->device_manager == NULL))
+ /* X11 filter functions have a higher priority */
+ if (backend_x11->event_filters != NULL)
{
- backend_x11->device_manager =
- g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
- "use-xinput-1", clutter_enable_xinput,
- "backend", backend_x11,
- NULL);
+ GSList *node = backend_x11->event_filters;
+
+ while (node != NULL)
+ {
+ ClutterX11EventFilter *filter = node->data;
+
+ switch (filter->func (xevent, event, filter->data))
+ {
+ case CLUTTER_X11_FILTER_CONTINUE:
+ break;
+
+ case CLUTTER_X11_FILTER_TRANSLATE:
+ return TRUE;
+
+ case CLUTTER_X11_FILTER_REMOVE:
+ return FALSE;
+
+ default:
+ break;
+ }
+
+ node = node->next;
+ }
}
- return backend_x11->device_manager;
+ /* we update the event time only for events that can
+ * actually reach Clutter's event queue
+ */
+ update_last_event_time (backend_x11, xevent);
+
+ /* chain up to the parent implementation, which will handle
+ * event translators
+ */
+ parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class);
+ return parent_class->translate_event (backend, native, event);
}
static void
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
- ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass);
gobject_class->constructor = clutter_backend_x11_constructor;
gobject_class->dispose = clutter_backend_x11_dispose;
gobject_class->finalize = clutter_backend_x11_finalize;
- backend_class->pre_parse = clutter_backend_x11_pre_parse;
- backend_class->post_parse = clutter_backend_x11_post_parse;
+ backend_class->pre_parse = _clutter_backend_x11_pre_parse;
+ backend_class->post_parse = _clutter_backend_x11_post_parse;
backend_class->init_events = clutter_backend_x11_init_events;
backend_class->add_options = clutter_backend_x11_add_options;
backend_class->get_features = clutter_backend_x11_get_features;
backend_class->get_device_manager = clutter_backend_x11_get_device_manager;
backend_class->copy_event_data = clutter_backend_x11_copy_event_data;
backend_class->free_event_data = clutter_backend_x11_free_event_data;
-
- backendx11_class->handle_event = clutter_backend_x11_handle_event;
+ backend_class->translate_event = clutter_backend_x11_translate_event;
}
static void
{
if (_clutter_context_is_initialized ())
{
- g_critical ("Display connection already exists. You can only call "
- "clutter_x11_set_display() before clutter_init()");
+ g_warning ("%s() can only be used before calling clutter_init()",
+ G_STRFUNC);
return;
}
{
if (_clutter_context_is_initialized ())
{
- g_critical ("clutter_x11_enable_xinput() can only be called "
- "before clutter_init()");
+ g_warning ("%s() can only be used before calling clutter_init()",
+ G_STRFUNC);
return;
}
{
if (_clutter_context_is_initialized ())
{
- g_warning ("clutter_x11_disable_event_retrieval() can only be "
- "called before clutter_init()");
+ g_warning ("%s() can only be used before calling clutter_init()",
+ G_STRFUNC);
return;
}
}
/**
- * clutter_x11_get_root_window:
+ * clutter_x11_get_root_window: (skip)
*
* Retrieves the root window.
*
}
/**
- * clutter_x11_add_filter:
+ * clutter_x11_add_filter: (skip)
* @func: a filter function
* @data: user data to be passed to the filter function, or %NULL
*
}
/**
- * clutter_x11_remove_filter:
+ * clutter_x11_remove_filter: (skip)
* @func: a filter function
* @data: user data to be passed to the filter function, or %NULL
*
}
}
-void
-_clutter_x11_select_events (Window xwin)
-{
-#ifdef HAVE_XINPUT
- ClutterDeviceManager *manager;
- const GSList *l;
-
- if (G_UNLIKELY (backend_singleton == NULL))
- {
- g_critical ("X11 backend has not been initialised");
-
- return;
- }
-
- manager = clutter_device_manager_get_default ();
-
- for (l = clutter_device_manager_peek_devices (manager);
- l != NULL;
- l = l->next)
- {
- ClutterInputDevice *device = l->data;
-
- _clutter_input_device_x11_select_events (device, backend_singleton, xwin);
- }
-#endif /* HAVE_XINPUT */
-}
-
-ClutterInputDevice *
-_clutter_x11_get_device_for_xid (XID id)
-{
- ClutterDeviceManager *manager;
-
- manager = clutter_device_manager_get_default ();
-
- return clutter_device_manager_get_device (manager, (gint) id);
-}
-
/**
* clutter_x11_get_input_devices:
*
gboolean
clutter_x11_has_xinput (void)
{
-#ifdef HAVE_XINPUT
- if (backend_singleton == NULL)
- {
- g_critical ("X11 backend has not been initialised");
- return FALSE;
- }
+#if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
+ if (backend_singleton != NULL)
+ return backend_singleton->has_xinput;
- return backend_singleton->have_xinput;
+ return FALSE;
#else
return FALSE;
#endif
if (done_check)
return have_composite;
- if (!backend_singleton)
+ if (!_clutter_context_is_initialized ())
{
g_critical ("X11 backend has not been initialised");
return FALSE;
}
XVisualInfo *
-clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
+_clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
{
ClutterBackendX11Class *klass;
}
/**
- * clutter_x11_get_visual_info:
+ * clutter_x11_get_visual_info: (skip)
*
* Retrieves the <structname>XVisualInfo</structname> used by the Clutter X11
* backend.
backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
- return clutter_backend_x11_get_visual_info (backend_x11);
+ return _clutter_backend_x11_get_visual_info (backend_x11);
+}
+
+gboolean
+_clutter_x11_input_device_translate_screen_coord (ClutterInputDevice *device,
+ gint stage_root_x,
+ gint stage_root_y,
+ guint index_,
+ gdouble value,
+ gdouble *axis_value)
+{
+ ClutterAxisInfo *info;
+ ClutterBackendX11 *backend_x11;
+ gdouble width, scale, offset;
+
+ backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
+
+ if (device->axes == NULL || index_ >= device->axes->len)
+ return FALSE;
+
+ info = &g_array_index (device->axes, ClutterAxisInfo, index_);
+ if (info->axis != CLUTTER_INPUT_AXIS_X ||
+ info->axis != CLUTTER_INPUT_AXIS_Y)
+ {
+ return FALSE;
+ }
+
+ width = info->max_value - info->min_value;
+
+ if (info->axis == CLUTTER_INPUT_AXIS_X)
+ {
+ if (width > 0)
+ scale = backend_x11->xscreen_width / width;
+ else
+ scale = 1;
+
+ offset = - stage_root_x;
+ }
+ else
+ {
+ if (width > 0)
+ scale = backend_x11->xscreen_height / width;
+ else
+ scale = 1;
+
+ offset = - stage_root_y;
+ }
+
+ if (axis_value)
+ *axis_value = offset + scale * (value - info->min_value);
+
+ return TRUE;
}
#include <X11/Xatom.h>
#include "clutter-x11.h"
+
#include "clutter-backend-private.h"
#include "clutter-keymap-x11.h"
+
#include "xsettings/xsettings-client.h"
G_BEGIN_DECLS
-#define CLUTTER_TYPE_BACKEND_X11 (clutter_backend_x11_get_type ())
+#define CLUTTER_TYPE_BACKEND_X11 (_clutter_backend_x11_get_type ())
#define CLUTTER_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_X11, ClutterBackendX11))
#define CLUTTER_IS_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_X11))
#define CLUTTER_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_X11, ClutterBackendX11Class))
typedef struct _ClutterBackendX11 ClutterBackendX11;
typedef struct _ClutterBackendX11Class ClutterBackendX11Class;
+typedef struct _ClutterEventX11 ClutterEventX11;
+typedef struct _ClutterX11EventFilter ClutterX11EventFilter;
-typedef struct _ClutterX11EventFilter
+struct _ClutterX11EventFilter
{
ClutterX11FilterFunc func;
gpointer data;
-} ClutterX11EventFilter;
+};
+
+struct _ClutterEventX11
+{
+ /* additional fields for Key events */
+ gint key_group;
+
+ guint key_is_modifier : 1;
+ guint num_lock_set : 1;
+ guint caps_lock_set : 1;
+};
struct _ClutterBackendX11
{
ClutterBackend parent_instance;
Display *xdpy;
- Window xwin_root;
+ gchar *display_name;
+
Screen *xscreen;
int xscreen_num;
- gchar *display_name;
+ int xscreen_width;
+ int xscreen_height;
+
+ Window xwin_root;
/* event source */
GSource *event_source;
Atom atom_NET_WM_NAME;
Atom atom_UTF8_STRING;
- int xi_event_base;
- int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
- gboolean have_xinput;
-
Time last_event_time;
ClutterDeviceManager *device_manager;
+ gboolean has_xinput;
XSettingsClient *xsettings;
Window xsettings_xwin;
ClutterKeymapX11 *keymap;
- int xkb_event_base;
gboolean use_xkb;
gboolean have_xkb_autorepeat;
+ guint keymap_serial;
};
struct _ClutterBackendX11Class
* may need to be handled differently for different backends.
*/
XVisualInfo *(* get_visual_info) (ClutterBackendX11 *backend);
-
- /*
- * Different X11 backends may care about some special events so they all have
- * a chance to intercept them.
- */
- gboolean (*handle_event) (ClutterBackendX11 *backend,
- XEvent *xevent);
};
-/* platform-specific event data */
-typedef struct _ClutterEventX11 ClutterEventX11;
-
void _clutter_backend_x11_events_init (ClutterBackend *backend);
void _clutter_backend_x11_events_uninit (ClutterBackend *backend);
-GType clutter_backend_x11_get_type (void) G_GNUC_CONST;
+GType _clutter_backend_x11_get_type (void) G_GNUC_CONST;
/* Private to glx/eglx backends */
-gboolean
-clutter_backend_x11_pre_parse (ClutterBackend *backend,
- GError **error);
-
-gboolean
-clutter_backend_x11_post_parse (ClutterBackend *backend,
- GError **error);
-
-gboolean
-clutter_backend_x11_init_stage (ClutterBackend *backend,
- GError **error);
-
-ClutterActor *
-clutter_backend_x11_get_stage (ClutterBackend *backend);
-
-void
-clutter_backend_x11_add_options (ClutterBackend *backend,
- GOptionGroup *group);
-
-ClutterFeatureFlags
-clutter_backend_x11_get_features (ClutterBackend *backend);
-
XVisualInfo *
-clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11);
-
-ClutterInputDevice *
-_clutter_x11_get_device_for_xid (XID id);
+_clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11);
void
_clutter_x11_select_events (Window xwin);
void
_clutter_event_x11_free (ClutterEventX11 *event_x11);
+gboolean
+_clutter_x11_input_device_translate_screen_coord (ClutterInputDevice *device,
+ gint stage_root_x,
+ gint stage_root_y,
+ guint index_,
+ gdouble value,
+ gdouble *axis_value);
+
G_END_DECLS
#endif /* __CLUTTER_BACKEND_X11_H__ */
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright © 2009, 2010, 2011 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>
+ */
+
+#include "config.h"
+
+#include "clutter-device-manager-core-x11.h"
+
+#include "clutter-backend-x11.h"
+#include "clutter-input-device-core-x11.h"
+#include "clutter-stage-x11.h"
+
+#include "clutter-backend.h"
+#include "clutter-debug.h"
+#include "clutter-device-manager-private.h"
+#include "clutter-event-translator.h"
+#include "clutter-stage-private.h"
+#include "clutter-private.h"
+
+#ifdef HAVE_XINPUT
+#include <X11/extensions/XInput.h>
+
+/* old versions of XI.h don't define these */
+#ifndef IsXExtensionKeyboard
+#define IsXExtensionKeyboard 3
+#define IsXExtensionPointer 4
+#endif
+
+#endif /* HAVE_XINPUT */
+
+enum
+{
+ PROP_0,
+
+ PROP_EVENT_BASE,
+
+ PROP_LAST
+};
+
+static GParamSpec *obj_props[PROP_LAST] = { NULL, };
+
+static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
+
+#define clutter_device_manager_x11_get_type _clutter_device_manager_x11_get_type
+
+G_DEFINE_TYPE_WITH_CODE (ClutterDeviceManagerX11,
+ clutter_device_manager_x11,
+ CLUTTER_TYPE_DEVICE_MANAGER,
+ G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
+ clutter_event_translator_iface_init));
+
+#ifdef HAVE_XINPUT
+static void
+translate_class_info (ClutterInputDevice *device,
+ XDeviceInfo *info)
+{
+ XAnyClassPtr any_class;
+ gint i;
+
+ any_class = info->inputclassinfo;
+
+ for (i = 0; i < info->num_classes; i++)
+ {
+ switch (any_class->class)
+ {
+ case ButtonClass:
+ break;
+
+ case KeyClass:
+ {
+ XKeyInfo *xk_info = (XKeyInfo *) any_class;
+ ClutterInputDeviceX11 *device_x11;
+ guint n_keys;
+
+ device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
+
+ n_keys = xk_info->max_keycode - xk_info->min_keycode + 1;
+
+ _clutter_input_device_set_n_keys (device, n_keys);
+ device_x11->min_keycode = xk_info->min_keycode;
+ device_x11->max_keycode = xk_info->max_keycode;
+ }
+ break;
+
+ case ValuatorClass:
+ {
+ XValuatorInfo *xv_info = (XValuatorInfo *) any_class;
+ gint j;
+
+ for (j = 0; j < xv_info->num_axes; j++)
+ {
+ ClutterInputAxis axis;
+
+ switch (j)
+ {
+ case 0:
+ axis = CLUTTER_INPUT_AXIS_X;
+ break;
+
+ case 1:
+ axis = CLUTTER_INPUT_AXIS_Y;
+ break;
+
+ case 2:
+ axis = CLUTTER_INPUT_AXIS_PRESSURE;
+ break;
+
+ case 3:
+ axis = CLUTTER_INPUT_AXIS_XTILT;
+ break;
+
+ case 4:
+ axis = CLUTTER_INPUT_AXIS_YTILT;
+ break;
+
+ case 5:
+ axis = CLUTTER_INPUT_AXIS_WHEEL;
+ break;
+
+ default:
+ axis = CLUTTER_INPUT_AXIS_IGNORE;
+ break;
+ }
+
+ _clutter_input_device_add_axis (device, axis,
+ xv_info->axes[j].min_value,
+ xv_info->axes[j].max_value,
+ xv_info->axes[j].resolution);
+ }
+ }
+ break;
+ }
+
+ any_class = (XAnyClassPtr) (((char *) any_class) + any_class->length);
+ }
+}
+
+static ClutterInputDevice *
+create_device (ClutterDeviceManagerX11 *manager_x11,
+ ClutterBackendX11 *backend_x11,
+ XDeviceInfo *info)
+{
+ ClutterInputDeviceType source;
+ ClutterInputDevice *retval;
+
+ if (info->use != IsXExtensionPointer &&
+ info->use != IsXExtensionKeyboard)
+ return NULL;
+
+ if (info->use == IsXExtensionKeyboard)
+ source = CLUTTER_KEYBOARD_DEVICE;
+ else
+ {
+ gchar *name;
+
+ name = g_ascii_strdown (info->name, -1);
+
+ if (strstr (name, "eraser") != NULL)
+ source = CLUTTER_ERASER_DEVICE;
+ else if (strstr (name, "cursor") != NULL)
+ source = CLUTTER_CURSOR_DEVICE;
+ else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL)
+ source = CLUTTER_PEN_DEVICE;
+ else
+ source = CLUTTER_POINTER_DEVICE;
+
+ g_free (name);
+ }
+
+ retval = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
+ "name", info->name,
+ "id", info->id,
+ "has-cursor", FALSE,
+ "device-manager", manager_x11,
+ "device-type", source,
+ "device-mode", CLUTTER_INPUT_MODE_FLOATING,
+ "backend", backend_x11,
+ "enabled", FALSE,
+ NULL);
+ translate_class_info (retval, info);
+
+ CLUTTER_NOTE (BACKEND,
+ "XI Device '%s' (id: %d) created",
+ info->name,
+ (int) info->id);
+
+ return retval;
+}
+#endif /* HAVE_XINPUT */
+
+static inline void
+translate_key_event (ClutterBackendX11 *backend_x11,
+ ClutterDeviceManagerX11 *manager_x11,
+ ClutterEvent *event,
+ XEvent *xevent)
+{
+ ClutterEventX11 *event_x11;
+ char buffer[256 + 1];
+ int n;
+
+ event->key.type = xevent->xany.type == KeyPress ? CLUTTER_KEY_PRESS
+ : CLUTTER_KEY_RELEASE;
+ event->key.time = xevent->xkey.time;
+
+ clutter_event_set_device (event, manager_x11->core_keyboard);
+
+ /* KeyEvents have platform specific data associated to them */
+ event_x11 = _clutter_event_x11_new ();
+ _clutter_event_set_platform_data (event, event_x11);
+
+ event->key.modifier_state = (ClutterModifierType) xevent->xkey.state;
+ event->key.hardware_keycode = xevent->xkey.keycode;
+
+ /* keyval is the key ignoring all modifiers ('1' vs. '!') */
+ event->key.keyval =
+ _clutter_keymap_x11_translate_key_state (backend_x11->keymap,
+ event->key.hardware_keycode,
+ event->key.modifier_state,
+ NULL);
+
+ event_x11->key_group =
+ _clutter_keymap_x11_get_key_group (backend_x11->keymap,
+ event->key.modifier_state);
+ event_x11->key_is_modifier =
+ _clutter_keymap_x11_get_is_modifier (backend_x11->keymap,
+ event->key.hardware_keycode);
+ event_x11->num_lock_set =
+ _clutter_keymap_x11_get_num_lock_state (backend_x11->keymap);
+ event_x11->caps_lock_set =
+ _clutter_keymap_x11_get_caps_lock_state (backend_x11->keymap);
+
+ /* unicode_value is the printable representation */
+ n = XLookupString (&xevent->xkey, buffer, sizeof (buffer) - 1, NULL, NULL);
+
+ if (n != NoSymbol)
+ {
+ event->key.unicode_value = g_utf8_get_char_validated (buffer, n);
+ if ((event->key.unicode_value != -1) &&
+ (event->key.unicode_value != -2))
+ goto out;
+ }
+ else
+ event->key.unicode_value = (gunichar)'\0';
+
+out:
+ CLUTTER_NOTE (EVENT,
+ "%s: win:0x%x, key: %12s (%d)",
+ event->any.type == CLUTTER_KEY_PRESS
+ ? "key press "
+ : "key release",
+ (unsigned int) xevent->xkey.window,
+ event->key.keyval ? buffer : "(none)",
+ event->key.keyval);
+ return;
+}
+
+#ifdef HAVE_XINPUT
+static ClutterInputDevice *
+get_device_from_event (ClutterDeviceManagerX11 *manager_x11,
+ XEvent *xevent)
+{
+ guint32 device_id;
+
+ device_id = ((XDeviceButtonEvent *) xevent)->deviceid;
+
+ return g_hash_table_lookup (manager_x11->devices_by_id,
+ GINT_TO_POINTER (device_id));
+}
+#endif /* HAVE_XINPUT */
+
+static ClutterTranslateReturn
+clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *event)
+{
+ ClutterDeviceManagerX11 *manager_x11;
+ ClutterBackendX11 *backend_x11;
+ ClutterInputDevice *device;
+ ClutterStageX11 *stage_x11;
+ ClutterTranslateReturn res;
+ ClutterStage *stage;
+ XEvent *xevent;
+
+ manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (translator);
+ backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
+ device = NULL;
+
+ xevent = native;
+
+ stage = clutter_x11_get_stage_from_window (xevent->xany.window);
+ if (stage == NULL)
+ return CLUTTER_TRANSLATE_CONTINUE;
+
+ if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
+ return CLUTTER_TRANSLATE_CONTINUE;
+
+ stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
+
+ event->any.stage = stage;
+
+ res = CLUTTER_TRANSLATE_CONTINUE;
+
+#ifdef HAVE_XINPUT
+ device = get_device_from_event (manager_x11, xevent);
+ if (device != NULL)
+ {
+ ClutterInputDeviceX11 *device_x11;
+ gboolean retval;
+
+ device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
+ retval = _clutter_input_device_x11_translate_xi_event (device_x11,
+ stage_x11,
+ xevent,
+ event);
+ if (retval)
+ return CLUTTER_TRANSLATE_QUEUE;
+ }
+#endif /* HAVE_XINPUT */
+
+ switch (xevent->type)
+ {
+ case KeyPress:
+ translate_key_event (backend_x11, manager_x11, event, xevent);
+ _clutter_stage_x11_set_user_time (stage_x11, xevent->xkey.time);
+ res = CLUTTER_TRANSLATE_QUEUE;
+ break;
+
+ case KeyRelease:
+ /* old-style X11 terminals require that even modern X11 send
+ * KeyPress/KeyRelease pairs when auto-repeating. for this
+ * reason modern(-ish) API like XKB has a way to detect
+ * auto-repeat and do a single KeyRelease at the end of a
+ * KeyPress sequence.
+ *
+ * this check emulates XKB's detectable auto-repeat; we peek
+ * the next event and check if it's a KeyPress for the same key
+ * and timestamp - and then ignore it if it matches the
+ * KeyRelease
+ *
+ * if we have XKB, and autorepeat is enabled, then this becomes
+ * a no-op
+ */
+ if (!backend_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
+ {
+ XEvent next_event;
+
+ XPeekEvent (xevent->xkey.display, &next_event);
+
+ if (next_event.type == KeyPress &&
+ next_event.xkey.keycode == xevent->xkey.keycode &&
+ next_event.xkey.time == xevent->xkey.time)
+ {
+ res = CLUTTER_TRANSLATE_REMOVE;
+ break;
+ }
+ }
+
+ translate_key_event (backend_x11, manager_x11, event, xevent);
+ res = CLUTTER_TRANSLATE_QUEUE;
+ break;
+
+ case ButtonPress:
+ CLUTTER_NOTE (EVENT,
+ "button press: win: 0x%x, coords: %d, %d, button: %d",
+ (unsigned int) stage_x11->xwin,
+ xevent->xbutton.x,
+ xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ switch (xevent->xbutton.button)
+ {
+ case 4: /* up */
+ case 5: /* down */
+ case 6: /* left */
+ case 7: /* right */
+ event->scroll.type = CLUTTER_SCROLL;
+
+ if (xevent->xbutton.button == 4)
+ event->scroll.direction = CLUTTER_SCROLL_UP;
+ else if (xevent->xbutton.button == 5)
+ event->scroll.direction = CLUTTER_SCROLL_DOWN;
+ else if (xevent->xbutton.button == 6)
+ event->scroll.direction = CLUTTER_SCROLL_LEFT;
+ else
+ event->scroll.direction = CLUTTER_SCROLL_RIGHT;
+
+ event->scroll.time = xevent->xbutton.time;
+ event->scroll.x = xevent->xbutton.x;
+ event->scroll.y = xevent->xbutton.y;
+ event->scroll.modifier_state = xevent->xbutton.state;
+ event->scroll.axes = NULL;
+ break;
+
+ default:
+ event->button.type = event->type = CLUTTER_BUTTON_PRESS;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
+ event->button.modifier_state = xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.axes = NULL;
+ break;
+ }
+
+ clutter_event_set_device (event, manager_x11->core_pointer);
+
+ _clutter_stage_x11_set_user_time (stage_x11, xevent->xbutton.time);
+ res = CLUTTER_TRANSLATE_QUEUE;
+ break;
+
+ case ButtonRelease:
+ CLUTTER_NOTE (EVENT,
+ "button press: win: 0x%x, coords: %d, %d, button: %d",
+ (unsigned int) stage_x11->xwin,
+ xevent->xbutton.x,
+ xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ /* scroll events don't have a corresponding release */
+ if (xevent->xbutton.button == 4 ||
+ xevent->xbutton.button == 5 ||
+ xevent->xbutton.button == 6 ||
+ xevent->xbutton.button == 7)
+ {
+ res = CLUTTER_TRANSLATE_REMOVE;
+ break;
+ }
+
+ event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
+ event->button.modifier_state = xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.axes = NULL;
+ clutter_event_set_device (event, manager_x11->core_pointer);
+ res = CLUTTER_TRANSLATE_QUEUE;
+ break;
+
+ case MotionNotify:
+ CLUTTER_NOTE (EVENT,
+ "motion: win: 0x%x, coords: %d, %d",
+ (unsigned int) stage_x11->xwin,
+ xevent->xmotion.x,
+ xevent->xmotion.y);
+
+ event->motion.type = event->type = CLUTTER_MOTION;
+ event->motion.time = xevent->xmotion.time;
+ event->motion.x = xevent->xmotion.x;
+ event->motion.y = xevent->xmotion.y;
+ event->motion.modifier_state = xevent->xmotion.state;
+ event->motion.axes = NULL;
+ clutter_event_set_device (event, manager_x11->core_pointer);
+ res = CLUTTER_TRANSLATE_QUEUE;
+ break;
+
+ case EnterNotify:
+ CLUTTER_NOTE (EVENT, "Entering the stage (time:%u)",
+ (unsigned int) xevent->xcrossing.time);
+
+ event->crossing.type = CLUTTER_ENTER;
+ event->crossing.time = xevent->xcrossing.time;
+ event->crossing.x = xevent->xcrossing.x;
+ event->crossing.y = xevent->xcrossing.y;
+ event->crossing.source = CLUTTER_ACTOR (stage);
+ event->crossing.related = NULL;
+ clutter_event_set_device (event, manager_x11->core_pointer);
+
+ _clutter_stage_add_device (stage, manager_x11->core_pointer);
+
+ res = CLUTTER_TRANSLATE_QUEUE;
+ break;
+
+ case LeaveNotify:
+ if (manager_x11->core_pointer->stage == NULL)
+ {
+ CLUTTER_NOTE (EVENT, "Discarding LeaveNotify for "
+ "ButtonRelease event off-stage");
+ res = CLUTTER_TRANSLATE_REMOVE;
+ break;
+ }
+
+ /* we know that we are leaving the stage here */
+ CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)",
+ (unsigned int) xevent->xcrossing.time);
+
+ event->crossing.type = CLUTTER_LEAVE;
+ event->crossing.time = xevent->xcrossing.time;
+ event->crossing.x = xevent->xcrossing.x;
+ event->crossing.y = xevent->xcrossing.y;
+ event->crossing.source = CLUTTER_ACTOR (stage);
+ event->crossing.related = NULL;
+ clutter_event_set_device (event, manager_x11->core_pointer);
+
+ _clutter_stage_remove_device (stage, manager_x11->core_pointer);
+
+ res = CLUTTER_TRANSLATE_QUEUE;
+ break;
+
+ default:
+ break;
+ }
+
+ return res;
+}
+
+static void
+clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface)
+{
+ iface->translate_event = clutter_device_manager_x11_translate_event;
+}
+
+static void
+clutter_device_manager_x11_constructed (GObject *gobject)
+{
+ ClutterDeviceManagerX11 *manager_x11;
+ ClutterBackendX11 *backend_x11;
+ ClutterDeviceManager *manager;
+#ifdef HAVE_XINPUT
+ XDeviceInfo *x_devices = NULL;
+ int i, n_devices;
+#endif /* HAVE_XINPUT */
+
+ manager = CLUTTER_DEVICE_MANAGER (gobject);
+ manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (gobject);
+
+ g_object_get (gobject, "backend", &backend_x11, NULL);
+ g_assert (backend_x11 != NULL);
+
+#ifdef HAVE_XINPUT
+ x_devices = XListInputDevices (backend_x11->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;
+ ClutterInputDevice *device;
+
+ CLUTTER_NOTE (BACKEND,
+ "Considering device %li with type %d, %d of %d",
+ info->id,
+ info->use,
+ i, n_devices);
+
+ device = create_device (manager_x11, backend_x11, info);
+ if (device != NULL)
+ _clutter_device_manager_add_device (manager, device);
+ }
+
+ XFreeDeviceList (x_devices);
+
+default_device:
+#endif /* HAVE_XINPUT */
+
+ /* fallback code in case:
+ *
+ * - we do not have XInput support compiled in
+ * - 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
+ */
+ manager_x11->core_pointer =
+ g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
+ "name", "Core Pointer",
+ "has-cursor", TRUE,
+ "device-type", CLUTTER_POINTER_DEVICE,
+ "device-manager", manager_x11,
+ "device-mode", CLUTTER_INPUT_MODE_MASTER,
+ "backend", backend_x11,
+ "enabled", TRUE,
+ NULL);
+ CLUTTER_NOTE (BACKEND, "Added core pointer device");
+
+ manager_x11->core_keyboard =
+ g_object_new (CLUTTER_TYPE_INPUT_DEVICE,
+ "name", "Core Keyboard",
+ "has-cursor", FALSE,
+ "device-type", CLUTTER_KEYBOARD_DEVICE,
+ "device-manager", manager_x11,
+ "device-mode", CLUTTER_INPUT_MODE_MASTER,
+ "backend", backend_x11,
+ "enabled", TRUE,
+ NULL);
+ CLUTTER_NOTE (BACKEND, "Added core keyboard device");
+
+ /* associate core devices */
+ _clutter_input_device_set_associated_device (manager_x11->core_pointer,
+ manager_x11->core_keyboard);
+ _clutter_input_device_set_associated_device (manager_x11->core_keyboard,
+ manager_x11->core_pointer);
+
+ if (G_OBJECT_CLASS (clutter_device_manager_x11_parent_class)->constructed)
+ G_OBJECT_CLASS (clutter_device_manager_x11_parent_class)->constructed (gobject);
+}
+
+static void
+clutter_device_manager_x11_add_device (ClutterDeviceManager *manager,
+ ClutterInputDevice *device)
+{
+ ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
+
+ manager_x11->devices = g_slist_prepend (manager_x11->devices, device);
+ g_hash_table_replace (manager_x11->devices_by_id,
+ GINT_TO_POINTER (device->id),
+ device);
+
+ /* blow the cache */
+ g_slist_free (manager_x11->all_devices);
+ manager_x11->all_devices = NULL;
+}
+
+static void
+clutter_device_manager_x11_remove_device (ClutterDeviceManager *manager,
+ ClutterInputDevice *device)
+{
+ ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
+
+ g_hash_table_remove (manager_x11->devices_by_id,
+ GINT_TO_POINTER (device->id));
+ manager_x11->devices = g_slist_remove (manager_x11->devices, device);
+
+ /* blow the cache */
+ g_slist_free (manager_x11->all_devices);
+ manager_x11->all_devices = NULL;
+}
+
+static const GSList *
+clutter_device_manager_x11_get_devices (ClutterDeviceManager *manager)
+{
+ ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
+
+ /* cache the devices list so that we can keep the core pointer
+ * and keyboard outside of the ManagerX11:devices list
+ */
+ if (manager_x11->all_devices == NULL)
+ {
+ GSList *all_devices = manager_x11->devices;
+
+ all_devices = g_slist_prepend (all_devices, manager_x11->core_keyboard);
+ all_devices = g_slist_prepend (all_devices, manager_x11->core_pointer);
+
+ manager_x11->all_devices = all_devices;
+ }
+
+ return CLUTTER_DEVICE_MANAGER_X11 (manager)->all_devices;
+}
+
+static ClutterInputDevice *
+clutter_device_manager_x11_get_core_device (ClutterDeviceManager *manager,
+ ClutterInputDeviceType type)
+{
+ ClutterDeviceManagerX11 *manager_x11;
+
+ manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
+
+ switch (type)
+ {
+ case CLUTTER_POINTER_DEVICE:
+ return manager_x11->core_pointer;
+
+ case CLUTTER_KEYBOARD_DEVICE:
+ return manager_x11->core_keyboard;
+
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static ClutterInputDevice *
+clutter_device_manager_x11_get_device (ClutterDeviceManager *manager,
+ gint id)
+{
+ ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
+
+ return g_hash_table_lookup (manager_x11->devices_by_id,
+ GINT_TO_POINTER (id));
+}
+
+static void
+clutter_device_manager_x11_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_EVENT_BASE:
+ manager_x11->xi_event_base = g_value_get_int (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+clutter_device_manager_x11_class_init (ClutterDeviceManagerX11Class *klass)
+{
+ ClutterDeviceManagerClass *manager_class;
+ GObjectClass *gobject_class;
+
+ obj_props[PROP_EVENT_BASE] =
+ g_param_spec_int ("event-base",
+ "Event Base",
+ "The first XI event",
+ -1, G_MAXINT,
+ -1,
+ CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->constructed = clutter_device_manager_x11_constructed;
+ gobject_class->set_property = clutter_device_manager_x11_set_property;
+
+ g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
+
+ manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
+ manager_class->add_device = clutter_device_manager_x11_add_device;
+ manager_class->remove_device = clutter_device_manager_x11_remove_device;
+ manager_class->get_devices = clutter_device_manager_x11_get_devices;
+ manager_class->get_core_device = clutter_device_manager_x11_get_core_device;
+ manager_class->get_device = clutter_device_manager_x11_get_device;
+}
+
+static void
+clutter_device_manager_x11_init (ClutterDeviceManagerX11 *self)
+{
+ self->devices_by_id = g_hash_table_new (NULL, NULL);
+}
*
* An OpenGL based 'interactive canvas' library.
*
- * Copyright (C) 2009 Intel Corp.
+ * Copyright © 2009, 2010, 2011 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
G_BEGIN_DECLS
-#define CLUTTER_TYPE_DEVICE_MANAGER_X11 (clutter_device_manager_x11_get_type ())
+#define CLUTTER_TYPE_DEVICE_MANAGER_X11 (_clutter_device_manager_x11_get_type ())
#define CLUTTER_DEVICE_MANAGER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_X11, ClutterDeviceManagerX11))
#define CLUTTER_IS_DEVICE_MANAGER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_X11))
#define CLUTTER_DEVICE_MANAGER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_X11, ClutterDeviceManagerX11Class))
{
ClutterDeviceManager parent_instance;
+ GHashTable *devices_by_id;
+
/* the list of transient devices */
GSList *devices;
ClutterInputDevice *core_pointer;
ClutterInputDevice *core_keyboard;
- guint use_xinput_1 : 1;
+ int xi_event_base;
};
struct _ClutterDeviceManagerX11Class
ClutterDeviceManagerClass parent_class;
};
-GType clutter_device_manager_x11_get_type (void) G_GNUC_CONST;
+GType _clutter_device_manager_x11_get_type (void) G_GNUC_CONST;
G_END_DECLS
+++ /dev/null
-/*
- * 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>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "clutter-backend-x11.h"
-#include "clutter-device-manager-x11.h"
-#include "clutter-input-device-x11.h"
-#include "clutter-stage-x11.h"
-
-#include "clutter-backend.h"
-#include "clutter-debug.h"
-#include "clutter-device-manager-private.h"
-#include "clutter-private.h"
-
-#ifdef HAVE_XINPUT
-#include <X11/extensions/XInput.h>
-#endif
-
-enum
-{
- PROP_0,
-
- PROP_USE_XINPUT_1,
-
- PROP_LAST
-};
-
-static GParamSpec *obj_props[PROP_LAST];
-
-G_DEFINE_TYPE (ClutterDeviceManagerX11,
- clutter_device_manager_x11,
- CLUTTER_TYPE_DEVICE_MANAGER);
-
-static void
-clutter_device_manager_x11_constructed (GObject *gobject)
-{
- ClutterDeviceManagerX11 *manager_x11;
- ClutterBackendX11 *backend_x11;
- 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 (gobject);
- manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (gobject);
- if (!manager_x11->use_xinput_1)
- {
- CLUTTER_NOTE (BACKEND, "XInput support not enabled");
- goto default_device;
- }
-
- g_object_get (gobject, "backend", &backend_x11, NULL);
- g_assert (backend_x11 != NULL);
-
-#ifdef HAVE_XINPUT
- res = XQueryExtension (backend_x11->xdpy, "XInputExtension",
- &opcode,
- &event,
- &error);
- if (!res)
- {
- CLUTTER_NOTE (BACKEND, "No XInput extension available");
- goto default_device;
- }
-
- backend_x11->xi_event_base = event;
-
- x_devices = XListInputDevices (backend_x11->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:
- default:
- 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_x11);
-
- _clutter_device_manager_add_device (manager, device);
-
- if (info->use == IsXExtensionPointer && n_events > 0)
- backend_x11->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");
- manager_x11->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");
- manager_x11->core_keyboard = device;
-
- if (G_OBJECT_CLASS (clutter_device_manager_x11_parent_class)->constructed)
- G_OBJECT_CLASS (clutter_device_manager_x11_parent_class)->constructed (gobject);
-}
-
-static void
-clutter_device_manager_x11_add_device (ClutterDeviceManager *manager,
- ClutterInputDevice *device)
-{
- ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
-
- manager_x11->devices = g_slist_prepend (manager_x11->devices, device);
-
- /* blow the cache */
- g_slist_free (manager_x11->all_devices);
- manager_x11->all_devices = NULL;
-}
-
-static void
-clutter_device_manager_x11_remove_device (ClutterDeviceManager *manager,
- ClutterInputDevice *device)
-{
- ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
-
- manager_x11->devices = g_slist_remove (manager_x11->devices, device);
-
- /* blow the cache */
- g_slist_free (manager_x11->all_devices);
- manager_x11->all_devices = NULL;
-}
-
-static const GSList *
-clutter_device_manager_x11_get_devices (ClutterDeviceManager *manager)
-{
- ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
-
- /* cache the devices list so that we can keep the core pointer
- * and keyboard outside of the ManagerX11:devices list
- */
- if (manager_x11->all_devices == NULL)
- {
- GSList *all_devices;
-
- all_devices = manager_x11->devices;
- all_devices = g_slist_prepend (all_devices, manager_x11->core_keyboard);
- all_devices = g_slist_prepend (all_devices, manager_x11->core_pointer);
-
- manager_x11->all_devices = all_devices;
- }
-
- return CLUTTER_DEVICE_MANAGER_X11 (manager)->all_devices;
-}
-
-static ClutterInputDevice *
-clutter_device_manager_x11_get_core_device (ClutterDeviceManager *manager,
- ClutterInputDeviceType type)
-{
- ClutterDeviceManagerX11 *manager_x11;
-
- manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
-
- switch (type)
- {
- case CLUTTER_POINTER_DEVICE:
- return manager_x11->core_pointer;
-
- case CLUTTER_KEYBOARD_DEVICE:
- return manager_x11->core_keyboard;
-
- case CLUTTER_EXTENSION_DEVICE:
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-static ClutterInputDevice *
-clutter_device_manager_x11_get_device (ClutterDeviceManager *manager,
- gint id)
-{
- ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager);
- GSList *l;
-
- for (l = manager_x11->devices; l != NULL; l = l->next)
- {
- ClutterInputDevice *device = l->data;
-
- if (clutter_input_device_get_device_id (device) == id)
- return device;
- }
-
- return NULL;
-}
-
-static void
-clutter_device_manager_x11_set_property (GObject *gobject,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- ClutterDeviceManagerX11 *manager_x11;
-
- manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (gobject);
-
- switch (prop_id)
- {
- case PROP_USE_XINPUT_1:
- manager_x11->use_xinput_1 = g_value_get_boolean (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
- break;
- }
-}
-
-static void
-clutter_device_manager_x11_get_property (GObject *gobject,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ClutterDeviceManagerX11 *manager_x11;
-
- manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (gobject);
-
- switch (prop_id)
- {
- case PROP_USE_XINPUT_1:
- g_value_set_boolean (value, manager_x11->use_xinput_1);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
- break;
- }
-}
-
-static void
-clutter_device_manager_x11_class_init (ClutterDeviceManagerX11Class *klass)
-{
- ClutterDeviceManagerClass *manager_class;
- GObjectClass *gobject_class;
- GParamSpec *pspec;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->set_property = clutter_device_manager_x11_set_property;
- gobject_class->get_property = clutter_device_manager_x11_get_property;
- gobject_class->constructed = clutter_device_manager_x11_constructed;
-
- manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
- manager_class->add_device = clutter_device_manager_x11_add_device;
- manager_class->remove_device = clutter_device_manager_x11_remove_device;
- manager_class->get_devices = clutter_device_manager_x11_get_devices;
- manager_class->get_core_device = clutter_device_manager_x11_get_core_device;
- manager_class->get_device = clutter_device_manager_x11_get_device;
-
- pspec = g_param_spec_boolean ("use-xinput-1",
- "Use XInput 1",
- "Use the XInput 1.0 extension",
- FALSE,
- CLUTTER_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- obj_props[PROP_USE_XINPUT_1] = pspec;
- g_object_class_install_property (gobject_class, PROP_USE_XINPUT_1, pspec);
-}
-
-static void
-clutter_device_manager_x11_init (ClutterDeviceManagerX11 *self)
-{
- self->use_xinput_1 = FALSE;
-}
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright © 2011 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>
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "clutter-device-manager-xi2.h"
+
+#include "clutter-backend-x11.h"
+#include "clutter-input-device-xi2.h"
+#include "clutter-stage-x11.h"
+
+#include "clutter-backend.h"
+#include "clutter-debug.h"
+#include "clutter-device-manager-private.h"
+#include "clutter-event-translator.h"
+#include "clutter-stage-private.h"
+#include "clutter-private.h"
+
+#include <X11/extensions/XInput2.h>
+
+enum
+{
+ PROP_0,
+
+ PROP_OPCODE,
+
+ PROP_LAST
+};
+
+static GParamSpec *obj_props[PROP_LAST] = { NULL, };
+
+static const char *clutter_input_axis_atom_names[] = {
+ "Abs X", /* CLUTTER_INPUT_AXIS_X */
+ "Abs Y", /* CLUTTER_INPUT_AXIS_Y */
+ "Abs Pressure", /* CLUTTER_INPUT_AXIS_PRESSURE */
+ "Abs Tilt X", /* CLUTTER_INPUT_AXIS_XTILT */
+ "Abs Tilt Y", /* CLUTTER_INPUT_AXIS_YTILT */
+ "Abs Wheel", /* CLUTTER_INPUT_AXIS_WHEEL */
+};
+
+#define N_AXIS_ATOMS G_N_ELEMENTS (clutter_input_axis_atom_names)
+
+static Atom clutter_input_axis_atoms[N_AXIS_ATOMS] = { 0, };
+
+static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
+
+#define clutter_device_manager_xi2_get_type _clutter_device_manager_xi2_get_type
+
+G_DEFINE_TYPE_WITH_CODE (ClutterDeviceManagerXI2,
+ clutter_device_manager_xi2,
+ CLUTTER_TYPE_DEVICE_MANAGER,
+ G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
+ clutter_event_translator_iface_init));
+
+static void
+translate_valuator_class (Display *xdisplay,
+ ClutterInputDevice *device,
+ XIValuatorClassInfo *class)
+{
+ static gboolean atoms_initialized = FALSE;
+ ClutterInputAxis axis, i;
+
+ if (G_UNLIKELY (!atoms_initialized))
+ {
+ XInternAtoms (xdisplay,
+ (char **) clutter_input_axis_atom_names, N_AXIS_ATOMS,
+ False,
+ clutter_input_axis_atoms);
+
+ atoms_initialized = TRUE;
+ }
+
+ for (i = CLUTTER_INPUT_AXIS_IGNORE;
+ i <= CLUTTER_INPUT_AXIS_WHEEL;
+ i += 1)
+ {
+ if (clutter_input_axis_atoms[i] == class->label)
+ {
+ axis = i;
+ break;
+ }
+ }
+
+ _clutter_input_device_add_axis (device, axis,
+ class->min,
+ class->max,
+ class->resolution);
+
+ CLUTTER_NOTE (BACKEND,
+ "Added axis '%s' (min:%.2f, max:%.2fd, res:%d) of device %d",
+ clutter_input_axis_atom_names[axis],
+ class->min,
+ class->max,
+ class->resolution,
+ device->id);
+}
+
+static void
+translate_device_classes (Display *xdisplay,
+ ClutterInputDevice *device,
+ XIAnyClassInfo **classes,
+ guint n_classes)
+{
+ gint i;
+
+ for (i = 0; i < n_classes; i++)
+ {
+ XIAnyClassInfo *class_info = classes[i];
+
+ switch (class_info->type)
+ {
+ case XIKeyClass:
+ {
+ XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
+ gint j;
+
+ _clutter_input_device_set_n_keys (device,
+ key_info->num_keycodes);
+
+ for (j = 0; j < key_info->num_keycodes; j++)
+ {
+ clutter_input_device_set_key (device, j,
+ key_info->keycodes[i],
+ 0);
+ }
+ }
+ break;
+
+ case XIValuatorClass:
+ translate_valuator_class (xdisplay, device,
+ (XIValuatorClassInfo *) class_info);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+static ClutterInputDevice *
+create_device (ClutterDeviceManagerXI2 *manager_xi2,
+ ClutterBackendX11 *backend_x11,
+ XIDeviceInfo *info)
+{
+ ClutterInputDeviceType source;
+ ClutterInputDevice *retval;
+ ClutterInputMode mode;
+ gboolean is_enabled;
+
+ if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
+ source = CLUTTER_KEYBOARD_DEVICE;
+ else
+ {
+ gchar *name;
+
+ name = g_ascii_strdown (info->name, -1);
+
+ if (strstr (name, "eraser") != NULL)
+ source = CLUTTER_ERASER_DEVICE;
+ else if (strstr (name, "cursor") != NULL)
+ source = CLUTTER_CURSOR_DEVICE;
+ else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL)
+ source = CLUTTER_PEN_DEVICE;
+ else
+ source = CLUTTER_POINTER_DEVICE;
+
+ g_free (name);
+ }
+
+ switch (info->use)
+ {
+ case XIMasterKeyboard:
+ case XIMasterPointer:
+ mode = CLUTTER_INPUT_MODE_MASTER;
+ is_enabled = TRUE;
+ break;
+
+ case XISlaveKeyboard:
+ case XISlavePointer:
+ mode = CLUTTER_INPUT_MODE_SLAVE;
+ is_enabled = FALSE;
+ break;
+
+ case XIFloatingSlave:
+ default:
+ mode = CLUTTER_INPUT_MODE_FLOATING;
+ is_enabled = FALSE;
+ break;
+ }
+
+ retval = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_XI2,
+ "name", info->name,
+ "id", info->deviceid,
+ "has-cursor", (info->use == XIMasterPointer),
+ "device-manager", manager_xi2,
+ "device-type", source,
+ "device-mode", mode,
+ "backend", backend_x11,
+ "enabled", is_enabled,
+ NULL);
+
+ translate_device_classes (backend_x11->xdpy, retval,
+ info->classes,
+ info->num_classes);
+
+ CLUTTER_NOTE (BACKEND, "Created device '%s' (id: %d, has-cursor: %s)",
+ info->name,
+ info->deviceid,
+ info->use == XIMasterPointer ? "yes" : "no");
+
+ return retval;
+}
+
+static ClutterInputDevice *
+add_device (ClutterDeviceManagerXI2 *manager_xi2,
+ ClutterBackendX11 *backend_x11,
+ XIDeviceInfo *info,
+ gboolean in_construction)
+{
+ ClutterInputDevice *device;
+
+ device = create_device (manager_xi2, backend_x11, info);
+
+ /* we don't go through the DeviceManager::add_device() vfunc because
+ * that emits the signal, and we only do it conditionally
+ */
+ g_hash_table_replace (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (info->deviceid),
+ g_object_ref (device));
+
+ if (info->use == XIMasterPointer ||
+ info->use == XIMasterKeyboard)
+ {
+ manager_xi2->master_devices =
+ g_list_prepend (manager_xi2->master_devices, device);
+ }
+ else if (info->use == XISlavePointer ||
+ info->use == XISlaveKeyboard ||
+ info->use == XIFloatingSlave)
+ {
+ manager_xi2->slave_devices =
+ g_list_prepend (manager_xi2->slave_devices, device);
+ }
+ else
+ g_warning ("Unhandled device: %s",
+ clutter_input_device_get_device_name (device));
+
+ /* relationships between devices and signal emissions are not
+ * necessary while we're constructing the device manager instance
+ */
+ if (!in_construction)
+ {
+ if (info->use == XISlavePointer || info->use == XISlaveKeyboard)
+ {
+ ClutterInputDevice *master;
+
+ master = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (info->attachment));
+ _clutter_input_device_set_associated_device (device, master);
+ _clutter_input_device_add_slave (master, device);
+ }
+
+ /* blow the cache */
+ g_slist_free (manager_xi2->all_devices);
+ manager_xi2->all_devices = NULL;
+
+ g_signal_emit_by_name (manager_xi2, "device-added", device);
+ }
+
+ return device;
+}
+
+static void
+remove_device (ClutterDeviceManagerXI2 *manager_xi2,
+ gint device_id)
+{
+ ClutterInputDevice *device;
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (device_id));
+
+ if (device != NULL)
+ {
+ manager_xi2->master_devices =
+ g_list_remove (manager_xi2->master_devices, device);
+ manager_xi2->slave_devices =
+ g_list_remove (manager_xi2->slave_devices, device);
+
+ /* blow the cache */
+ g_slist_free (manager_xi2->all_devices);
+ manager_xi2->all_devices = NULL;
+
+ g_signal_emit_by_name (manager_xi2, "device-removed", device);
+
+ g_object_run_dispose (G_OBJECT (device));
+
+ g_hash_table_remove (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (device_id));
+ }
+}
+
+static void
+translate_hierarchy_event (ClutterBackendX11 *backend_x11,
+ ClutterDeviceManagerXI2 *manager_xi2,
+ XIHierarchyEvent *ev)
+{
+ ClutterInputDevice *device;
+ int i;
+
+ for (i = 0; i < ev->num_info; i++)
+ {
+ if (ev->info[i].flags & XIDeviceEnabled)
+ {
+ XIDeviceInfo *info;
+ int n_devices;
+
+ CLUTTER_NOTE (EVENT, "Hierarchy event: device enabled");
+
+ info = XIQueryDevice (backend_x11->xdpy,
+ ev->info[i].deviceid,
+ &n_devices);
+ device = add_device (manager_xi2, backend_x11, &info[0], FALSE);
+ }
+ else if (ev->info[i].flags & XIDeviceDisabled)
+ {
+ CLUTTER_NOTE (EVENT, "Hierarchy event: device disabled");
+
+ remove_device (manager_xi2, ev->info[i].deviceid);
+ }
+ else if ((ev->info[i].flags & XISlaveAttached) ||
+ (ev->info[i].flags & XISlaveDetached))
+ {
+ ClutterInputDevice *master, *slave;
+ XIDeviceInfo *info;
+ int n_devices;
+
+ CLUTTER_NOTE (EVENT, "Hierarchy event: slave %s",
+ (ev->info[i].flags & XISlaveAttached)
+ ? "attached"
+ : "detached");
+
+ slave = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (ev->info[i].deviceid));
+ master = clutter_input_device_get_associated_device (slave);
+
+ /* detach the slave in both cases */
+ if (master != NULL)
+ {
+ _clutter_input_device_remove_slave (master, slave);
+ _clutter_input_device_set_associated_device (slave, NULL);
+ }
+
+ /* and attach the slave to the new master if needed */
+ if (ev->info[i].flags & XISlaveAttached)
+ {
+ info = XIQueryDevice (backend_x11->xdpy,
+ ev->info[i].deviceid,
+ &n_devices);
+ master = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (info->attachment));
+ _clutter_input_device_set_associated_device (slave, master);
+ _clutter_input_device_add_slave (master, slave);
+
+ XIFreeDeviceInfo (info);
+ }
+ }
+ }
+}
+
+static void
+clutter_device_manager_xi2_select_events (ClutterDeviceManager *manager,
+ Window xwindow,
+ XIEventMask *event_mask)
+{
+ Display *xdisplay;
+
+ xdisplay = clutter_x11_get_default_display ();
+
+ XISelectEvents (xdisplay, xwindow, event_mask, 1);
+}
+
+static ClutterStage *
+get_event_stage (ClutterEventTranslator *translator,
+ XIEvent *xi_event)
+{
+ Window xwindow = None;
+
+ switch (xi_event->evtype)
+ {
+ case XI_KeyPress:
+ case XI_KeyRelease:
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
+
+ xwindow = xev->event;
+ }
+ break;
+
+ case XI_Enter:
+ case XI_Leave:
+ case XI_FocusIn:
+ case XI_FocusOut:
+ {
+ XIEnterEvent *xev = (XIEnterEvent *) xi_event;
+
+ xwindow = xev->event;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (xwindow == None)
+ return NULL;
+
+ return clutter_x11_get_stage_from_window (xwindow);
+}
+
+/*
+ * print_key_sym: Translate a symbol to its printable form if any
+ * @symbol: the symbol to translate
+ * @buffer: the buffer where to put the translated string
+ * @len: size of the buffer
+ *
+ * Translates @symbol into a printable representation in @buffer, if possible.
+ *
+ * Return value: The number of bytes of the translated string, 0 if the
+ * symbol can't be printed
+ *
+ * Note: The code is derived from libX11's src/KeyBind.c
+ * Copyright 1985, 1987, 1998 The Open Group
+ *
+ * Note: This code works for Latin-1 symbols. clutter_keysym_to_unicode()
+ * does the work for the other keysyms.
+ */
+static int
+print_keysym (uint32_t symbol,
+ char *buffer,
+ int len)
+{
+ unsigned long high_bytes;
+ unsigned char c;
+
+ high_bytes = symbol >> 8;
+ if (!(len &&
+ ((high_bytes == 0) ||
+ ((high_bytes == 0xFF) &&
+ (((symbol >= CLUTTER_KEY_BackSpace) &&
+ (symbol <= CLUTTER_KEY_Clear)) ||
+ (symbol == CLUTTER_KEY_Return) ||
+ (symbol == CLUTTER_KEY_Escape) ||
+ (symbol == CLUTTER_KEY_KP_Space) ||
+ (symbol == CLUTTER_KEY_KP_Tab) ||
+ (symbol == CLUTTER_KEY_KP_Enter) ||
+ ((symbol >= CLUTTER_KEY_KP_Multiply) &&
+ (symbol <= CLUTTER_KEY_KP_9)) ||
+ (symbol == CLUTTER_KEY_KP_Equal) ||
+ (symbol == CLUTTER_KEY_Delete))))))
+ return 0;
+
+ /* if X keysym, convert to ascii by grabbing low 7 bits */
+ if (symbol == CLUTTER_KEY_KP_Space)
+ c = CLUTTER_KEY_space & 0x7F; /* patch encoding botch */
+ else if (high_bytes == 0xFF)
+ c = symbol & 0x7F;
+ else
+ c = symbol & 0xFF;
+
+ buffer[0] = c;
+ return 1;
+}
+
+static gdouble *
+translate_axes (ClutterInputDevice *device,
+ gdouble x,
+ gdouble y,
+ ClutterStageX11 *stage_x11,
+ XIValuatorState *valuators)
+{
+ guint n_axes = clutter_input_device_get_n_axes (device);
+ guint i;
+ gdouble *retval;
+ double *values;
+
+ retval = g_new0 (gdouble, n_axes);
+ values = valuators->values;
+
+ for (i = 0; i < valuators->mask_len * 8; i++)
+ {
+ ClutterInputAxis axis;
+ gdouble val;
+
+ if (!XIMaskIsSet (valuators->mask, i))
+ continue;
+
+ axis = clutter_input_device_get_axis (device, i);
+ val = *values++;
+
+ switch (axis)
+ {
+ case CLUTTER_INPUT_AXIS_X:
+ retval[i] = x;
+ break;
+
+ case CLUTTER_INPUT_AXIS_Y:
+ retval[i] = y;
+ break;
+
+ default:
+ _clutter_input_device_translate_axis (device, i, val, &retval[i]);
+ break;
+ }
+ }
+
+ return retval;
+}
+
+static ClutterTranslateReturn
+clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *event)
+{
+ ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (translator);
+ ClutterTranslateReturn retval = CLUTTER_TRANSLATE_CONTINUE;
+ ClutterBackendX11 *backend_x11;
+ ClutterStageX11 *stage_x11 = NULL;
+ ClutterStage *stage = NULL;
+ ClutterInputDevice *device, *source_device;
+ XGenericEventCookie *cookie;
+ XIEvent *xi_event;
+ XEvent *xevent;
+
+ backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
+
+ xevent = native;
+
+ cookie = &xevent->xcookie;
+
+ if (!XGetEventData (backend_x11->xdpy, cookie))
+ return CLUTTER_TRANSLATE_CONTINUE;
+
+ if (cookie->type != GenericEvent ||
+ cookie->extension != manager_xi2->opcode)
+ {
+ XFreeEventData (backend_x11->xdpy, cookie);
+ return CLUTTER_TRANSLATE_CONTINUE;
+ }
+
+ xi_event = (XIEvent *) cookie->data;
+
+ if (!(xi_event->evtype == XI_HierarchyChanged ||
+ xi_event->evtype == XI_DeviceChanged))
+ {
+ stage = get_event_stage (translator, xi_event);
+ if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
+ {
+ XFreeEventData (backend_x11->xdpy, cookie);
+ return CLUTTER_TRANSLATE_CONTINUE;
+ }
+ else
+ stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
+ }
+
+ event->any.stage = stage;
+
+ switch (xi_event->evtype)
+ {
+ case XI_HierarchyChanged:
+ {
+ XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event;
+
+ translate_hierarchy_event (backend_x11, manager_xi2, xev);
+ }
+ retval = CLUTTER_TRANSLATE_REMOVE;
+ break;
+
+ case XI_DeviceChanged:
+ {
+ XIDeviceChangedEvent *xev = (XIDeviceChangedEvent *) xi_event;
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->deviceid));
+ _clutter_input_device_reset_axes (device);
+ translate_device_classes (backend_x11->xdpy,
+ device,
+ xev->classes,
+ xev->num_classes);
+ }
+ retval = CLUTTER_TRANSLATE_REMOVE;
+ break;
+
+ case XI_KeyPress:
+ case XI_KeyRelease:
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
+ ClutterEventX11 *event_x11;
+ char buffer[7] = { 0, };
+ gunichar n;
+
+ event->key.type = event->type = (xev->evtype == XI_KeyPress)
+ ? CLUTTER_KEY_PRESS
+ : CLUTTER_KEY_RELEASE;
+
+ event->key.time = xev->time;
+ event->key.stage = stage;
+ event->key.modifier_state =
+ _clutter_input_device_xi2_translate_state (&xev->mods, &xev->buttons);
+ event->key.hardware_keycode = xev->detail;
+
+ /* keyval is the key ignoring all modifiers ('1' vs. '!') */
+ event->key.keyval =
+ _clutter_keymap_x11_translate_key_state (backend_x11->keymap,
+ event->key.hardware_keycode,
+ event->key.modifier_state,
+ NULL);
+
+ /* KeyEvents have platform specific data associated to them */
+ event_x11 = _clutter_event_x11_new ();
+ _clutter_event_set_platform_data (event, event_x11);
+
+ event_x11->key_group =
+ _clutter_keymap_x11_get_key_group (backend_x11->keymap,
+ event->key.modifier_state);
+ event_x11->key_is_modifier =
+ _clutter_keymap_x11_get_is_modifier (backend_x11->keymap,
+ event->key.hardware_keycode);
+ event_x11->num_lock_set =
+ _clutter_keymap_x11_get_num_lock_state (backend_x11->keymap);
+ event_x11->caps_lock_set =
+ _clutter_keymap_x11_get_caps_lock_state (backend_x11->keymap);
+
+ source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->sourceid));
+ _clutter_event_set_source_device (event, source_device);
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->deviceid));
+ _clutter_event_set_device (event, device);
+
+ /* XXX keep this in sync with the evdev device manager */
+ n = print_keysym (event->key.keyval, buffer, sizeof (buffer));
+ if (n == 0)
+ {
+ /* not printable */
+ event->key.unicode_value = (gunichar) '\0';
+ }
+ else
+ {
+ event->key.unicode_value = g_utf8_get_char_validated (buffer, n);
+ if (event->key.unicode_value == -1 ||
+ event->key.unicode_value == -2)
+ event->key.unicode_value = (gunichar) '\0';
+ }
+
+ CLUTTER_NOTE (EVENT,
+ "%s: win:0x%x device:%d source:%d, key: %12s (%d)",
+ event->any.type == CLUTTER_KEY_PRESS
+ ? "key press "
+ : "key release",
+ (unsigned int) stage_x11->xwin,
+ xev->deviceid,
+ xev->sourceid,
+ event->key.keyval ? buffer : "(none)",
+ event->key.keyval);
+
+ if (xi_event->evtype == XI_KeyPress)
+ _clutter_stage_x11_set_user_time (stage_x11, event->key.time);
+
+ retval = CLUTTER_TRANSLATE_QUEUE;
+ }
+ break;
+
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
+
+ switch (xev->detail)
+ {
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ event->scroll.type = event->type = CLUTTER_SCROLL;
+
+ if (xev->detail == 4)
+ event->scroll.direction = CLUTTER_SCROLL_UP;
+ else if (xev->detail == 5)
+ event->scroll.direction = CLUTTER_SCROLL_DOWN;
+ else if (xev->detail == 6)
+ event->scroll.direction = CLUTTER_SCROLL_LEFT;
+ else
+ event->scroll.direction = CLUTTER_SCROLL_RIGHT;
+
+ event->scroll.stage = stage;
+
+ event->scroll.time = xev->time;
+ event->scroll.x = xev->event_x;
+ event->scroll.y = xev->event_y;
+ event->scroll.modifier_state =
+ _clutter_input_device_xi2_translate_state (&xev->mods,
+ &xev->buttons);
+
+ source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->sourceid));
+ _clutter_event_set_source_device (event, source_device);
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->deviceid));
+ _clutter_event_set_device (event, device);
+
+ event->scroll.axes = translate_axes (event->scroll.device,
+ event->scroll.x,
+ event->scroll.y,
+ stage_x11,
+ &xev->valuators);
+
+ break;
+
+ default:
+ event->button.type = event->type =
+ (xi_event->evtype == XI_ButtonPress) ? CLUTTER_BUTTON_PRESS
+ : CLUTTER_BUTTON_RELEASE;
+
+ event->button.stage = stage;
+
+ event->button.time = xev->time;
+ event->button.x = xev->event_x;
+ event->button.y = xev->event_y;
+ event->button.button = xev->detail;
+ event->button.modifier_state =
+ _clutter_input_device_xi2_translate_state (&xev->mods,
+ &xev->buttons);
+
+ source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->sourceid));
+ _clutter_event_set_source_device (event, source_device);
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->deviceid));
+ _clutter_event_set_device (event, device);
+
+ event->button.axes = translate_axes (event->button.device,
+ event->button.x,
+ event->button.y,
+ stage_x11,
+ &xev->valuators);
+ break;
+ }
+
+ if (source_device != NULL && device->stage != NULL)
+ _clutter_input_device_set_stage (source_device, device->stage);
+
+ CLUTTER_NOTE (EVENT,
+ "%s: win:0x%x, device:%s (button:%d, x:%.2f, y:%.2f, axes:%s)",
+ event->any.type == CLUTTER_BUTTON_PRESS
+ ? "button press "
+ : "button release",
+ (unsigned int) stage_x11->xwin,
+ event->button.device->device_name,
+ event->button.button,
+ event->button.x,
+ event->button.y,
+ event->button.axes != NULL ? "yes" : "no");
+
+ if (xi_event->evtype == XI_ButtonPress)
+ _clutter_stage_x11_set_user_time (stage_x11, event->button.time);
+
+ retval = CLUTTER_TRANSLATE_QUEUE;
+ }
+ break;
+
+ case XI_Motion:
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
+
+ event->motion.type = event->type = CLUTTER_MOTION;
+
+ event->motion.stage = stage;
+
+ event->motion.time = xev->time;
+ event->motion.x = xev->event_x;
+ event->motion.y = xev->event_y;
+ event->motion.modifier_state =
+ _clutter_input_device_xi2_translate_state (&xev->mods,
+ &xev->buttons);
+
+ source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->sourceid));
+ _clutter_event_set_source_device (event, source_device);
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->deviceid));
+ _clutter_event_set_device (event, device);
+
+ event->motion.axes = translate_axes (event->motion.device,
+ event->motion.x,
+ event->motion.y,
+ stage_x11,
+ &xev->valuators);
+
+ if (source_device != NULL && device->stage != NULL)
+ _clutter_input_device_set_stage (source_device, device->stage);
+
+ CLUTTER_NOTE (EVENT, "motion: win:0x%x device:%s (x:%.2f, y:%.2f, axes:%s)",
+ (unsigned int) stage_x11->xwin,
+ event->motion.device->device_name,
+ event->motion.x,
+ event->motion.y,
+ event->motion.axes != NULL ? "yes" : "no");
+
+ retval = CLUTTER_TRANSLATE_QUEUE;
+ }
+ break;
+
+ case XI_Enter:
+ case XI_Leave:
+ {
+ XIEnterEvent *xev = (XIEnterEvent *) xi_event;
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->deviceid));
+
+ source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->sourceid));
+
+ if (xi_event->evtype == XI_Enter)
+ {
+ event->crossing.type = event->type = CLUTTER_ENTER;
+
+ event->crossing.stage = stage;
+ event->crossing.source = CLUTTER_ACTOR (stage);
+ event->crossing.related = NULL;
+
+ event->crossing.time = xev->time;
+ event->crossing.x = xev->event_x;
+ event->crossing.y = xev->event_y;
+
+ _clutter_stage_add_device (stage, device);
+ }
+ else
+ {
+ if (device->stage == NULL)
+ {
+ CLUTTER_NOTE (EVENT,
+ "Discarding Leave for ButtonRelease "
+ "event off-stage");
+
+ retval = CLUTTER_TRANSLATE_REMOVE;
+ break;
+ }
+
+ event->crossing.type = event->type = CLUTTER_LEAVE;
+
+ event->crossing.stage = stage;
+ event->crossing.source = CLUTTER_ACTOR (stage);
+ event->crossing.related = NULL;
+
+ event->crossing.time = xev->time;
+ event->crossing.x = xev->event_x;
+ event->crossing.y = xev->event_y;
+
+ _clutter_stage_remove_device (stage, device);
+ }
+
+ clutter_event_set_device (event, device);
+ _clutter_event_set_source_device (event, source_device);
+
+ retval = CLUTTER_TRANSLATE_QUEUE;
+ }
+ break;
+
+ case XI_FocusIn:
+ case XI_FocusOut:
+ retval = CLUTTER_TRANSLATE_CONTINUE;
+ break;
+ }
+
+ XFreeEventData (backend_x11->xdpy, cookie);
+
+ return retval;
+}
+
+static void
+clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface)
+{
+ iface->translate_event = clutter_device_manager_xi2_translate_event;
+}
+
+static void
+clutter_device_manager_xi2_add_device (ClutterDeviceManager *manager,
+ ClutterInputDevice *device)
+{
+ /* XXX implement */
+}
+
+static void
+clutter_device_manager_xi2_remove_device (ClutterDeviceManager *manager,
+ ClutterInputDevice *device)
+{
+ /* XXX implement */
+}
+
+static const GSList *
+clutter_device_manager_xi2_get_devices (ClutterDeviceManager *manager)
+{
+ ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (manager);
+ GSList *all_devices = NULL;
+ GList *l;
+
+ if (manager_xi2->all_devices != NULL)
+ return manager_xi2->all_devices;
+
+ for (l = manager_xi2->master_devices; l != NULL; l = l->next)
+ all_devices = g_slist_prepend (all_devices, l->data);
+
+ for (l = manager_xi2->slave_devices; l != NULL; l = l->next)
+ all_devices = g_slist_prepend (all_devices, l->data);
+
+ manager_xi2->all_devices = g_slist_reverse (all_devices);
+
+ return manager_xi2->all_devices;
+}
+
+static ClutterInputDevice *
+clutter_device_manager_xi2_get_device (ClutterDeviceManager *manager,
+ gint id)
+{
+ ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (manager);
+
+ return g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (id));
+}
+
+static ClutterInputDevice *
+clutter_device_manager_xi2_get_core_device (ClutterDeviceManager *manager,
+ ClutterInputDeviceType device_type)
+{
+ ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (manager);
+ ClutterBackendX11 *backend_x11;
+ ClutterInputDevice *device;
+ int device_id;
+
+ backend_x11 =
+ CLUTTER_BACKEND_X11 (_clutter_device_manager_get_backend (manager));
+
+ XIGetClientPointer (backend_x11->xdpy, None, &device_id);
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (device_id));
+
+ switch (device_type)
+ {
+ case CLUTTER_POINTER_DEVICE:
+ return device;
+
+ case CLUTTER_KEYBOARD_DEVICE:
+ return clutter_input_device_get_associated_device (device);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static void
+relate_masters (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ ClutterDeviceManagerXI2 *manager_xi2 = data;
+ ClutterInputDevice *device, *relative;
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id, key);
+ relative = g_hash_table_lookup (manager_xi2->devices_by_id, value);
+
+ _clutter_input_device_set_associated_device (device, relative);
+ _clutter_input_device_set_associated_device (relative, device);
+}
+
+static void
+relate_slaves (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ ClutterDeviceManagerXI2 *manager_xi2 = data;
+ ClutterInputDevice *master, *slave;
+
+ master = g_hash_table_lookup (manager_xi2->devices_by_id, key);
+ slave = g_hash_table_lookup (manager_xi2->devices_by_id, value);
+
+ _clutter_input_device_set_associated_device (slave, master);
+ _clutter_input_device_add_slave (master, slave);
+}
+
+static void
+clutter_device_manager_xi2_constructed (GObject *gobject)
+{
+ ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (gobject);
+ ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (gobject);
+ ClutterBackendX11 *backend_x11;
+ GHashTable *masters, *slaves;
+ XIDeviceInfo *info;
+ XIEventMask event_mask;
+ unsigned char mask[2] = { 0, };
+ int n_devices, i;
+
+ backend_x11 =
+ CLUTTER_BACKEND_X11 (_clutter_device_manager_get_backend (manager));
+
+ masters = g_hash_table_new (NULL, NULL);
+ slaves = g_hash_table_new (NULL, NULL);
+
+ info = XIQueryDevice (backend_x11->xdpy, XIAllDevices, &n_devices);
+
+ for (i = 0; i < n_devices; i++)
+ {
+ XIDeviceInfo *xi_device = &info[i];
+ ClutterInputDevice *device;
+
+ device = add_device (manager_xi2, backend_x11, xi_device, TRUE);
+
+ if (xi_device->use == XIMasterPointer ||
+ xi_device->use == XIMasterKeyboard)
+ {
+ g_hash_table_insert (masters,
+ GINT_TO_POINTER (xi_device->deviceid),
+ GINT_TO_POINTER (xi_device->attachment));
+ }
+ else if (xi_device->use == XISlavePointer ||
+ xi_device->use == XISlaveKeyboard)
+ {
+ g_hash_table_insert (slaves,
+ GINT_TO_POINTER (xi_device->deviceid),
+ GINT_TO_POINTER (xi_device->attachment));
+ }
+ }
+
+ XIFreeDeviceInfo (info);
+
+ g_hash_table_foreach (masters, relate_masters, manager_xi2);
+ g_hash_table_destroy (masters);
+
+ g_hash_table_foreach (slaves, relate_slaves, manager_xi2);
+ g_hash_table_destroy (slaves);
+
+ XISetMask (mask, XI_HierarchyChanged);
+ XISetMask (mask, XI_DeviceChanged);
+
+ event_mask.deviceid = XIAllDevices;
+ event_mask.mask_len = sizeof (mask);
+ event_mask.mask = mask;
+
+ clutter_device_manager_xi2_select_events (manager,
+ clutter_x11_get_root_window (),
+ &event_mask);
+
+ if (G_OBJECT_CLASS (clutter_device_manager_xi2_parent_class)->constructed)
+ G_OBJECT_CLASS (clutter_device_manager_xi2_parent_class)->constructed (gobject);
+}
+
+static void
+clutter_device_manager_xi2_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_OPCODE:
+ manager_xi2->opcode = g_value_get_int (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+clutter_device_manager_xi2_class_init (ClutterDeviceManagerXI2Class *klass)
+{
+ ClutterDeviceManagerClass *manager_class;
+ GObjectClass *gobject_class;
+
+ obj_props[PROP_OPCODE] =
+ g_param_spec_int ("opcode",
+ "Opcode",
+ "The XI2 opcode",
+ -1, G_MAXINT,
+ -1,
+ CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->constructed = clutter_device_manager_xi2_constructed;
+ gobject_class->set_property = clutter_device_manager_xi2_set_property;
+
+ g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
+
+ manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
+ manager_class->add_device = clutter_device_manager_xi2_add_device;
+ manager_class->remove_device = clutter_device_manager_xi2_remove_device;
+ manager_class->get_devices = clutter_device_manager_xi2_get_devices;
+ manager_class->get_core_device = clutter_device_manager_xi2_get_core_device;
+ manager_class->get_device = clutter_device_manager_xi2_get_device;
+}
+
+static void
+clutter_device_manager_xi2_init (ClutterDeviceManagerXI2 *self)
+{
+ self->devices_by_id = g_hash_table_new_full (NULL, NULL,
+ NULL,
+ (GDestroyNotify) g_object_unref);
+}
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright © 2011 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>
+ */
+
+#ifndef __CLUTTER_DEVICE_MANAGER_XI2_H__
+#define __CLUTTER_DEVICE_MANAGER_XI2_H__
+
+#include <clutter/clutter-device-manager.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_DEVICE_MANAGER_XI2 (_clutter_device_manager_xi2_get_type ())
+#define CLUTTER_DEVICE_MANAGER_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_XI2, ClutterDeviceManagerXI2))
+#define CLUTTER_IS_DEVICE_MANAGER_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_XI2))
+#define CLUTTER_DEVICE_MANAGER_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_XI2, ClutterDeviceManagerXI2Class))
+#define CLUTTER_IS_DEVICE_MANAGER_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_XI2))
+#define CLUTTER_DEVICE_MANAGER_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_XI2, ClutterDeviceManagerXI2Class))
+
+typedef struct _ClutterDeviceManagerXI2 ClutterDeviceManagerXI2;
+typedef struct _ClutterDeviceManagerXI2Class ClutterDeviceManagerXI2Class;
+
+struct _ClutterDeviceManagerXI2
+{
+ ClutterDeviceManager parent_instance;
+
+ GHashTable *devices_by_id;
+
+ GSList *all_devices;
+
+ GList *master_devices;
+ GList *slave_devices;
+
+ ClutterInputDevice *client_pointer;
+
+ int opcode;
+};
+
+struct _ClutterDeviceManagerXI2Class
+{
+ ClutterDeviceManagerClass parent_class;
+};
+
+GType _clutter_device_manager_xi2_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __CLUTTER_DEVICE_MANAGER_XI2_H__ */
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
-#include "clutter-stage-x11.h"
#include "clutter-backend-x11.h"
-#include "clutter-keymap-x11.h"
#include "clutter-x11.h"
-#include "clutter-actor-private.h"
#include "clutter-backend-private.h"
#include "clutter-debug.h"
-#include "clutter-device-manager-private.h"
#include "clutter-event.h"
#include "clutter-main.h"
-#include "clutter-paint-volume-private.h"
#include "clutter-private.h"
-#include "clutter-stage-private.h"
-
-#include "cogl/cogl-internal.h"
#include <string.h>
#include <glib.h>
-#ifdef HAVE_XFIXES
-#include <X11/extensions/Xfixes.h>
-#endif
-
-#include <X11/Xatom.h>
-
-#ifdef HAVE_XINPUT
-#include <X11/extensions/XInput.h>
-#endif
-
-#ifdef HAVE_XKB
-#include <X11/XKBlib.h>
-#endif
-
+#if 0
/* XEMBED protocol support for toolkit embedding */
#define XEMBED_MAPPED (1 << 0)
#define MAX_SUPPORTED_XEMBED_VERSION 1
#define XEMBED_ACTIVATE_ACCELERATOR 14
static Window ParentEmbedderWin = None;
+#endif
typedef struct _ClutterEventSource ClutterEventSource;
GPollFD event_poll_fd;
};
-struct _ClutterEventX11
-{
- /* additional fields for Key events */
- gint key_group;
-
- guint key_is_modifier : 1;
- guint num_lock_set : 1;
- guint caps_lock_set : 1;
-};
-
ClutterEventX11 *
_clutter_event_x11_new (void)
{
GSource *source = g_source_new (&event_funcs, sizeof (ClutterEventSource));
ClutterEventSource *event_source = (ClutterEventSource *) source;
- g_source_set_name (source, "Clutter X11 Event");
event_source->backend = backend;
return source;
return XPending (CLUTTER_BACKEND_X11 (backend)->xdpy);
}
+#if 0
static gboolean
xembed_send_message (ClutterBackendX11 *backend_x11,
Window window,
backend_x11->atom_XEMBED_INFO, 32,
PropModeReplace, (unsigned char *) list, 2);
}
+#endif
void
_clutter_backend_x11_events_init (ClutterBackend *backend)
GSource *source;
ClutterEventSource *event_source;
int connection_number;
+ gchar *name;
connection_number = ConnectionNumber (backend_x11->xdpy);
CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number);
event_source = (ClutterEventSource *) source;
g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
+ name = g_strdup_printf ("Clutter X11 Event (connection: %d)",
+ connection_number);
+ g_source_set_name (source, name);
+ g_free (name);
+
event_source->event_poll_fd.fd = connection_number;
event_source->event_poll_fd.events = G_IO_IN;
}
static void
-update_last_event_time (ClutterBackendX11 *backend_x11,
- XEvent *xevent)
-{
- Time current_time = CurrentTime;
- Time last_time = backend_x11->last_event_time;
-
- switch (xevent->type)
- {
- case KeyPress:
- case KeyRelease:
- current_time = xevent->xkey.time;
- break;
-
- case ButtonPress:
- case ButtonRelease:
- current_time = xevent->xbutton.time;
- break;
-
- case MotionNotify:
- current_time = xevent->xmotion.time;
- break;
-
- case EnterNotify:
- case LeaveNotify:
- current_time = xevent->xcrossing.time;
- break;
-
- case PropertyNotify:
- current_time = xevent->xproperty.time;
- break;
-
- default:
- break;
- }
-
- /* only change the current event time if it's after the previous event
- * time, or if it is at least 30 seconds earlier - in case the system
- * clock was changed
- */
- if ((current_time != CurrentTime) &&
- (current_time > last_time || (last_time - current_time > (30 * 1000))))
- backend_x11->last_event_time = current_time;
-}
-
-static void
-set_user_time (ClutterBackendX11 *backend_x11,
- Window *xwindow,
- long timestamp)
-{
- if (timestamp != CLUTTER_CURRENT_TIME)
- {
- XChangeProperty (backend_x11->xdpy, *xwindow,
- backend_x11->atom_NET_WM_USER_TIME,
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *) ×tamp, 1);
- }
-}
-
-#ifdef HAVE_XINPUT
-static void
-convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev,
- XEvent *xevent)
-{
- xevent->xany.type = xevent->xkey.type = xkev->type;
- xevent->xkey.serial = xkev->serial;
- xevent->xkey.display = xkev->display;
- xevent->xkey.window = xkev->window;
- xevent->xkey.root = xkev->root;
- xevent->xkey.subwindow = xkev->subwindow;
- xevent->xkey.time = xkev->time;
- xevent->xkey.x = xkev->x;
- xevent->xkey.y = xkev->y;
- xevent->xkey.x_root = xkev->x_root;
- xevent->xkey.y_root = xkev->y_root;
- xevent->xkey.state = xkev->state;
- xevent->xkey.keycode = xkev->keycode;
- xevent->xkey.same_screen = xkev->same_screen;
-}
-#endif /* HAVE_XINPUT */
-
-static inline void
-translate_key_event (ClutterBackendX11 *backend_x11,
- ClutterEvent *event,
- XEvent *xevent)
-{
- ClutterEventX11 *event_x11;
- char buffer[256 + 1];
- int n;
-
- /* KeyEvents have platform specific data associated to them */
- event_x11 = _clutter_event_x11_new ();
- _clutter_event_set_platform_data (event, event_x11);
-
- event->key.time = xevent->xkey.time;
- event->key.modifier_state = (ClutterModifierType) xevent->xkey.state;
- event->key.hardware_keycode = xevent->xkey.keycode;
-
- /* keyval is the key ignoring all modifiers ('1' vs. '!') */
- event->key.keyval =
- _clutter_keymap_x11_translate_key_state (backend_x11->keymap,
- event->key.hardware_keycode,
- event->key.modifier_state,
- NULL);
-
- event_x11->key_group =
- _clutter_keymap_x11_get_key_group (backend_x11->keymap,
- event->key.modifier_state);
- event_x11->key_is_modifier =
- _clutter_keymap_x11_get_is_modifier (backend_x11->keymap,
- event->key.hardware_keycode);
- event_x11->num_lock_set =
- _clutter_keymap_x11_get_num_lock_state (backend_x11->keymap);
- event_x11->caps_lock_set =
- _clutter_keymap_x11_get_caps_lock_state (backend_x11->keymap);
-
- /* unicode_value is the printable representation */
- n = XLookupString (&xevent->xkey, buffer, sizeof (buffer) - 1, NULL, NULL);
-
- if (n != NoSymbol)
- {
- event->key.unicode_value = g_utf8_get_char_validated (buffer, n);
- if ((event->key.unicode_value != -1) &&
- (event->key.unicode_value != -2))
- goto out;
- }
- else
- event->key.unicode_value = (gunichar)'\0';
-
-out:
- return;
-}
-
-static gboolean
-handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
- Window window,
- XEvent *xevent)
-{
- Atom atom = (Atom) xevent->xclient.data.l[0];
-
- if (atom == backend_x11->atom_WM_DELETE_WINDOW &&
- xevent->xany.window == window)
- {
- /* the WM_DELETE_WINDOW is a request: we do not destroy
- * the window right away, as it might contain vital data;
- * we relay the event to the application and we let it
- * handle the request
- */
- CLUTTER_NOTE (EVENT, "delete window:\txid: %ld",
- xevent->xclient.window);
-
- set_user_time (backend_x11,
- &window,
- xevent->xclient.data.l[1]);
-
- return TRUE;
- }
- else if (atom == backend_x11->atom_NET_WM_PING &&
- xevent->xany.window == window)
- {
- XClientMessageEvent xclient = xevent->xclient;
-
- xclient.window = backend_x11->xwin_root;
- XSendEvent (backend_x11->xdpy, xclient.window,
- False,
- SubstructureRedirectMask | SubstructureNotifyMask,
- (XEvent *) &xclient);
- return FALSE;
- }
-
- /* do not send any of the WM_PROTOCOLS events to the queue */
- return FALSE;
-}
-
-static gboolean
-handle_xembed_event (ClutterBackendX11 *backend_x11,
- XEvent *xevent)
-{
- ClutterActor *stage;
-
- stage = clutter_stage_get_default ();
-
- switch (xevent->xclient.data.l[1])
- {
- case XEMBED_EMBEDDED_NOTIFY:
- CLUTTER_NOTE (EVENT, "got XEMBED_EMBEDDED_NOTIFY from %lx",
- xevent->xclient.data.l[3]);
-
- ParentEmbedderWin = xevent->xclient.data.l[3];
-
- clutter_actor_realize (stage);
- clutter_actor_show (stage);
-
- xembed_set_info (backend_x11,
- clutter_x11_get_stage_window (CLUTTER_STAGE (stage)),
- XEMBED_MAPPED);
- break;
- case XEMBED_WINDOW_ACTIVATE:
- CLUTTER_NOTE (EVENT, "got XEMBED_WINDOW_ACTIVATE");
- break;
- case XEMBED_WINDOW_DEACTIVATE:
- CLUTTER_NOTE (EVENT, "got XEMBED_WINDOW_DEACTIVATE");
- break;
- case XEMBED_FOCUS_IN:
- CLUTTER_NOTE (EVENT, "got XEMBED_FOCUS_IN");
- if (ParentEmbedderWin)
- xembed_send_message (backend_x11, ParentEmbedderWin,
- XEMBED_FOCUS_NEXT,
- 0, 0, 0);
- break;
- default:
- CLUTTER_NOTE (EVENT, "got unknown XEMBED message");
- break;
- }
-
- /* do not propagate the XEMBED events to the stage */
- return FALSE;
-}
-
-static gboolean
-clipped_redraws_cool_off_cb (void *data)
-{
- ClutterStageX11 *stage_x11 = data;
-
- stage_x11->clipped_redraws_cool_off = 0;
-
- return FALSE;
-}
-
-static gboolean
-event_translate (ClutterBackend *backend,
- ClutterEvent *event,
- XEvent *xevent)
-{
- ClutterBackendX11 *backend_x11;
- ClutterStageX11 *stage_x11;
- ClutterStage *stage;
- ClutterStageWindow *impl;
- ClutterDeviceManager *manager;
- gboolean res, not_yet_handled = FALSE;
- Window xwindow, stage_xwindow;
- ClutterInputDevice *device;
-
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
- xwindow = xevent->xany.window;
-
- if (backend_x11->event_filters)
- {
- GSList *node;
-
- node = backend_x11->event_filters;
-
- while (node)
- {
- ClutterX11EventFilter *filter = node->data;
-
- switch (filter->func (xevent, event, filter->data))
- {
- case CLUTTER_X11_FILTER_CONTINUE:
- break;
- case CLUTTER_X11_FILTER_TRANSLATE:
- return TRUE;
- case CLUTTER_X11_FILTER_REMOVE:
- return FALSE;
- default:
- break;
- }
-
- node = node->next;
- }
- }
-
- /* Pass the event through Cogl */
- if (_cogl_xlib_handle_event (xevent) == COGL_XLIB_FILTER_REMOVE)
- return FALSE;
-
- /* Do further processing only on events for the stage window (the x11
- * filters might be getting events for other windows, so do not mess
- * them about.
- */
- stage = clutter_x11_get_stage_from_window (xwindow);
- if (stage == NULL)
- return FALSE;
-
- impl = _clutter_stage_get_window (stage);
- stage_x11 = CLUTTER_STAGE_X11 (impl);
- stage_xwindow = xwindow; /* clutter_x11_get_stage_window (stage); */
-
- event->any.stage = stage;
-
- res = TRUE;
-
- update_last_event_time (backend_x11, xevent);
-
- manager = clutter_device_manager_get_default ();
-
- switch (xevent->type)
- {
- case ConfigureNotify:
- if (!stage_x11->is_foreign_xwin)
- {
- CLUTTER_NOTE (BACKEND, "%s: ConfigureNotify[%x] (%d, %d)",
- G_STRLOC,
- (unsigned int) stage_x11->xwin,
- xevent->xconfigure.width,
- xevent->xconfigure.height);
-
- /* Queue a relayout - we want glViewport to be called
- * with the correct values, and this is done in ClutterStage
- * via _cogl_onscreen_clutter_backend_set_size ().
- *
- * We queue a relayout, because if this ConfigureNotify is
- * in response to a size we set in the application, the
- * set_size above is essentially a null-op.
- *
- * Make sure we do this only when the size has changed,
- * otherwise we end up relayouting on window moves.
- */
- if ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) ||
- (stage_x11->xwin_width != xevent->xconfigure.width) ||
- (stage_x11->xwin_height != xevent->xconfigure.height))
- {
- clutter_actor_queue_relayout (CLUTTER_ACTOR (stage));
- }
-
- /* If we're fullscreened, we want these variables to
- * represent the size of the window before it was set
- * to fullscreen.
- */
- if (!(stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN))
- {
- stage_x11->xwin_width = xevent->xconfigure.width;
- stage_x11->xwin_height = xevent->xconfigure.height;
- }
-
- clutter_actor_set_size (CLUTTER_ACTOR (stage),
- xevent->xconfigure.width,
- xevent->xconfigure.height);
-
- /* XXX: This is a workaround for a race condition when
- * resizing windows while there are in-flight
- * glXCopySubBuffer blits happening.
- *
- * The problem stems from the fact that rectangles for the
- * blits are described relative to the bottom left of the
- * window and because we can't guarantee control over the X
- * window gravity used when resizing so the gravity is
- * typically NorthWest not SouthWest.
- *
- * This means if you grow a window vertically the server
- * will make sure to place the old contents of the window
- * at the top-left/north-west of your new larger window, but
- * that may happen asynchronous to GLX preparing to do a
- * blit specified relative to the bottom-left/south-west of
- * the window (based on the old smaller window geometry).
- *
- * When the GLX issued blit finally happens relative to the
- * new bottom of your window, the destination will have
- * shifted relative to the top-left where all the pixels you
- * care about are so it will result in a nasty artefact
- * making resizing look very ugly!
- *
- * We can't currently fix this completely, in-part because
- * the window manager tends to trample any gravity we might
- * set. This workaround instead simply disables blits for a
- * while if we are notified of any resizes happening so if
- * the user is resizing a window via the window manager then
- * they may see an artefact for one frame but then we will
- * fallback to redrawing the full stage until the cooling
- * off period is over.
- */
- if (stage_x11->clipped_redraws_cool_off)
- g_source_remove (stage_x11->clipped_redraws_cool_off);
- stage_x11->clipped_redraws_cool_off =
- g_timeout_add_seconds (1, clipped_redraws_cool_off_cb, stage_x11);
-
- CLUTTER_UNSET_PRIVATE_FLAGS (stage_x11->wrapper,
- CLUTTER_IN_RESIZE);
-
- /* the resize process is complete, so we can ask the stage
- * to set up the GL viewport with the new size
- */
- clutter_stage_ensure_viewport (stage);
- }
- res = FALSE;
- break;
-
- case PropertyNotify:
- if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE &&
- xevent->xproperty.window == stage_xwindow &&
- !stage_x11->is_foreign_xwin)
- {
- Atom type;
- gint format;
- gulong n_items, bytes_after;
- guchar *data = NULL;
- gboolean fullscreen_set = FALSE;
-
- clutter_x11_trap_x_errors ();
- XGetWindowProperty (backend_x11->xdpy, stage_xwindow,
- backend_x11->atom_NET_WM_STATE,
- 0, G_MAXLONG,
- False, XA_ATOM,
- &type, &format, &n_items,
- &bytes_after, &data);
- clutter_x11_untrap_x_errors ();
-
- if (type != None && data != NULL)
- {
- Atom *atoms = (Atom *) data;
- gulong i;
- gboolean is_fullscreen = FALSE;
-
- for (i = 0; i < n_items; i++)
- {
- if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN)
- fullscreen_set = TRUE;
- }
-
- is_fullscreen =
- (stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN);
-
- if (fullscreen_set != is_fullscreen)
- {
- if (fullscreen_set)
- stage_x11->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
- else
- stage_x11->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
-
- stage_x11->fullscreening = fullscreen_set;
-
- event->type = CLUTTER_STAGE_STATE;
- event->stage_state.changed_mask =
- CLUTTER_STAGE_STATE_FULLSCREEN;
- event->stage_state.new_state = stage_x11->state;
- }
- else
- res = FALSE;
-
- XFree (data);
- }
- else
- res = FALSE;
- }
- else
- res = FALSE;
- break;
-
- case MapNotify:
- res = FALSE;
- break;
-
- case UnmapNotify:
- res = FALSE;
- break;
-
- case FocusIn:
- if (!(stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED))
- {
- /* TODO: check xevent->xfocus.detail ? */
- stage_x11->state |= CLUTTER_STAGE_STATE_ACTIVATED;
-
- event->type = CLUTTER_STAGE_STATE;
- event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
- event->stage_state.new_state = stage_x11->state;
- }
- else
- res = FALSE;
- break;
-
- case FocusOut:
- if (stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED)
- {
- stage_x11->state &= ~CLUTTER_STAGE_STATE_ACTIVATED;
-
- event->type = CLUTTER_STAGE_STATE;
- event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
- event->stage_state.new_state = stage_x11->state;
- }
- else
- res = FALSE;
- break;
-
- case Expose:
- {
- XExposeEvent *expose = (XExposeEvent *)xevent;
- ClutterPaintVolume clip;
- ClutterVertex origin;
-
- CLUTTER_NOTE (MULTISTAGE, "expose for stage: %p, redrawing", stage);
- CLUTTER_NOTE (MULTISTAGE,
- "expose for stage: %p, "
- "redrawing (x=%d, y=%d, width=%d, height=%d)",
- stage,
- expose->x,
- expose->y,
- expose->width,
- expose->height);
-
- origin.x = expose->x;
- origin.y = expose->y;
- origin.z = 0;
-
- _clutter_paint_volume_init_static (CLUTTER_ACTOR (stage), &clip);
-
- clutter_paint_volume_set_origin (&clip, &origin);
- clutter_paint_volume_set_width (&clip, expose->width);
- clutter_paint_volume_set_height (&clip, expose->height);
-
- _clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), 0, &clip);
-
- clutter_paint_volume_free (&clip);
-
- res = FALSE;
- }
- break;
- case DestroyNotify:
- CLUTTER_NOTE (EVENT, "destroy notify:\txid: %ld",
- xevent->xdestroywindow.window);
- if (xevent->xdestroywindow.window == stage_xwindow &&
- !stage_x11->is_foreign_xwin)
- event->type = event->any.type = CLUTTER_DESTROY_NOTIFY;
- else
- res = FALSE;
- break;
-
- case ClientMessage:
- CLUTTER_NOTE (EVENT, "client message");
-
- event->type = event->any.type = CLUTTER_CLIENT_MESSAGE;
-
- if (xevent->xclient.message_type == backend_x11->atom_XEMBED)
- res = handle_xembed_event (backend_x11, xevent);
- else if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
- {
- res = handle_wm_protocols_event (backend_x11, stage_xwindow, xevent);
- event->type = event->any.type = CLUTTER_DELETE;
- }
- break;
-
- case KeyPress:
- event->key.type = event->type = CLUTTER_KEY_PRESS;
- event->key.device =
- clutter_device_manager_get_core_device (manager,
- CLUTTER_KEYBOARD_DEVICE);
-
- translate_key_event (backend_x11, event, xevent);
-
- set_user_time (backend_x11, &xwindow, xevent->xkey.time);
- break;
-
- case KeyRelease:
- /* old-style X11 terminals require that even modern X11 send
- * KeyPress/KeyRelease pairs when auto-repeating. for this
- * reason modern(-ish) API like XKB has a way to detect
- * auto-repeat and do a single KeyRelease at the end of a
- * KeyPress sequence.
- *
- * this check emulates XKB's detectable auto-repeat; we peek
- * the next event and check if it's a KeyPress for the same key
- * and timestamp - and then ignore it if it matches the
- * KeyRelease
- *
- * if we have XKB, and autorepeat is enabled, then this becomes
- * a no-op
- */
- if (!backend_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
- {
- XEvent next_event;
-
- XPeekEvent (xevent->xkey.display, &next_event);
-
- if (next_event.type == KeyPress &&
- next_event.xkey.keycode == xevent->xkey.keycode &&
- next_event.xkey.time == xevent->xkey.time)
- {
- res = FALSE;
- break;
- }
- }
-
- event->key.type = event->type = CLUTTER_KEY_RELEASE;
- event->key.device =
- clutter_device_manager_get_core_device (manager,
- CLUTTER_KEYBOARD_DEVICE);
-
- translate_key_event (backend_x11, event, xevent);
- break;
-
- default:
- /* ignore every other event */
- not_yet_handled = TRUE;
- break;
- }
-
- /* Input device event handling.. */
- if (not_yet_handled)
- {
- device = clutter_device_manager_get_core_device (manager,
- CLUTTER_POINTER_DEVICE);
-
- /* Regular X event */
- switch (xevent->type)
- {
- case ButtonPress:
- switch (xevent->xbutton.button)
- {
- case 4: /* up */
- case 5: /* down */
- case 6: /* left */
- case 7: /* right */
- event->scroll.type = event->type = CLUTTER_SCROLL;
-
- if (xevent->xbutton.button == 4)
- event->scroll.direction = CLUTTER_SCROLL_UP;
- else if (xevent->xbutton.button == 5)
- event->scroll.direction = CLUTTER_SCROLL_DOWN;
- else if (xevent->xbutton.button == 6)
- event->scroll.direction = CLUTTER_SCROLL_LEFT;
- else
- event->scroll.direction = CLUTTER_SCROLL_RIGHT;
-
- event->scroll.time = xevent->xbutton.time;
- event->scroll.x = xevent->xbutton.x;
- event->scroll.y = xevent->xbutton.y;
- event->scroll.modifier_state = xevent->xbutton.state;
- event->scroll.device = device;
- break;
-
- default:
- event->button.type = event->type = CLUTTER_BUTTON_PRESS;
- event->button.time = xevent->xbutton.time;
- event->button.x = xevent->xbutton.x;
- event->button.y = xevent->xbutton.y;
- event->button.modifier_state = xevent->xbutton.state;
- event->button.button = xevent->xbutton.button;
- event->button.device = device;
- break;
- }
-
- set_user_time (backend_x11, &xwindow, event->button.time);
-
- res = TRUE;
- break;
-
- case ButtonRelease:
- /* scroll events don't have a corresponding release */
- if (xevent->xbutton.button == 4 ||
- xevent->xbutton.button == 5 ||
- xevent->xbutton.button == 6 ||
- xevent->xbutton.button == 7)
- {
- res = FALSE;
- goto out;
- }
-
- event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
- event->button.time = xevent->xbutton.time;
- event->button.x = xevent->xbutton.x;
- event->button.y = xevent->xbutton.y;
- event->button.modifier_state = xevent->xbutton.state;
- event->button.button = xevent->xbutton.button;
- event->button.device = device;
-
- res = TRUE;
- break;
-
- case MotionNotify:
- event->motion.type = event->type = CLUTTER_MOTION;
- event->motion.time = xevent->xmotion.time;
- event->motion.x = xevent->xmotion.x;
- event->motion.y = xevent->xmotion.y;
- event->motion.modifier_state = xevent->xmotion.state;
- event->motion.device = device;
-
- res = TRUE;
- break;
-
- case EnterNotify:
- /* we know that we are entering the stage here */
- _clutter_input_device_set_stage (device, stage);
- CLUTTER_NOTE (EVENT, "Entering the stage");
-
- /* Convert enter notifies to motion events because X
- doesn't emit the corresponding motion notify */
- event->motion.type = event->type = CLUTTER_MOTION;
- event->motion.time = xevent->xcrossing.time;
- event->motion.x = xevent->xcrossing.x;
- event->motion.y = xevent->xcrossing.y;
- event->motion.modifier_state = xevent->xcrossing.state;
- event->motion.source = CLUTTER_ACTOR (stage);
- event->motion.device = device;
-
- res = TRUE;
- break;
-
- case LeaveNotify:
- if (device->stage == NULL)
- {
- CLUTTER_NOTE (EVENT,
- "Discarding LeaveNotify for ButtonRelease "
- "event off-stage");
- res = FALSE;
- goto out;
- }
-
- /* we know that we are leaving the stage here */
- _clutter_input_device_set_stage (device, NULL);
- CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)",
- event->crossing.time);
-
- event->crossing.type = event->type = CLUTTER_LEAVE;
- event->crossing.time = xevent->xcrossing.time;
- event->crossing.x = xevent->xcrossing.x;
- event->crossing.y = xevent->xcrossing.y;
- event->crossing.source = CLUTTER_ACTOR (stage);
- event->crossing.device = device;
- res = TRUE;
- break;
-
- default:
- res = FALSE;
- break;
- }
- }
-
- /* XInput fun...*/
- if (!res && clutter_x11_has_xinput ())
- {
-#ifdef HAVE_XINPUT
- int *ev_types = backend_x11->event_types;
- int button_press, button_release;
- int key_press, key_release;
- int motion_notify;
-
- button_press = ev_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
- button_release = ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
- motion_notify = ev_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT];
- key_press = ev_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT];
- key_release = ev_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT];
-
- CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type);
-
- if (xevent->type == button_press)
- {
- XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent;
-
- device = _clutter_x11_get_device_for_xid (xbev->deviceid);
- _clutter_input_device_set_stage (device, stage);
-
- CLUTTER_NOTE (EVENT,
- "XI ButtonPress for %li ('%s') at %d, %d",
- xbev->deviceid,
- device->device_name,
- xbev->x,
- xbev->y);
-
- switch (xbev->button)
- {
- case 4:
- case 5:
- case 6:
- case 7:
- event->scroll.type = event->type = CLUTTER_SCROLL;
-
- if (xbev->button == 4)
- event->scroll.direction = CLUTTER_SCROLL_UP;
- else if (xbev->button == 5)
- event->scroll.direction = CLUTTER_SCROLL_DOWN;
- else if (xbev->button == 6)
- event->scroll.direction = CLUTTER_SCROLL_LEFT;
- else
- event->scroll.direction = CLUTTER_SCROLL_RIGHT;
-
- event->scroll.time = xbev->time;
- event->scroll.x = xbev->x;
- event->scroll.y = xbev->y;
- event->scroll.modifier_state = xbev->state;
- event->scroll.device = device;
- break;
-
- default:
- event->button.type = event->type = CLUTTER_BUTTON_PRESS;
- event->button.time = xbev->time;
- event->button.x = xbev->x;
- event->button.y = xbev->y;
- event->button.modifier_state = xbev->state;
- event->button.button = xbev->button;
- event->button.device = device;
- break;
- }
-
- set_user_time (backend_x11, &xwindow, xbev->time);
-
- res = TRUE;
- }
- else if (xevent->type == button_release)
- {
- XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
-
- device = _clutter_x11_get_device_for_xid (xbev->deviceid);
- _clutter_input_device_set_stage (device, stage);
-
- CLUTTER_NOTE (EVENT, "XI ButtonRelease for %li ('%s') at %d, %d",
- xbev->deviceid,
- device->device_name,
- xbev->x,
- xbev->y);
-
- /* scroll events don't have a corresponding release */
- if (xbev->button == 4 ||
- xbev->button == 5 ||
- xbev->button == 6 ||
- xbev->button == 7)
- {
- res = FALSE;
- goto out;
- }
-
- event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
- event->button.time = xbev->time;
- event->button.x = xbev->x;
- event->button.y = xbev->y;
- event->button.modifier_state = xbev->state;
- event->button.button = xbev->button;
- event->button.device = device;
-
- res = TRUE;
- }
- else if (xevent->type == motion_notify)
- {
- XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
-
- device = _clutter_x11_get_device_for_xid (xmev->deviceid);
- _clutter_input_device_set_stage (device, stage);
-
- CLUTTER_NOTE (EVENT, "XI Motion for %li ('%s') at %d, %d",
- xmev->deviceid,
- device->device_name,
- xmev->x,
- xmev->y);
-
- event->motion.type = event->type = CLUTTER_MOTION;
- event->motion.time = xmev->time;
- event->motion.x = xmev->x;
- event->motion.y = xmev->y;
- event->motion.modifier_state = xmev->state;
- event->motion.device = device;
-
- res = TRUE;
- }
- 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;
-
- convert_xdevicekey_to_xkey (xkev, &xevent_converted);
-
- event->key.type = event->type = (xevent->type == key_press)
- ? CLUTTER_KEY_PRESS
- : CLUTTER_KEY_RELEASE;
-
- translate_key_event (backend_x11, event, &xevent_converted);
-
- if (xevent->type == key_press)
- set_user_time (backend_x11, &xwindow, xkev->time);
- }
- else
-#endif /* HAVE_XINPUT */
- {
- CLUTTER_NOTE (EVENT, "Uknown Event");
- res = FALSE;
- }
- }
-
-out:
- return res;
-}
-
-static void
events_queue (ClutterBackend *backend)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
- ClutterBackendX11Class *backend_x11_class =
- CLUTTER_BACKEND_X11_GET_CLASS (backend_x11);
- ClutterEvent *event;
- Display *xdisplay = backend_x11->xdpy;
- XEvent xevent;
- ClutterMainContext *clutter_context;
-
- clutter_context = _clutter_context_get_default ();
+ Display *xdisplay = backend_x11->xdpy;
+ ClutterEvent *event;
+ XEvent xevent;
while (!clutter_events_pending () && XPending (xdisplay))
{
XNextEvent (xdisplay, &xevent);
- if (backend_x11_class->handle_event (backend_x11, &xevent))
- continue;
-
event = clutter_event_new (CLUTTER_NOTHING);
- if (event_translate (backend, event, &xevent))
- {
- /* push directly here to avoid copy of queue_put */
- g_queue_push_head (clutter_context->events_queue, event);
- }
+ if (_clutter_backend_translate_event (backend, &xevent, event))
+ _clutter_event_push (event, FALSE);
else
clutter_event_free (event);
}
ClutterX11FilterReturn
clutter_x11_handle_event (XEvent *xevent)
{
- ClutterBackend *backend;
- ClutterBackendX11Class *backend_x11_class;
- ClutterEvent *event;
- ClutterMainContext *clutter_context;
ClutterX11FilterReturn result;
- gint spin = 1;
+ ClutterBackend *backend;
+ ClutterEvent *event;
+ gint spin = 1;
/* The return values here are someone approximate; we return
* CLUTTER_X11_FILTER_REMOVE if a clutter event is
clutter_threads_enter ();
- clutter_context = _clutter_context_get_default ();
- backend = clutter_context->backend;
- backend_x11_class = CLUTTER_BACKEND_X11_GET_CLASS (backend);
-
- /* If the backend just observed the event and didn't want it
- * removed it could return FALSE, so assume that a TRUE return
- * means that our caller should also do no further processing. */
- if (backend_x11_class->handle_event (CLUTTER_BACKEND_X11(backend), xevent))
- return CLUTTER_X11_FILTER_REMOVE;
+ backend = clutter_get_default_backend ();
event = clutter_event_new (CLUTTER_NOTHING);
- if (event_translate (backend, event, xevent))
+ if (_clutter_backend_translate_event (backend, xevent, event))
{
- /* push directly here to avoid copy of queue_put */
+ _clutter_event_push (event, FALSE);
+
result = CLUTTER_X11_FILTER_REMOVE;
- g_queue_push_head (clutter_context->events_queue, event);
}
else
{
--spin;
}
- out:
+out:
clutter_threads_leave ();
return result;
/* Pop an event off the queue if any */
event = clutter_event_get ();
-
- if (event)
+ if (event != NULL)
{
/* forward the event into clutter for emission etc. */
clutter_do_event (event);
}
/**
- * clutter_x11_get_current_event_time:
+ * clutter_x11_get_current_event_time: (skip)
*
* Retrieves the timestamp of the last X11 event processed by
* Clutter. This might be different from the timestamp returned
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright © 2010, 2011 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>
+ */
+
+#include "config.h"
+
+#include "clutter-input-device-core-x11.h"
+
+#include "clutter-debug.h"
+#include "clutter-device-manager-private.h"
+#include "clutter-private.h"
+#include "clutter-stage-private.h"
+
+#include "clutter-backend-x11.h"
+#include "clutter-stage-x11.h"
+
+#ifdef HAVE_XINPUT
+#include <X11/extensions/XInput.h>
+#endif
+
+#define MAX_DEVICE_CLASSES 13
+
+typedef struct _ClutterInputDeviceClass ClutterInputDeviceX11Class;
+
+/* a specific X11 input device */
+struct _ClutterInputDeviceX11
+{
+ ClutterInputDevice device;
+
+#ifdef HAVE_XINPUT
+ XDevice *xdevice;
+
+ XEventClass event_classes[MAX_DEVICE_CLASSES];
+ int num_classes;
+
+ int button_press_type;
+ int button_release_type;
+ int motion_notify_type;
+ int state_notify_type;
+ int key_press_type;
+ int key_release_type;
+#endif /* HAVE_XINPUT */
+
+ gint *axis_data;
+
+ gint min_keycode;
+ gint max_keycode;
+};
+
+#define clutter_input_device_x11_get_type _clutter_input_device_x11_get_type
+
+G_DEFINE_TYPE (ClutterInputDeviceX11,
+ clutter_input_device_x11,
+ CLUTTER_TYPE_INPUT_DEVICE);
+
+static void
+clutter_input_device_x11_select_stage_events (ClutterInputDevice *device,
+ ClutterStage *stage,
+ gint event_mask)
+{
+#if HAVE_XINPUT
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
+ ClutterInputDeviceX11 *device_x11;
+ ClutterStageX11 *stage_x11;
+ XEventClass class;
+ gint i;
+
+ device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
+
+ stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
+
+ i = 0;
+
+ if (event_mask & ButtonPressMask)
+ {
+ DeviceButtonPress (device_x11->xdevice,
+ device_x11->button_press_type,
+ class);
+ if (class != 0)
+ device_x11->event_classes[i++] = class;
+
+ DeviceButtonPressGrab (device_x11->xdevice, 0, class);
+ if (class != 0)
+ device_x11->event_classes[i++] = class;
+ }
+
+ if (event_mask & ButtonReleaseMask)
+ {
+ DeviceButtonRelease (device_x11->xdevice,
+ device_x11->button_release_type,
+ class);
+ if (class != 0)
+ device_x11->event_classes[i++] = class;
+ }
+
+ if (event_mask & PointerMotionMask)
+ {
+ DeviceMotionNotify (device_x11->xdevice,
+ device_x11->motion_notify_type,
+ class);
+ if (class != 0)
+ device_x11->event_classes[i++] = class;
+
+ DeviceStateNotify (device_x11->xdevice,
+ device_x11->state_notify_type,
+ class);
+ if (class != 0)
+ device_x11->event_classes[i++] = class;
+ }
+
+ if (event_mask & KeyPressMask)
+ {
+ DeviceKeyPress (device_x11->xdevice,
+ device_x11->key_press_type,
+ class);
+ if (class != 0)
+ device_x11->event_classes[i++] = class;
+ }
+
+ if (event_mask & KeyReleaseMask)
+ {
+ DeviceKeyRelease (device_x11->xdevice,
+ device_x11->key_release_type,
+ class);
+ if (class != 0)
+ device_x11->event_classes[i++] = class;
+ }
+
+ device_x11->num_classes = i;
+
+ XSelectExtensionEvent (backend_x11->xdpy,
+ stage_x11->xwin,
+ device_x11->event_classes,
+ device_x11->num_classes);
+#endif /* HAVE_XINPUT */
+}
+
+static void
+clutter_input_device_x11_dispose (GObject *gobject)
+{
+ ClutterInputDeviceX11 *device_x11 = CLUTTER_INPUT_DEVICE_X11 (gobject);
+
+#ifdef HAVE_XINPUT
+ if (device_x11->xdevice)
+ {
+ ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (gobject);
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
+
+ XCloseDevice (backend_x11->xdpy, device_x11->xdevice);
+ device_x11->xdevice = NULL;
+ }
+#endif /* HAVE_XINPUT */
+
+ g_free (device_x11->axis_data);
+
+ G_OBJECT_CLASS (clutter_input_device_x11_parent_class)->dispose (gobject);
+}
+
+static void
+clutter_input_device_x11_constructed (GObject *gobject)
+{
+#ifdef HAVE_XINPUT
+ ClutterInputDeviceX11 *device_x11 = CLUTTER_INPUT_DEVICE_X11 (gobject);
+ ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (gobject);
+ ClutterBackendX11 *backend_x11;
+
+ backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
+
+ clutter_x11_trap_x_errors ();
+
+ device_x11->xdevice = XOpenDevice (backend_x11->xdpy, device->id);
+
+ if (clutter_x11_untrap_x_errors ())
+ {
+ g_warning ("Device '%s' cannot be opened",
+ clutter_input_device_get_device_name (device));
+ }
+#endif /* HAVE_XINPUT */
+
+ if (G_OBJECT_CLASS (clutter_input_device_x11_parent_class)->constructed)
+ G_OBJECT_CLASS (clutter_input_device_x11_parent_class)->constructed (gobject);
+}
+
+static void
+clutter_input_device_x11_class_init (ClutterInputDeviceX11Class *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass);
+
+ gobject_class->constructed = clutter_input_device_x11_constructed;
+ gobject_class->dispose = clutter_input_device_x11_dispose;
+
+ device_class->select_stage_events = clutter_input_device_x11_select_stage_events;
+}
+
+static void
+clutter_input_device_x11_init (ClutterInputDeviceX11 *self)
+{
+}
+
+#ifdef HAVE_XINPUT
+static void
+update_axes (ClutterInputDeviceX11 *device_x11,
+ guint n_axes,
+ gint first_axis,
+ gint *axes_data)
+{
+ ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_x11);
+ gint i;
+
+ if (device_x11->axis_data == NULL)
+ {
+ device_x11->axis_data =
+ g_new0 (gint, clutter_input_device_get_n_axes (device));
+ }
+
+ for (i = 0; i < n_axes; i++)
+ device_x11->axis_data[first_axis + i] = axes_data[i];
+}
+
+static gdouble *
+translate_axes (ClutterInputDeviceX11 *device_x11,
+ ClutterStageX11 *stage_x11,
+ gfloat *event_x,
+ gfloat *event_y)
+{
+ ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_x11);
+ gint root_x, root_y;
+ gint n_axes, i;
+ gdouble x, y;
+ gdouble *retval;
+
+ if (!_clutter_stage_x11_get_root_coords (stage_x11, &root_x, &root_y))
+ return NULL;
+
+ x = y = 0.0f;
+ n_axes = clutter_input_device_get_n_axes (device);
+
+ retval = g_new0 (gdouble, n_axes);
+
+ for (i = 0; i < n_axes; i++)
+ {
+ ClutterInputAxis axis;
+
+ axis = clutter_input_device_get_axis (device, i);
+ switch (axis)
+ {
+ case CLUTTER_INPUT_AXIS_X:
+ case CLUTTER_INPUT_AXIS_Y:
+ _clutter_x11_input_device_translate_screen_coord (device,
+ root_x, root_y,
+ i,
+ device_x11->axis_data[i],
+ &retval[i]);
+ if (axis == CLUTTER_INPUT_AXIS_X)
+ x = retval[i];
+ else if (axis == CLUTTER_INPUT_AXIS_Y)
+ y = retval[i];
+ break;
+
+ default:
+ _clutter_input_device_translate_axis (device, i,
+ device_x11->axis_data[i],
+ &retval[i]);
+ break;
+ }
+ }
+
+ if (event_x)
+ *event_x = x;
+
+ if (event_y)
+ *event_y = y;
+
+ return retval;
+}
+
+/*
+ * translate_state:
+ * @state: the keyboard state of the core device
+ * @device_state: the button state of the device
+ *
+ * Trivially translates the state and the device state into a
+ * single bitmask.
+ */
+static guint
+translate_state (guint state,
+ guint device_state)
+{
+ return device_state | (state & 0xff);
+}
+#endif /* HAVE_XINPUT */
+
+gboolean
+_clutter_input_device_x11_translate_xi_event (ClutterInputDeviceX11 *device_x11,
+ ClutterStageX11 *stage_x11,
+ XEvent *xevent,
+ ClutterEvent *event)
+{
+#ifdef HAVE_XINPUT
+ ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_x11);
+
+ if ((xevent->type == device_x11->button_press_type) ||
+ (xevent->type == device_x11->button_release_type))
+ {
+ XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *) xevent;
+
+ event->button.type = event->type =
+ (xdbe->type == device_x11->button_press_type) ? CLUTTER_BUTTON_PRESS
+ : CLUTTER_BUTTON_RELEASE;
+ event->button.device = device;
+ event->button.time = xdbe->time;
+ event->button.button = xdbe->button;
+ event->button.modifier_state =
+ translate_state (xdbe->state, xdbe->device_state);
+
+ update_axes (device_x11,
+ xdbe->axes_count,
+ xdbe->first_axis,
+ xdbe->axis_data);
+
+ event->button.axes = translate_axes (device_x11, stage_x11,
+ &event->button.x,
+ &event->button.y);
+
+ _clutter_stage_x11_set_user_time (stage_x11, event->button.time);
+
+ return TRUE;
+ }
+
+ if ((xevent->type == device_x11->key_press_type) ||
+ (xevent->type == device_x11->key_release_type))
+ {
+ XDeviceKeyEvent *xdke = (XDeviceKeyEvent *) xevent;
+
+ if (xdke->keycode < device_x11->min_keycode ||
+ xdke->keycode >= device_x11->max_keycode)
+ {
+ g_warning ("Invalid device key code received: %d", xdke->keycode);
+ return FALSE;
+ }
+
+ clutter_input_device_get_key (device,
+ xdke->keycode - device_x11->min_keycode,
+ &event->key.keyval,
+ &event->key.modifier_state);
+ if (event->key.keyval == 0)
+ return FALSE;
+
+ event->key.type = event->type =
+ (xdke->type == device_x11->key_press_type) ? CLUTTER_KEY_PRESS
+ : CLUTTER_KEY_RELEASE;
+ event->key.time = xdke->time;
+ event->key.modifier_state |=
+ translate_state (xdke->state, xdke->device_state);
+ event->key.device = device;
+
+#if 0
+ if ((event->key.keyval >= 0x20) && (event->key.keyval <= 0xff))
+ {
+ event->key.unicode = (gunichar) event->key.keyval;
+ }
+#endif
+
+ _clutter_stage_x11_set_user_time (stage_x11, event->key.time);
+
+ return TRUE;
+ }
+
+ if (xevent->type == device_x11->motion_notify_type)
+ {
+ XDeviceMotionEvent *xdme = (XDeviceMotionEvent *) xevent;
+
+ event->motion.type = event->type = CLUTTER_MOTION;
+ event->motion.time = xdme->time;
+ event->motion.modifier_state =
+ translate_state (xdme->state, xdme->device_state);
+ event->motion.device = device;
+
+ event->motion.axes =
+ g_new0 (gdouble, clutter_input_device_get_n_axes (device));
+
+ update_axes (device_x11,
+ xdme->axes_count,
+ xdme->first_axis,
+ xdme->axis_data);
+
+ event->motion.axes = translate_axes (device_x11, stage_x11,
+ &event->motion.x,
+ &event->motion.y);
+
+ return TRUE;
+ }
+
+ if (xevent->type == device_x11->state_notify_type)
+ {
+ XDeviceStateNotifyEvent *xdse = (XDeviceStateNotifyEvent *) xevent;
+ XInputClass *input_class = (XInputClass *) xdse->data;
+ gint n_axes = clutter_input_device_get_n_axes (device);
+ int i;
+
+ for (i = 0; i < xdse->num_classes; i++)
+ {
+ if (input_class->class == ValuatorClass)
+ {
+ int *axis_data = ((XValuatorState *) input_class)->valuators;
+
+ update_axes (device_x11, n_axes, 0, axis_data);
+ }
+
+ input_class =
+ (XInputClass *)(((char *) input_class) + input_class->length);
+ }
+ }
+#endif /* HAVE_XINPUT */
+
+ return FALSE;
+}
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright © 2010, 2011 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>
+ */
+
+#ifndef __CLUTTER_INPUT_DEVICE_X11_H__
+#define __CLUTTER_INPUT_DEVICE_X11_H__
+
+#include <clutter/clutter-input-device.h>
+#include <X11/Xlib.h>
+
+#include "clutter-stage-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;
+
+gboolean _clutter_input_device_x11_translate_xi_event (ClutterInputDeviceX11 *device_x11,
+ ClutterStageX11 *stage_x11,
+ XEvent *xevent,
+ ClutterEvent *event);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_INPUT_DEVICE_X11_H__ */
+++ /dev/null
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "clutter-input-device-x11.h"
-
-#include "clutter-debug.h"
-#include "clutter-device-manager-private.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,
-
- PROP_LAST
-};
-
-static GParamSpec *obj_props[PROP_LAST];
-
-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);
- obj_props[PROP_IS_CORE] = pspec;
- 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 */
-}
+++ /dev/null
-#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__ */
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright © 2011 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>
+ */
+
+#include "config.h"
+
+#include "clutter-input-device-xi2.h"
+
+#include "clutter-debug.h"
+#include "clutter-device-manager-private.h"
+#include "clutter-private.h"
+#include "clutter-stage-private.h"
+
+#include "clutter-backend-x11.h"
+#include "clutter-stage-x11.h"
+
+#include <X11/extensions/XInput2.h>
+
+typedef struct _ClutterInputDeviceClass ClutterInputDeviceXI2Class;
+
+/* a specific XI2 input device */
+struct _ClutterInputDeviceXI2
+{
+ ClutterInputDevice device;
+
+ gint device_id;
+};
+
+#define N_BUTTONS 5
+
+#define clutter_input_device_xi2_get_type _clutter_input_device_xi2_get_type
+
+G_DEFINE_TYPE (ClutterInputDeviceXI2,
+ clutter_input_device_xi2,
+ CLUTTER_TYPE_INPUT_DEVICE);
+
+static void
+clutter_input_device_xi2_select_stage_events (ClutterInputDevice *device,
+ ClutterStage *stage,
+ gint event_mask)
+{
+ ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device);
+ ClutterBackendX11 *backend_x11;
+ ClutterStageX11 *stage_x11;
+ XIEventMask xi_event_mask;
+ unsigned char *mask;
+ int len;
+
+ backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
+ stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
+
+ len = XIMaskLen (XI_LASTEVENT);
+ mask = g_new0 (unsigned char, len);
+
+ if (event_mask & PointerMotionMask)
+ XISetMask (mask, XI_Motion);
+
+ if (event_mask & ButtonPressMask)
+ XISetMask (mask, XI_ButtonPress);
+
+ if (event_mask & ButtonReleaseMask)
+ XISetMask (mask, XI_ButtonRelease);
+
+ if (event_mask & KeyPressMask)
+ XISetMask (mask, XI_KeyPress);
+
+ if (event_mask & KeyReleaseMask)
+ XISetMask (mask, XI_KeyRelease);
+
+ if (event_mask & EnterWindowMask)
+ XISetMask (mask, XI_Enter);
+
+ if (event_mask & LeaveWindowMask)
+ XISetMask (mask, XI_Leave);
+
+ xi_event_mask.deviceid = device_xi2->device_id;
+ xi_event_mask.mask = mask;
+ xi_event_mask.mask_len = len;
+
+ CLUTTER_NOTE (BACKEND, "Selecting device id '%d' events",
+ device_xi2->device_id);
+
+ XISelectEvents (backend_x11->xdpy, stage_x11->xwin, &xi_event_mask, 1);
+
+ g_free (mask);
+}
+
+static void
+clutter_input_device_xi2_constructed (GObject *gobject)
+{
+ ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (gobject);
+
+ g_object_get (gobject, "id", &device_xi2->device_id, NULL);
+
+ if (G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed)
+ G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed (gobject);
+}
+
+static void
+clutter_input_device_xi2_class_init (ClutterInputDeviceXI2Class *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass);
+
+ gobject_class->constructed = clutter_input_device_xi2_constructed;
+
+ device_class->select_stage_events = clutter_input_device_xi2_select_stage_events;
+}
+
+static void
+clutter_input_device_xi2_init (ClutterInputDeviceXI2 *self)
+{
+}
+
+guint
+_clutter_input_device_xi2_translate_state (XIModifierState *modifiers_state,
+ XIButtonState *buttons_state)
+{
+ guint retval = 0;
+
+ if (modifiers_state)
+ retval = (guint) modifiers_state->effective;
+
+ if (buttons_state)
+ {
+ int len, i;
+
+ len = MIN (N_BUTTONS, buttons_state->mask_len * 8);
+
+ for (i = 0; i < len; i++)
+ {
+ if (!XIMaskIsSet (buttons_state->mask, i))
+ continue;
+
+ switch (i)
+ {
+ case 1:
+ retval |= CLUTTER_BUTTON1_MASK;
+ break;
+
+ case 2:
+ retval |= CLUTTER_BUTTON2_MASK;
+ break;
+
+ case 3:
+ retval |= CLUTTER_BUTTON3_MASK;
+ break;
+
+ case 4:
+ retval |= CLUTTER_BUTTON4_MASK;
+ break;
+
+ case 5:
+ retval |= CLUTTER_BUTTON5_MASK;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ return retval;
+}
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright © 2011 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>
+ */
+
+#ifndef __CLUTTER_INPUT_DEVICE_XI2_H__
+#define __CLUTTER_INPUT_DEVICE_XI2_H__
+
+#include <clutter/clutter-input-device.h>
+#include <X11/extensions/XInput2.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_INPUT_DEVICE_XI2 (_clutter_input_device_xi2_get_type ())
+#define CLUTTER_INPUT_DEVICE_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_XI2, ClutterInputDeviceXI2))
+#define CLUTTER_IS_INPUT_DEVICE_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_XI2))
+
+typedef struct _ClutterInputDeviceXI2 ClutterInputDeviceXI2;
+
+GType _clutter_input_device_xi2_get_type (void) G_GNUC_CONST;
+
+guint _clutter_input_device_xi2_translate_state (XIModifierState *modifiers_state,
+ XIButtonState *buttons_state);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_INPUT_DEVICE_XI2_H__ */
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include "clutter-keymap-x11.h"
#include "clutter-backend-x11.h"
#include "clutter-debug.h"
+#include "clutter-event-translator.h"
#include "clutter-private.h"
#include <X11/Xatom.h>
-#ifdef HAVE_XINPUT
-#include <X11/extensions/XInput.h>
-#endif
-
#ifdef HAVE_XKB
#include <X11/XKBlib.h>
#endif
#ifdef HAVE_XKB
XkbDescPtr xkb_desc;
+ int xkb_event_base;
+ guint xkb_map_serial;
#endif
guint caps_lock_state : 1;
PROP_LAST
};
-static GParamSpec *obj_props[PROP_LAST];
+static GParamSpec *obj_props[PROP_LAST] = { NULL, };
+
+static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
+
+#define clutter_keymap_x11_get_type _clutter_keymap_x11_get_type
-G_DEFINE_TYPE (ClutterKeymapX11, clutter_keymap_x11, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_CODE (ClutterKeymapX11, clutter_keymap_x11, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
+ clutter_event_translator_iface_init));
#ifdef HAVE_XKB
update_modmap (backend_x11->xdpy, keymap_x11);
}
+ else if (keymap_x11->xkb_map_serial != backend_x11->keymap_serial)
+ {
+ int flags = XkbKeySymsMask
+ | XkbKeyTypesMask
+ | XkbModifierMapMask
+ | XkbVirtualModsMask;
+
+ CLUTTER_NOTE (BACKEND, "Updating XKB keymap");
+
+ XkbGetUpdatedMap (backend_x11->xdpy, flags, keymap_x11->xkb_desc);
+
+ flags = XkbGroupNamesMask | XkbVirtualModNamesMask;
+ XkbGetNames (backend_x11->xdpy, flags, keymap_x11->xkb_desc);
+
+ update_modmap (backend_x11->xdpy, keymap_x11);
+
+ keymap_x11->xkb_map_serial = backend_x11->keymap_serial;
+ }
if (keymap_x11->num_lock_mask == 0)
keymap_x11->num_lock_mask = XkbKeysymToModifiers (backend_x11->xdpy,
g_signal_emit_by_name (keymap_x11->backend, "key-lock-changed");
#endif
}
-
-static ClutterX11FilterReturn
-xkb_filter (XEvent *xevent,
- ClutterEvent *event,
- gpointer data)
-{
- ClutterBackendX11 *backend_x11 = data;
- ClutterKeymapX11 *keymap_x11 = backend_x11->keymap;
-
- g_assert (keymap_x11 != NULL);
-
- if (!backend_x11->use_xkb)
- return CLUTTER_X11_FILTER_CONTINUE;
-
- if (xevent->type == backend_x11->xkb_event_base)
- {
- XkbEvent *xkb_event = (XkbEvent *) xevent;
-
- CLUTTER_NOTE (BACKEND, "Received XKB event [%d]",
- xkb_event->any.xkb_type);
-
- switch (xkb_event->any.xkb_type)
- {
- case XkbStateNotify:
- update_locked_mods (keymap_x11, xkb_event->state.locked_mods);
- break;
-
- default:
- break;
- }
- }
-
- return CLUTTER_X11_FILTER_CONTINUE;
-}
#endif /* HAVE_XKB */
static void
g_assert (keymap_x11->backend != NULL);
backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
-#if HAVE_XKB
+#ifdef HAVE_XKB
{
gint xkb_major = XkbMajorVersion;
gint xkb_minor = XkbMinorVersion;
xkb_minor = XkbMinorVersion;
if (XkbQueryExtension (backend_x11->xdpy,
- NULL, &backend_x11->xkb_event_base, NULL,
+ NULL,
+ &keymap_x11->xkb_event_base,
+ NULL,
&xkb_major, &xkb_minor))
{
Bool detectable_autorepeat_supported;
XkbSelectEventDetails (backend_x11->xdpy,
XkbUseCoreKbd, XkbStateNotify,
XkbAllStateComponentsMask,
- XkbGroupLockMask|XkbModifierLockMask);
-
- clutter_x11_add_filter (xkb_filter, backend_x11);
+ XkbGroupLockMask | XkbModifierLockMask);
/* enable XKB autorepeat */
XkbSetDetectableAutoRepeat (backend_x11->xdpy,
clutter_keymap_x11_finalize (GObject *gobject)
{
ClutterKeymapX11 *keymap;
+ ClutterEventTranslator *translator;
keymap = CLUTTER_KEYMAP_X11 (gobject);
+ translator = CLUTTER_EVENT_TRANSLATOR (keymap);
#ifdef HAVE_XKB
+ _clutter_backend_remove_event_translator (keymap->backend, translator);
+
if (keymap->xkb_desc != NULL)
XkbFreeKeyboard (keymap->xkb_desc, XkbAllComponentsMask, True);
#endif
clutter_keymap_x11_class_init (ClutterKeymapX11Class *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GParamSpec *pspec;
+
+ obj_props[PROP_BACKEND] =
+ g_param_spec_object ("backend",
+ P_("Backend"),
+ P_("The Clutter backend"),
+ CLUTTER_TYPE_BACKEND,
+ CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
gobject_class->constructed = clutter_keymap_x11_constructed;
gobject_class->set_property = clutter_keymap_x11_set_property;
gobject_class->finalize = clutter_keymap_x11_finalize;
-
- pspec = g_param_spec_object ("backend",
- "Backend",
- "The Clutter backend",
- CLUTTER_TYPE_BACKEND,
- CLUTTER_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY);
- obj_props[PROP_BACKEND] = pspec;
- g_object_class_install_property (gobject_class, PROP_BACKEND, pspec);
+ g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
}
static void
{
}
+static ClutterTranslateReturn
+clutter_keymap_x11_translate_event (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *event)
+{
+ ClutterKeymapX11 *keymap_x11 = CLUTTER_KEYMAP_X11 (translator);
+ ClutterBackendX11 *backend_x11;
+ ClutterTranslateReturn retval;
+ XEvent *xevent;
+
+ backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
+ if (!backend_x11->use_xkb)
+ return CLUTTER_TRANSLATE_CONTINUE;
+
+ xevent = native;
+
+ retval = CLUTTER_TRANSLATE_CONTINUE;
+
+#ifdef HAVE_XKB
+ if (xevent->type == keymap_x11->xkb_event_base)
+ {
+ XkbEvent *xkb_event = (XkbEvent *) xevent;
+
+ switch (xkb_event->any.xkb_type)
+ {
+ case XkbStateNotify:
+ CLUTTER_NOTE (EVENT, "Updating locked modifiers");
+ update_locked_mods (keymap_x11, xkb_event->state.locked_mods);
+ retval = CLUTTER_TRANSLATE_REMOVE;
+ break;
+
+ case XkbMapNotify:
+ CLUTTER_NOTE (EVENT, "Updating keyboard mapping");
+ XkbRefreshKeyboardMapping (&xkb_event->map);
+ backend_x11->keymap_serial += 1;
+ retval = CLUTTER_TRANSLATE_REMOVE;
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif /* HAVE_XKB */
+
+ return retval;
+}
+
+static void
+clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface)
+{
+ iface->translate_event = clutter_keymap_x11_translate_event;
+}
+
gint
_clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap,
ClutterModifierType state)
G_BEGIN_DECLS
-#define CLUTTER_TYPE_KEYMAP_X11 (clutter_keymap_x11_get_type ())
+#define CLUTTER_TYPE_KEYMAP_X11 (_clutter_keymap_x11_get_type ())
#define CLUTTER_KEYMAP_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_KEYMAP_X11, ClutterKeymapX11))
#define CLUTTER_IS_KEYMAP_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_KEYMAP_X11))
typedef struct _ClutterKeymapX11 ClutterKeymapX11;
-GType clutter_keymap_x11_get_type (void) G_GNUC_CONST;
+GType _clutter_keymap_x11_get_type (void) G_GNUC_CONST;
gint _clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap,
ClutterModifierType state);
*
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
+
+#include <math.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include "clutter-actor-private.h"
#include "clutter-debug.h"
-#include "clutter-main.h"
-#include "clutter-feature.h"
-#include "clutter-event.h"
+#include "clutter-device-manager-private.h"
#include "clutter-enum-types.h"
+#include "clutter-event-translator.h"
+#include "clutter-event.h"
+#include "clutter-feature.h"
+#include "clutter-main.h"
+#include "clutter-paint-volume-private.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
#define STAGE_X11_IS_MAPPED(s) ((((ClutterStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0)
-static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
+static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
+static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
+
+static GHashTable *clutter_stages_by_xid = NULL;
+
+#define clutter_stage_x11_get_type _clutter_stage_x11_get_type
G_DEFINE_TYPE_WITH_CODE (ClutterStageX11,
clutter_stage_x11,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
- clutter_stage_window_iface_init));
+ clutter_stage_window_iface_init)
+ G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
+ clutter_event_translator_iface_init));
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
#define _NET_WM_STATE_ADD 1 /* add/set property */
xclient.data.l[4] = 0;
XSendEvent (backend_x11->xdpy,
- DefaultRootWindow(backend_x11->xdpy),
+ DefaultRootWindow (backend_x11->xdpy),
False,
- SubstructureRedirectMask|SubstructureNotifyMask,
+ SubstructureRedirectMask | SubstructureNotifyMask,
(XEvent *)&xclient);
}
}
}
-void
+static void
clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
gint new_width,
gint new_height)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
- gboolean resize;
-
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
- resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin)
{
guint min_width, min_height;
XSizeHints *size_hints;
+ gboolean resize;
+
+ resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
size_hints = XAllocSizeHints();
}
}
-void
+static void
clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
Atom protocols[2];
int n = 0;
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
protocols[n++] = backend_x11->atom_WM_DELETE_WINDOW;
protocols[n++] = backend_x11->atom_NET_WM_PING;
clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window,
ClutterGeometry *geometry)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
-
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
/* If we're fullscreen, return the size of the display. */
if ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) &&
gint width,
gint height)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
gboolean resize;
if (stage_x11->is_foreign_xwin)
resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
if (width == 0 || height == 0)
{
/* Should not happen, if this turns up we need to debug it and
static inline void
set_wm_pid (ClutterStageX11 *stage_x11)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
long pid;
if (stage_x11->xwin == None || stage_x11->is_foreign_xwin)
static inline void
set_wm_title (ClutterStageX11 *stage_x11)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
-
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
if (stage_x11->xwin == None || stage_x11->is_foreign_xwin)
return;
static inline void
set_cursor_visible (ClutterStageX11 *stage_x11)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
-
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
if (stage_x11->xwin == None)
return;
clutter_stage_x11_realize (ClutterStageWindow *stage_window)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
+ ClutterDeviceManager *device_manager;
+ int event_flags;
set_wm_pid (stage_x11);
set_wm_title (stage_x11);
set_cursor_visible (stage_x11);
+
+ /* the masks for the events we want to select on a stage window;
+ * KeyPressMask and KeyReleaseMask are necessary even with XI1
+ * because key events are broken with that extension, and will
+ * be fixed by XI2
+ */
+ event_flags = StructureNotifyMask
+ | FocusChangeMask
+ | ExposureMask
+ | PropertyChangeMask
+ | EnterWindowMask
+ | LeaveWindowMask
+ | KeyPressMask
+ | KeyReleaseMask
+ | ButtonPressMask
+ | ButtonReleaseMask
+ | PointerMotionMask;
+
+ /* we unconditionally select input events even with event retrieval
+ * disabled because we need to guarantee that the Clutter internal
+ * state is maintained when calling clutter_x11_handle_event() without
+ * requiring applications or embedding toolkits to select events
+ * themselves. if we did that, we'd have to document the events to be
+ * selected, and also update applications and embedding toolkits each
+ * time we added a new mask, or a new class of events.
+ *
+ * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=998
+ * for the rationale of why we did conditional selection. it is now
+ * clear that a compositor should clear out the input region, since
+ * it cannot assume a perfectly clean slate coming from us.
+ *
+ * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=2228
+ * for an example of things that break if we do conditional event
+ * selection.
+ */
+ XSelectInput (backend_x11->xdpy, stage_x11->xwin, event_flags);
+
+ /* input events also depent on the actual device, so we need to
+ * use the device manager to let every device select them, using
+ * the event mask we passed to XSelectInput as the template
+ */
+ device_manager = clutter_device_manager_get_default ();
+ _clutter_device_manager_select_stage_events (device_manager,
+ stage_x11->wrapper,
+ event_flags);
+
+ /* no user resize.. */
+ clutter_stage_x11_fix_window_size (stage_x11,
+ stage_x11->xwin_width,
+ stage_x11->xwin_height);
+ clutter_stage_x11_set_wm_protocols (stage_x11);
+
+ CLUTTER_NOTE (BACKEND, "Successfully realized stage");
+
return TRUE;
}
clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
gboolean is_fullscreen)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStage *stage = stage_x11->wrapper;
+ gboolean was_fullscreen;
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
- if (stage == NULL)
+ if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
return;
- if (!!(stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) == is_fullscreen)
+ was_fullscreen = ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) != 0);
+ is_fullscreen = !!is_fullscreen;
+
+ if (was_fullscreen == is_fullscreen)
return;
CLUTTER_NOTE (BACKEND, "%ssetting fullscreen", is_fullscreen ? "" : "un");
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
- stage_x11->is_cursor_visible = (cursor_visible == TRUE);
+ stage_x11->is_cursor_visible = !!cursor_visible;
set_cursor_visible (stage_x11);
}
static inline void
update_wm_hints (ClutterStageX11 *stage_x11)
{
- ClutterBackend *backend;
- ClutterBackendX11 *backend_x11;
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
XWMHints wm_hints;
if (stage_x11->wm_state & STAGE_X11_WITHDRAWN)
if (stage_x11->is_foreign_xwin)
return;
- backend = clutter_get_default_backend ();
- g_assert (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
wm_hints.flags = StateHint | InputHint;
wm_hints.initial_state = NormalState;
wm_hints.input = stage_x11->accept_focus ? True : False;
clutter_stage_x11_show (ClutterStageWindow *stage_window,
gboolean do_raise)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
-
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
if (stage_x11->xwin != None)
{
static void
clutter_stage_x11_hide (ClutterStageWindow *stage_window)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
-
- g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
if (stage_x11->xwin != None)
{
static void
clutter_stage_x11_dispose (GObject *gobject)
{
+ ClutterEventTranslator *translator = CLUTTER_EVENT_TRANSLATOR (gobject);
+ ClutterBackendX11 *backend = CLUTTER_STAGE_X11 (gobject)->backend;
+
+ _clutter_backend_remove_event_translator (CLUTTER_BACKEND (backend),
+ translator);
+
G_OBJECT_CLASS (clutter_stage_x11_parent_class)->dispose (gobject);
}
iface->realize = clutter_stage_x11_realize;
}
+static inline void
+set_user_time (ClutterBackendX11 *backend_x11,
+ ClutterStageX11 *stage_x11,
+ long timestamp)
+{
+ if (timestamp != CLUTTER_CURRENT_TIME)
+ {
+ XChangeProperty (backend_x11->xdpy,
+ stage_x11->xwin,
+ backend_x11->atom_NET_WM_USER_TIME,
+ XA_CARDINAL, 32,
+ PropModeReplace,
+ (unsigned char *) ×tamp, 1);
+ }
+}
+
+static gboolean
+handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
+ ClutterStageX11 *stage_x11,
+ XEvent *xevent)
+{
+ Atom atom = (Atom) xevent->xclient.data.l[0];
+
+ if (atom == backend_x11->atom_WM_DELETE_WINDOW &&
+ xevent->xany.window == stage_x11->xwin)
+ {
+ /* the WM_DELETE_WINDOW is a request: we do not destroy
+ * the window right away, as it might contain vital data;
+ * we relay the event to the application and we let it
+ * handle the request
+ */
+ CLUTTER_NOTE (EVENT, "Delete stage %s[%p], win:0x%x",
+ _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage_x11->wrapper)),
+ stage_x11->wrapper,
+ (unsigned int) stage_x11->xwin);
+
+ set_user_time (backend_x11, stage_x11, xevent->xclient.data.l[1]);
+
+ return TRUE;
+ }
+ else if (atom == backend_x11->atom_NET_WM_PING &&
+ xevent->xany.window == stage_x11->xwin)
+ {
+ XClientMessageEvent xclient = xevent->xclient;
+
+ xclient.window = backend_x11->xwin_root;
+ XSendEvent (backend_x11->xdpy, xclient.window,
+ False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ (XEvent *) &xclient);
+ return FALSE;
+ }
+
+ /* do not send any of the WM_PROTOCOLS events to the queue */
+ return FALSE;
+}
+
+static gboolean
+clipped_redraws_cool_off_cb (void *data)
+{
+ ClutterStageX11 *stage_x11 = data;
+
+ stage_x11->clipped_redraws_cool_off = 0;
+
+ return FALSE;
+}
+
+static ClutterTranslateReturn
+clutter_stage_x11_translate_event (ClutterEventTranslator *translator,
+ gpointer native,
+ ClutterEvent *event)
+{
+ ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (translator);
+ ClutterTranslateReturn res = CLUTTER_TRANSLATE_CONTINUE;
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
+ Window stage_xwindow = stage_x11->xwin;
+ XEvent *xevent = native;
+ ClutterStage *stage;
+
+ stage = clutter_x11_get_stage_from_window (xevent->xany.window);
+ if (stage == NULL)
+ return CLUTTER_TRANSLATE_CONTINUE;
+
+ switch (xevent->type)
+ {
+ case ConfigureNotify:
+ if (!stage_x11->is_foreign_xwin)
+ {
+ gboolean size_changed = FALSE;
+
+ CLUTTER_NOTE (BACKEND, "ConfigureNotify[%x] (%d, %d)",
+ (unsigned int) stage_x11->xwin,
+ xevent->xconfigure.width,
+ xevent->xconfigure.height);
+
+ /* When fullscreen, we'll keep the xwin_width/height
+ variables to track the old size of the window and we'll
+ assume all ConfigureNotifies constitute a size change */
+ if ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN))
+ size_changed = TRUE;
+ else if ((stage_x11->xwin_width != xevent->xconfigure.width) ||
+ (stage_x11->xwin_height != xevent->xconfigure.height))
+ {
+ size_changed = TRUE;
+ stage_x11->xwin_width = xevent->xconfigure.width;
+ stage_x11->xwin_height = xevent->xconfigure.height;
+ }
+
+ clutter_actor_set_size (CLUTTER_ACTOR (stage),
+ xevent->xconfigure.width,
+ xevent->xconfigure.height);
+
+ CLUTTER_UNSET_PRIVATE_FLAGS (stage_x11->wrapper, CLUTTER_IN_RESIZE);
+
+ if (size_changed)
+ {
+ /* XXX: This is a workaround for a race condition when
+ * resizing windows while there are in-flight
+ * glXCopySubBuffer blits happening.
+ *
+ * The problem stems from the fact that rectangles for the
+ * blits are described relative to the bottom left of the
+ * window and because we can't guarantee control over the X
+ * window gravity used when resizing so the gravity is
+ * typically NorthWest not SouthWest.
+ *
+ * This means if you grow a window vertically the server
+ * will make sure to place the old contents of the window
+ * at the top-left/north-west of your new larger window, but
+ * that may happen asynchronous to GLX preparing to do a
+ * blit specified relative to the bottom-left/south-west of
+ * the window (based on the old smaller window geometry).
+ *
+ * When the GLX issued blit finally happens relative to the
+ * new bottom of your window, the destination will have
+ * shifted relative to the top-left where all the pixels you
+ * care about are so it will result in a nasty artefact
+ * making resizing look very ugly!
+ *
+ * We can't currently fix this completely, in-part because
+ * the window manager tends to trample any gravity we might
+ * set. This workaround instead simply disables blits for a
+ * while if we are notified of any resizes happening so if
+ * the user is resizing a window via the window manager then
+ * they may see an artefact for one frame but then we will
+ * fallback to redrawing the full stage until the cooling
+ * off period is over.
+ */
+ if (stage_x11->clipped_redraws_cool_off)
+ g_source_remove (stage_x11->clipped_redraws_cool_off);
+
+ stage_x11->clipped_redraws_cool_off =
+ g_timeout_add_seconds (1, clipped_redraws_cool_off_cb,
+ stage_x11);
+
+ /* Queue a relayout - we want glViewport to be called
+ * with the correct values, and this is done in ClutterStage
+ * via _cogl_onscreen_clutter_backend_set_size ().
+ *
+ * We queue a relayout, because if this ConfigureNotify is
+ * in response to a size we set in the application, the
+ * set_size() call above is essentially a null-op.
+ *
+ * Make sure we do this only when the size has changed,
+ * otherwise we end up relayouting on window moves.
+ */
+ clutter_actor_queue_relayout (CLUTTER_ACTOR (stage));
+
+ /* the resize process is complete, so we can ask the stage
+ * to set up the GL viewport with the new size
+ */
+ clutter_stage_ensure_viewport (stage);
+ }
+ }
+ break;
+
+ case PropertyNotify:
+ if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE &&
+ xevent->xproperty.window == stage_xwindow &&
+ !stage_x11->is_foreign_xwin)
+ {
+ Atom type;
+ gint format;
+ gulong n_items, bytes_after;
+ guchar *data = NULL;
+ gboolean fullscreen_set = FALSE;
+
+ clutter_x11_trap_x_errors ();
+ XGetWindowProperty (backend_x11->xdpy, stage_xwindow,
+ backend_x11->atom_NET_WM_STATE,
+ 0, G_MAXLONG,
+ False, XA_ATOM,
+ &type, &format, &n_items,
+ &bytes_after, &data);
+ clutter_x11_untrap_x_errors ();
+
+ if (type != None && data != NULL)
+ {
+ Atom *atoms = (Atom *) data;
+ gulong i;
+ gboolean is_fullscreen = FALSE;
+
+ for (i = 0; i < n_items; i++)
+ {
+ if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN)
+ fullscreen_set = TRUE;
+ }
+
+ is_fullscreen =
+ (stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN);
+
+ if (fullscreen_set != is_fullscreen)
+ {
+ if (fullscreen_set)
+ stage_x11->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
+ else
+ stage_x11->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
+
+ stage_x11->fullscreening = fullscreen_set;
+
+ event->any.type = CLUTTER_STAGE_STATE;
+ event->any.source = CLUTTER_ACTOR (stage);
+ event->any.stage = stage;
+ event->stage_state.changed_mask =
+ CLUTTER_STAGE_STATE_FULLSCREEN;
+ event->stage_state.new_state = stage_x11->state;
+
+ res = CLUTTER_TRANSLATE_QUEUE;
+ }
+
+ XFree (data);
+ }
+ }
+ break;
+
+ case FocusIn:
+ if (!(stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED))
+ {
+ /* TODO: check the detail? */
+ stage_x11->state |= CLUTTER_STAGE_STATE_ACTIVATED;
+
+ event->type = CLUTTER_STAGE_STATE;
+ event->any.source = CLUTTER_ACTOR (stage);
+ event->any.stage = stage;
+ event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
+ event->stage_state.new_state = stage_x11->state;
+
+ res = CLUTTER_TRANSLATE_QUEUE;
+ }
+ break;
+
+ case FocusOut:
+ if (stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED)
+ {
+ /* TODO: check the detail? */
+ stage_x11->state &= ~CLUTTER_STAGE_STATE_ACTIVATED;
+
+ event->any.type = CLUTTER_STAGE_STATE;
+ event->any.source = CLUTTER_ACTOR (stage);
+ event->any.stage = stage;
+ event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
+ event->stage_state.new_state = stage_x11->state;
+
+ res = CLUTTER_TRANSLATE_QUEUE;
+ }
+ break;
+
+ case Expose:
+ {
+ XExposeEvent *expose = (XExposeEvent *) xevent;
+ ClutterPaintVolume clip;
+ ClutterVertex origin;
+
+ CLUTTER_NOTE (EVENT,
+ "expose for stage: %s[%p], win:0x%x - "
+ "redrawing area (x: %d, y: %d, width: %d, height: %d)",
+ _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)),
+ stage,
+ (unsigned int) stage_xwindow,
+ expose->x,
+ expose->y,
+ expose->width,
+ expose->height);
+
+ origin.x = expose->x;
+ origin.y = expose->y;
+ origin.z = 0;
+
+ _clutter_paint_volume_init_static (CLUTTER_ACTOR (stage), &clip);
+
+ clutter_paint_volume_set_origin (&clip, &origin);
+ clutter_paint_volume_set_width (&clip, expose->width);
+ clutter_paint_volume_set_height (&clip, expose->height);
+
+ _clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), 0, &clip);
+
+ clutter_paint_volume_free (&clip);
+ }
+ break;
+
+ case DestroyNotify:
+ CLUTTER_NOTE (EVENT,
+ "Destroy notification received for stage %s[%p], win:0x%x",
+ _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)),
+ stage,
+ (unsigned int) stage_xwindow);
+ event->any.type = CLUTTER_DESTROY_NOTIFY;
+ event->any.stage = stage;
+ res = CLUTTER_TRANSLATE_QUEUE;
+ break;
+
+ case ClientMessage:
+ CLUTTER_NOTE (EVENT, "Client message for stage %s[%p], win:0x%x",
+ _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)),
+ stage,
+ (unsigned int) stage_xwindow);
+ if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
+ {
+ event->any.type = CLUTTER_DELETE;
+ event->any.stage = stage;
+ res = CLUTTER_TRANSLATE_QUEUE;
+ }
+ break;
+
+ case MappingNotify:
+ CLUTTER_NOTE (EVENT, "Refresh keyboard mapping");
+ XRefreshKeyboardMapping (&xevent->xmapping);
+ backend_x11->keymap_serial += 1;
+ res = CLUTTER_TRANSLATE_REMOVE;
+ break;
+
+ default:
+ res = CLUTTER_TRANSLATE_CONTINUE;
+ break;
+ }
+
+ return res;
+}
+
+static void
+clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface)
+{
+ iface->translate_event = clutter_stage_x11_translate_event;
+}
+
/**
- * clutter_x11_get_stage_window:
+ * clutter_x11_get_stage_window: (skip)
* @stage: a #ClutterStage
*
* Gets the stages X Window.
ClutterStage *
clutter_x11_get_stage_from_window (Window win)
{
- ClutterStageManager *stage_manager;
- const GSList *stages, *s;
+ ClutterStageX11 *stage_x11;
- stage_manager = clutter_stage_manager_get_default ();
- stages = clutter_stage_manager_peek_stages (stage_manager);
+ if (clutter_stages_by_xid == NULL)
+ return NULL;
- /* XXX: might use a hash here for performance resaon */
- for (s = stages; s != NULL; s = s->next)
- {
- ClutterStage *stage = s->data;
- ClutterStageWindow *impl;
+ stage_x11 = g_hash_table_lookup (clutter_stages_by_xid,
+ GINT_TO_POINTER (win));
- impl = _clutter_stage_get_window (stage);
- g_assert (CLUTTER_IS_STAGE_X11 (impl));
-
- if (CLUTTER_STAGE_X11 (impl)->xwin == win)
- return stage;
- }
+ if (stage_x11 != NULL)
+ return stage_x11->wrapper;
return NULL;
}
/**
- * clutter_x11_get_stage_visual:
+ * clutter_x11_get_stage_visual: (skip)
* @stage: a #ClutterStage
*
* Returns an XVisualInfo suitable for creating a foreign window for the given
g_return_val_if_fail (CLUTTER_IS_BACKEND_X11 (backend), NULL);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
- return clutter_backend_x11_get_visual_info (backend_x11);
+ return _clutter_backend_x11_get_visual_info (backend_x11);
}
typedef struct {
void *data)
{
ForeignWindowData *fwd = data;
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendX11 *backend_x11 = fwd->stage_x11->backend;
CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)",
(unsigned int) fwd->xwindow);
clutter_actor_set_geometry (actor, &fwd->geom);
+ if (clutter_stages_by_xid == NULL)
+ clutter_stages_by_xid = g_hash_table_new (NULL, NULL);
+
+ g_hash_table_insert (clutter_stages_by_xid,
+ GINT_TO_POINTER (fwd->stage_x11->xwin),
+ fwd->stage_x11);
+
/* calling this with the stage unrealized will unset the stage
* from the GL context; once the stage is realized the GL context
* will be set again
clutter_x11_set_stage_foreign (ClutterStage *stage,
Window xwindow)
{
- ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11;
ClutterStageWindow *impl;
ForeignWindowData fwd;
XVisualInfo *xvisinfo;
- g_return_val_if_fail (CLUTTER_IS_BACKEND_X11 (backend), FALSE);
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
g_return_val_if_fail (!CLUTTER_ACTOR_IN_DESTRUCTION (stage), FALSE);
g_return_val_if_fail (xwindow != None, FALSE);
- actor = CLUTTER_ACTOR (stage);
+ impl = _clutter_stage_get_window (stage);
+ stage_x11 = CLUTTER_STAGE_X11 (impl);
+ backend_x11 = stage_x11->backend;
- xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
+ xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11);
g_return_val_if_fail (xvisinfo != NULL, FALSE);
clutter_x11_trap_x_errors ();
return FALSE;
}
- impl = _clutter_stage_get_window (stage);
- stage_x11 = CLUTTER_STAGE_X11 (impl);
-
fwd.stage_x11 = stage_x11;
fwd.xwindow = xwindow;
fwd.geom.width = width;
fwd.geom.height = height;
+ actor = CLUTTER_ACTOR (stage);
+
_clutter_actor_rerealize (actor,
set_foreign_window_callback,
&fwd);
* in the Cogl viewport changing when _clutter_do_redraw
* calls _clutter_stage_maybe_setup_viewport().
*/
- clutter_actor_queue_relayout (CLUTTER_ACTOR (stage));
+ clutter_actor_queue_relayout (actor);
return TRUE;
}
+
+void
+_clutter_stage_x11_destroy_window_untrapped (ClutterStageX11 *stage_x11)
+{
+ Window xwin = stage_x11->xwin;
+
+ if (clutter_stages_by_xid != NULL)
+ g_hash_table_remove (clutter_stages_by_xid, GINT_TO_POINTER (xwin));
+
+ if (!stage_x11->is_foreign_xwin && xwin != None)
+ {
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
+
+ g_assert (clutter_stages_by_xid != NULL);
+
+ XDestroyWindow (backend_x11->xdpy, xwin);
+ stage_x11->xwin = None;
+ }
+ else
+ stage_x11->xwin = None;
+}
+
+void
+_clutter_stage_x11_destroy_window (ClutterStageX11 *stage_x11)
+{
+ if (stage_x11->xwin == None)
+ return;
+
+ clutter_x11_trap_x_errors ();
+
+ _clutter_stage_x11_destroy_window_untrapped (stage_x11);
+
+ clutter_x11_untrap_x_errors ();
+}
+
+gboolean
+_clutter_stage_x11_create_window (ClutterStageX11 *stage_x11)
+{
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
+ XSetWindowAttributes xattr;
+ XVisualInfo *xvisinfo;
+ unsigned long mask;
+ gfloat width, height;
+
+ if (stage_x11->xwin != None)
+ return TRUE;
+
+ CLUTTER_NOTE (MISC, "Creating stage X window");
+
+ xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11);
+ if (xvisinfo == NULL)
+ {
+ g_critical ("Unable to find suitable GL visual.");
+ return FALSE;
+ }
+
+ /* window attributes */
+ xattr.background_pixel = WhitePixel (backend_x11->xdpy,
+ backend_x11->xscreen_num);
+ xattr.border_pixel = 0;
+ xattr.colormap = XCreateColormap (backend_x11->xdpy,
+ backend_x11->xwin_root,
+ xvisinfo->visual,
+ AllocNone);
+ mask = CWBorderPixel | CWColormap;
+
+ /* Call get_size - this will either get the geometry size (which
+ * before we create the window is set to 640x480), or if a size
+ * is set, it will get that. This lets you set a size on the
+ * stage before it's realized.
+ *
+ * we also round to the nearest integer because stage sizes
+ * should always be in pixels
+ */
+ clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
+ stage_x11->xwin_width = floorf (width + 0.5);
+ stage_x11->xwin_height = floorf (height + 0.5);
+
+ stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
+ backend_x11->xwin_root,
+ 0, 0,
+ stage_x11->xwin_width,
+ stage_x11->xwin_height,
+ 0,
+ xvisinfo->depth,
+ InputOutput,
+ xvisinfo->visual,
+ mask, &xattr);
+
+ CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
+ stage_x11,
+ (unsigned int) stage_x11->xwin,
+ stage_x11->xwin_width,
+ stage_x11->xwin_height);
+
+ XFree (xvisinfo);
+
+ if (clutter_stages_by_xid == NULL)
+ clutter_stages_by_xid = g_hash_table_new (NULL, NULL);
+
+ g_hash_table_insert (clutter_stages_by_xid,
+ GINT_TO_POINTER (stage_x11->xwin),
+ stage_x11);
+
+ return TRUE;
+}
+
+void
+_clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
+ guint32 user_time)
+{
+ set_user_time (stage_x11->backend, stage_x11, user_time);
+}
+
+gboolean
+_clutter_stage_x11_get_root_coords (ClutterStageX11 *stage_x11,
+ gint *root_x,
+ gint *root_y)
+{
+ ClutterBackendX11 *backend_x11 = stage_x11->backend;
+ gint return_val;
+ Window child;
+ gint tx, ty;
+
+ return_val = XTranslateCoordinates (backend_x11->xdpy,
+ stage_x11->xwin,
+ backend_x11->xwin_root,
+ 0, 0, &tx, &ty,
+ &child);
+
+ if (root_x)
+ *root_x = tx;
+
+ if (root_y)
+ *root_y = ty;
+
+ return (return_val == 0);
+}
G_BEGIN_DECLS
-#define CLUTTER_TYPE_STAGE_X11 (clutter_stage_x11_get_type ())
+#define CLUTTER_TYPE_STAGE_X11 (_clutter_stage_x11_get_type ())
#define CLUTTER_STAGE_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_X11, ClutterStageX11))
#define CLUTTER_IS_STAGE_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_X11))
#define CLUTTER_STAGE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_X11, ClutterStageX11Class))
ClutterStageX11State wm_state;
- int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
- GList *devices;
-
+ /* backpointers */
ClutterStage *wrapper;
+ ClutterBackendX11 *backend;
};
struct _ClutterStageX11Class
ClutterGroupClass parent_class;
};
-GType clutter_stage_x11_get_type (void) G_GNUC_CONST;
+GType _clutter_stage_x11_get_type (void) G_GNUC_CONST;
/* Private to subclasses */
-void clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
- gint new_width,
- gint new_height);
-void clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11);
-void clutter_stage_x11_map (ClutterStageX11 *stage_x11);
-void clutter_stage_x11_unmap (ClutterStageX11 *stage_x11);
-
-GList *clutter_stage_x11_get_input_devices (ClutterStageX11 *stage_x11);
+gboolean _clutter_stage_x11_create_window (ClutterStageX11 *stage_x11);
+void _clutter_stage_x11_destroy_window_untrapped (ClutterStageX11 *stage_x11);
+void _clutter_stage_x11_destroy_window (ClutterStageX11 *stage_x11);
+void _clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
+ guint32 user_time);
+gboolean _clutter_stage_x11_get_root_coords (ClutterStageX11 *stage_x11,
+ gint *root_x,
+ gint *root_y);
G_END_DECLS
* ClutterX11TexturePixmap::update-area:
* @texture: the object which received the signal
*
- * The ::hide signal is emitted to ask the texture to update its
+ * The ::update-area signal is emitted to ask the texture to update its
* content from its source pixmap.
*
* Since: 0.8
# Making a point release:
# - increase clutter_micro_version to the next even number
# - increase clutter_interface_age to the next even number
-# UNLESS there was an API addition/deprecation, in which case
-# - set clutter_interface_age to 0
# After the release:
# - increase clutter_micro_version to the next odd number
# - increase clutter_interface_version to the next odd number
m4_define([clutter_major_version], [1])
-m4_define([clutter_minor_version], [5])
-m4_define([clutter_micro_version], [11])
+m4_define([clutter_minor_version], [6])
+m4_define([clutter_micro_version], [3])
-m4_define([clutter_release_status],
- [m4_if(m4_eval(clutter_micro_version % 2), [1], [git],
- [m4_if(m4_eval(clutter_minor_version % 2), [1], [snapshot],
- [release])])])
-
-m4_define([clutter_version], [clutter_major_version.clutter_minor_version.clutter_micro_version])
-
-# change this only when breaking the API
-m4_define([clutter_api_version], [1.0])
-
-# increase the interface age by 1 for each release; if the API changes,
-# set to 0. interface_age and binary_age are used to create the soname
-# of the shared object:
+# • for stable releases: increase the interface age by 1 for each release;
+# if the API changes, set to 0. interface_age and binary_age are used to
+# create the soname of the shared object:
#
# (<minor> * 100 + <micro>) - <interface_age>
#
# clutter 1.2.10 -> 100 * 2 + 10 = 210, interface age = 4 -> 206
# ...
#
-m4_define([clutter_interface_age], [0])
+# • for development releases: keep clutter_interface_age to 0
+m4_define([clutter_interface_age], [3])
+
m4_define([clutter_binary_age], [m4_eval(100 * clutter_minor_version + clutter_micro_version)])
+m4_define([clutter_release_status],
+ [m4_if(m4_eval(clutter_micro_version % 2), [1], [git],
+ [m4_if(m4_eval(clutter_minor_version % 2), [1], [snapshot],
+ [release])])])
+
+m4_define([clutter_version], [clutter_major_version.clutter_minor_version.clutter_micro_version])
+
+# change this only when breaking the API
+m4_define([clutter_api_version], [1.0])
+
AC_PREREQ([2.63])
AC_INIT([clutter],
AC_SUBST(CLUTTER_LT_VERSION)
AC_SUBST(CLUTTER_LT_LDFLAGS)
+dnl The 'ffs' function is part of C99 so it isn't always
+dnl available. Cogl has a fallback if needed.
+AC_CHECK_FUNCS([ffs])
+
dnl ========================================================================
# Checks for programs.
AC_DEFINE([COGL_ENABLE_EXPERIMENTAL_2_0_API], [1],
[Can use Cogl 2.0 API internally])
+dnl === Clutter configuration =================================================
+
+CLUTTER_CONFIG_DEFINES=
+
+# windowing systems
+AS_IF([test "x$SUPPORT_XLIB" = "x1"],
+ [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
+#define CLUTTER_WINDOWING_X11 1"])
+AS_IF([test "x$SUPPORT_GLX" = "x1"],
+ [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
+#define CLUTTER_WINDOWING_GLX 1"])
+AS_IF([test "x$SUPPORT_EGL" = "x1"],
+ [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
+#define CLUTTER_WINDOWING_EGL 1"])
+AS_IF([test "x$SUPPORT_WAYLAND" = "x1"],
+ [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
+#define CLUTTER_WINDOWING_WAYLAND 1"])
+AS_IF([test "x$SUPPORT_OSX" = "x1"],
+ [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
+#define CLUTTER_WINDOWING_OSX 1"])
+AS_IF([test "x$SUPPORT_WIN32" = "x1"],
+ [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
+#define CLUTTER_WINDOWING_WIN32 1"])
+AS_IF([test "x$SUPPORT_CEX100" = "x1"],
+ [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES
+#define CLUTTER_WINDOWING_CEX100 1"])
+
+AC_SUBST([CLUTTER_CONFIG_DEFINES])
+
dnl === Clutter substitutions =================================================
# Eventually the idea of a winsys should be hidden from Clutter and moved
# into Cogl, but for now we have CLUTTER_WINSYS...
[AC_MSG_ERROR([not found])]
)
- # XINPUT (optional)
- xinput=no
+ # XI (optional)
AC_ARG_ENABLE([xinput],
- [AS_HELP_STRING([--enable-xinput], [Use the XINPUT X extension])],
- [
- AS_IF([test "x$enableval" = "xyes"],
- [PKG_CHECK_MODULES(XINPUT, [xi], [xinput=yes], [xinput=no])]
- )
- ],
- [xinput=no])
+ [AS_HELP_STRING([--enable-xinput], [Use the XI X extension])],
+ [],
+ [enable_xinput=yes])
- AS_CASE([$xinput],
+ AS_IF([test "x$enable_xinput" = "xyes"],
+ [
+ PKG_CHECK_EXISTS([xi], [have_xinput=yes], [have_xinput=no])
+ ],
+ [
+ have_xinput=no
+ ])
+
+ AS_CASE([$have_xinput],
[yes],
[
- AC_DEFINE(HAVE_XINPUT, 1, [Use the XINPUT X extension])
-
- X11_LIBS="$X11_LIBS -lXi"
+ AC_CHECK_HEADERS([X11/extensions/XInput2.h],
+ [
+ have_xinput2=yes
+ AC_DEFINE([HAVE_XINPUT_2],
+ [1],
+ [Define to 1 if XI2 is available])
+ ],
+ [
+ have_xinput2=no
+ AC_DEFINE([HAVE_XINPUT],
+ [1],
+ [Define to 1 if XInput is available])
+ ])
+
+ X11_LIBS="$X11_LIBS $XINPUT_LIBS"
X11_PC_FILES="$X11_PC_FILES xi"
],
[no],
- [],
+ [have_xinput2=no],
+
+ [*],
+ [AC_MSG_ERROR([Invalid argument for --enable-xinput])]
)
# XKB
]
)
+AM_CONDITIONAL([BUILD_XI2], [test "x$have_xinput2" = "xyes"])
AM_CONDITIONAL(X11_TESTS, [test "x$x11_tests" = "xyes"])
dnl === Enable debug level ====================================================
dnl === Enable strict compiler flags ==========================================
-# use strict compiler flags only on development releases
-m4_define([maintainer_flags_default], [m4_if(m4_eval(clutter_minor_version % 2), [1], [yes], [no])])
+# use strict compiler flags only when building from git; the rules for
+# distcheck will take care of turning this on when making a release
+m4_define([maintainer_flags_default], [m4_if(m4_eval(clutter_micro_version % 2), [1], [yes], [no])])
AC_ARG_ENABLE([maintainer-flags],
- [AC_HELP_STRING([--enable-maintainer-flags=@<:@no/yes@:>@],
+ [AC_HELP_STRING([--enable-maintainer-flags=@<:@no/yes/error@:>@],
[Use strict compiler flags @<:@default=maintainer_flags_default@:>@])],
[],
[enable_maintainer_flags=maintainer_flags_default])
-AS_IF([test "x$enable_maintainer_flags" = "xyes" && test "x$GCC" = "xyes"],
- [
- AS_COMPILER_FLAGS([MAINTAINER_CFLAGS],
- ["-Wall -Wshadow -Wcast-align -Wuninitialized
- -Wno-strict-aliasing -Wempty-body -Wformat
- -Wformat-security -Winit-self
- -Wdeclaration-after-statement -Wvla"])
- ]
+MAINTAINER_COMPILER_FLAGS="-Wall -Wshadow -Wcast-align -Wuninitialized
+ -Wno-strict-aliasing -Wempty-body -Wformat
+ -Wformat-security -Winit-self
+ -Wdeclaration-after-statement -Wvla"
+
+AS_CASE([$enable_maintainer_flags],
+ [yes],
+ [
+ AS_COMPILER_FLAGS([MAINTAINER_CFLAGS], [$MAINTAINER_COMPILER_FLAGS])
+ ],
+
+ [no],
+ [
+ ],
+
+ [error],
+ [
+ MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS -Werror"
+ AS_COMPILER_FLAGS([MAINTAINER_CFLAGS], [$MAINTAINER_COMPILER_FLAGS])
+ ],
+
+ [*],
+ [AC_MSG_ERROR([Invalid option for --enable-maintainer-flags])]
)
AC_SUBST(MAINTAINER_CFLAGS)
build/mingw/Makefile
clutter/Makefile
+ clutter/clutter-config.h
clutter/clutter-version.h
clutter/clutter-$CLUTTER_API_VERSION.pc:clutter/clutter.pc.in
if test "x$SUPPORT_XLIB" = "x1"; then
echo " Enable XComposite: ${have_xcomposite}"
-echo " Enable XInput 1.0: ${xinput}"
+echo " Enable XInput: ${have_xinput}"
+echo " Enable XI2: ${have_xinput2}"
echo " Enable XKB: ${have_xkb}"
echo " Enable X11 tests: ${x11_tests}"
fi
IMPLEMENTING BACKENDS
-=====================
+===============================================================================
Clutter supports multiple backends for handling windowing systems and
GL/GLES API on different platforms.
<backend>/clutter-stage-<backend>.h
<backend>/clutter-stage-<backend>.c
- -- The implementation of the stage actor.
+ -- The implementation of the stage window
+
+ <backend>/clutter-device-manager-<backend>.h
+ <backend>/clutter-device-manager-<backend>.c
+
+ -- The implementation of the input device manager
<backend>/clutter-event-<backend>.c
- -- The event handling code (optional).
+ -- Event-specific code (optional)
<backend>/clutter-<backend>.h
Implementing ClutterBackend
----------------------------
+-------------------------------------------------------------------------------
Each backend must implement the
drawing surface or should unset the drawing surface from the
drawing context.
- ClutterBackend::redraw
- -- This function is used to draw the passed ClutterStage; the backend
- must call clutter_actor_paint() on the ClutterStage that has been
- passed as a parameter and then perform backend-specific tasks, like
- waiting for vertical blanking and swapping the buffers.
-
ClutterBackend::create_stage
-- This function is used to create the stage implementation. It will
receive as an argument the ClutterStage instance that is "wrapping"
its stage implementation, initialise it and then return it; in case
of error, the backend must return NULL and set the passed GError.
+ ClutterBackend::get_device_manager
+ -- This function is used to return the ClutterDeviceManager instance
+ that is going to be returned by clutter_device_manager_get_default()
+ and that should be used internally by input event translation.
+
Implementing the stage
-----------------------
+-------------------------------------------------------------------------------
ClutterStage acts as a wrapper object relaying all the drawing operations
to the actual implementation. The implementation of the stage can be any
• ClutterStageWindow::show() and ::hide()
• ClutterStageWindow::resize()
• ClutterStageWindow::get_geometry()
+ • ClutterStageWindow::redraw()
The ::get_wrapper() implementation should return the pointer to the
ClutterStage actor using the ClutterStageWindow implementation.
The ::resize() virtual function implementation should cause an update
of the COGL viewport.
+The ::redraw() virtual function implementation should contain the platform
+specific drawing logic, and call _clutter_stage_do_paint() on the ClutterStage
+wrapper instance to cause the scene to be painted.
+
The stage implementation actor can optionally implement:
• ClutterStageWindow::get_pending_swaps()
buffer requests pending completion. This is only relevent for backends
that also support CLUTTER_FEATURE_SWAP_EVENTS.
+If the stage window is supposed to handle events, then it should also implement
+the ClutterEventTranslator interface; this interface has a single virtual
+function:
+
+ • ClutterEventTranslator::translate_event()
+
+which gets passed a pointer to the native event data structure, and a pointer
+to a newly-allocated, empty ClutterEvent. The EventTranslator implementation
+should then decide between three options:
+
+ - translate the native event and return CLUTTER_TRANSLATE_QUEUE to
+ let Clutter queue it up in the events queue;
+ - return CLUTTER_TRANSLATE_CONTINUE to let other event translators handle
+ the event;
+ - return CLUTTER_TRANSLATE_REMOVE to ignore the event.
+
+Implementing ClutterDeviceManager
+-------------------------------------------------------------------------------
+
+Backends with input devices should provide a ClutterDeviceManager
+implementation to handle addition, removal and input device event translation
+through the ClutterEventTranslator interface.
+
NOTES
-=====
+===============================================================================
-If the platform is using X11 you should probably subclass ClutterBackendX11
-and ClutterStageX11, which will provide you with a ready to use code
-implementation for event handling and window management.
+• If the platform is using X11 you should probably subclass ClutterBackendX11
+ and ClutterStageX11, which will provide you with a ready to use code
+ implementation for event handling and window management.
TARGET_DIR = $(HTML_DIR)/clutter-cookbook
XML_FILES = \
- actors.xml \
- animations.xml \
- events.xml \
- introduction.xml \
- text.xml \
- textures.xml \
- layouts.xml \
- script.xml \
+ $(srcdir)/actors.xml \
+ $(srcdir)/animations.xml \
+ $(srcdir)/events.xml \
+ $(srcdir)/introduction.xml \
+ $(srcdir)/text.xml \
+ $(srcdir)/textures.xml \
+ $(srcdir)/layouts.xml \
+ $(srcdir)/script.xml \
$(NULL)
XSLTOPTS = \
--stringparam section.autolabel 1 \
--stringparam gtkdoc.bookname "clutter-cookbook" \
--stringparam gtkdoc.version @CLUTTER_API_VERSION@ \
- --stringparam callout.graphics 0 \
+ --stringparam callout.graphics 0 \
--path $(top_srcdir)/doc/common \
--xinclude
XSL_BASE_URI = http://docbook.sourceforge.net/release/xsl/current
XSL_XHTML_URI = $(XSL_BASE_URI)/xhtml/docbook.xsl
-HTML_FILES = html/*.html
-CSS_FILES = html/*.css
+HTML_FILES = $(top_builddir)/doc/cookbook/html/*.html
+CSS_FILES = $(top_builddir)/doc/cookbook/html/*.css
IMAGE_FILES = \
- images/clutter-logo.png \
- images/textures-reflection.png \
- images/actors-opacity.png \
- images/actors-opacity-container-affects-opacity.png \
- images/text-shadow.png \
- images/textures-sub-texture.png \
- images/layouts-stacking-diff-actor-sizes.png \
- images/events-pointer-motion-stacking.png \
- images/layouts-bind-constraint-stage.png \
+ $(srcdir)/images/clutter-logo.png \
+ $(srcdir)/images/textures-reflection.png \
+ $(srcdir)/images/actors-opacity.png \
+ $(srcdir)/images/actors-opacity-container-affects-opacity.png \
+ $(srcdir)/images/text-shadow.png \
+ $(srcdir)/images/textures-sub-texture.png \
+ $(srcdir)/images/layouts-stacking-diff-actor-sizes.png \
+ $(srcdir)/images/events-pointer-motion-stacking.png \
+ $(srcdir)/images/layouts-bind-constraint-stage.png \
$(NULL)
+
VIDEO_FILES = \
- videos/animations-fading-out.ogv \
- videos/animations-fading-in-then-out.ogv \
- videos/animations-rotating-x-minus-45.ogv \
- videos/animations-rotating-y-45.ogv \
- videos/animations-rotating-z-90.ogv \
- videos/animations-rotating-x-minus-180-with-y-minus-96.ogv \
- videos/animations-rotating-x-minus-180-with-z-minus-96.ogv \
- videos/animations-rotating-x-centered.ogv \
- videos/animations-rotating-y-centered.ogv \
- videos/animations-rotating-z-centered.ogv \
- videos/animations-rotating-container-reverses-direction.ogv \
- videos/textures-split-go.ogv \
- videos/events-mouse-scroll.ogv \
- videos/textures-crossfade-two-textures.ogv \
- videos/animations-complex.ogv \
- videos/animations-reuse.ogv \
- videos/animations-moving-anchors.ogv \
- videos/animations-moving-depth.ogv \
- videos/animations-looping.ogv \
+ $(srcdir)/videos/animations-fading-out.ogv \
+ $(srcdir)/videos/animations-fading-in-then-out.ogv \
+ $(srcdir)/videos/animations-path.ogv \
+ $(srcdir)/videos/animations-rotating-x-minus-45.ogv \
+ $(srcdir)/videos/animations-rotating-y-45.ogv \
+ $(srcdir)/videos/animations-rotating-z-90.ogv \
+ $(srcdir)/videos/animations-rotating-x-minus-180-with-y-minus-96.ogv \
+ $(srcdir)/videos/animations-rotating-x-minus-180-with-z-minus-96.ogv \
+ $(srcdir)/videos/animations-rotating-x-centered.ogv \
+ $(srcdir)/videos/animations-rotating-y-centered.ogv \
+ $(srcdir)/videos/animations-rotating-z-centered.ogv \
+ $(srcdir)/videos/animations-rotating-container-reverses-direction.ogv \
+ $(srcdir)/videos/textures-split-go.ogv \
+ $(srcdir)/videos/events-mouse-scroll.ogv \
+ $(srcdir)/videos/textures-crossfade-two-textures.ogv \
+ $(srcdir)/videos/animations-complex.ogv \
+ $(srcdir)/videos/animations-reuse.ogv \
+ $(srcdir)/videos/animations-moving-anchors.ogv \
+ $(srcdir)/videos/animations-moving-depth.ogv \
+ $(srcdir)/videos/animations-looping.ogv \
$(NULL)
EXTRA_DIST = \
CLEANFILES = \
pdf-build.stamp \
- html-build.stamp
+ html-build.stamp \
+ clutter-cookbook.html
pdf-build.stamp: clutter-cookbook.xml $(XML_FILES)
SP_ENCODING=XML SP_CHARSET_FIXED=YES \
cp $$file html/videos/ ; \
done \
fi && \
- cp images/* html/images/ && \
- cp examples/*.c html/examples/ && \
+ cp $(top_srcdir)/doc/cookbook/images/* html/images/ && \
+ cp $(top_srcdir)/doc/cookbook/examples/*.c html/examples/ && \
echo timestamp > $(@F)
if ENABLE_PDFS
rm -f *.stamp
uninstall-local:
+ @rm -rf $(DESTDIR)$(TARGET_DIR)
+ @rm -f $(DESTDIR)$(TARGET_DIR)/clutter-cookbook.devhelp
install-data-local:
- installfiles=`echo ./html/*`; \
- if test "$$installfiles" = './html/*'; \
+ installfiles=`echo $(top_builddir)/doc/cookbook/html/*`; \
+ if test "$$installfiles" = '$(top_builddir)/doc/cookbook/html/*'; \
then echo '-- Nothing to install' ; \
else \
$(mkinstalldirs) $(DESTDIR)$(TARGET_DIR) ; \
fi \
done; \
fi; \
- if [ -d ./images ]; \
+ if [ -d $(top_srcdir)/doc/cookbook/images ]; \
then \
$(mkinstalldirs) $(DESTDIR)$(TARGET_DIR)/images ; \
for file in `ls $(IMAGE_FILES)`; do \
fi \
done; \
fi; \
- if [ -d ./videos ] && [[ "$(VIDEO_FILES)" != "" ]] ; \
+ if [ -d $(top_srcdir)/doc/cookbook/videos ]; \
then \
$(mkinstalldirs) $(DESTDIR)$(TARGET_DIR)/videos ; \
- for file in `ls $(VIDEO_FILES)`; do \
- if [ -f $$file ]; \
- then \
- basefile=`echo $$file | sed -e 's,^.*/,,'`; \
- $(INSTALL_DATA) $$file $(DESTDIR)$(TARGET_DIR)/videos/$$basefile; \
- fi \
- done; \
+ for file in `ls $(VIDEO_FILES)`; do \
+ if [ -f $$file ]; \
+ then \
+ basefile=`echo $$file | sed -e 's,^.*/,,'`; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(TARGET_DIR)/videos/$$basefile; \
+ fi \
+ done; \
fi; \
- $(INSTALL_DATA) html/clutter-cookbook.devhelp $(DESTDIR)$(TARGET_DIR)/clutter-cookbook.devhelp
+ $(INSTALL_DATA) $(top_builddir)/doc/cookbook/html/clutter-cookbook.devhelp $(DESTDIR)$(TARGET_DIR)/clutter-cookbook.devhelp
.PHONY : doc
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-<chapter id="actors">
+<chapter id="actors"
+ xmlns:xi="http://www.w3.org/2003/XInclude">
<title>Actors</title>
<epigraph>
</section>
+ <section id="actors-composite">
+ <title>Implementing a simple custom actor</title>
+
+ <section id="actors-composite-problem">
+ <title>Problem</title>
+
+ <para>You want to implement your own <type>ClutterActor</type>;
+ for example, a very simple button widget. But you want to base it
+ on existing Clutter primitives (rectangles, text) to minimise
+ the work required.</para>
+ </section>
+
+ <section id="actors-composite-solution">
+ <title>Solution</title>
+
+ <para>Implement a custom actor composed from a <type>ClutterBox</type>
+ packed with other <type>ClutterActors</type>. The custom actor
+ provides a facade over these internal actors, simplifying
+ access to their properties and behavior.</para>
+
+ <para>In this recipe, we subclass <type>ClutterActor</type> using this
+ approach to create a very simple button widget, <type>CbButton</type>.
+ It is not a complete button implementation: see
+ <ulink url="http://git.clutter-project.org/mx/tree/mx/mx-button.c">
+ <type>MxButton</type></ulink> for a more comprehensive example
+ (and the basis for this recipe). But this recipe does cover the most
+ important parts of a <type>ClutterActor</type> implementation,
+ as well some useful <type>GObject</type>-related code.</para>
+
+ <tip>
+ <para>As Clutter is a GObject-based library, it relies
+ heavily on GObject concepts and idioms. If you are unfamiliar with
+ GObject, please read
+ <ulink url="http://library.gnome.org/devel/gobject/unstable/">the GObject
+ Reference Manual</ulink> before proceeding. You might also find
+ <ulink url="http://diuf.unifr.ch/pai/wiki/doku.php/research:projects:gobject_tutorial">this
+ tutorial</ulink> a useful introduction.</para>
+ </tip>
+
+ <para>The code for this solution is structured like standard GObject
+ C library code:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The header file <filename>cb-button.h</filename>
+ declares the class' public API (function prototypes, macros,
+ structs).</para>
+ </listitem>
+ <listitem>
+ <para>The code file <filename>cb-button.c</filename>
+ contains the class implementation.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>One more example file, <filename>actors-composite-main.c</filename>,
+ shows how to use <type>CbButton</type> in an application.</para>
+
+ <para>Each of these files is described in more detail below.</para>
+
+ <note>
+ <para>In a more realistic context, <type>CbButton</type> would
+ have some build infrastructure (for example, autotooling)
+ so it could be compiled, installed, and reused in a variety of
+ applications. However, for the purposes of cookbook examples,
+ these issues are ignored here.</para>
+
+ <para>If you <emphasis>are</emphasis> planning on building
+ your own widgets using Clutter as part of an application, or
+ to create your own library, the
+ <ulink url="http://git.clutter-project.org/mx/">Mx toolkit</ulink>
+ provides an excellent example of how to autotool your project.</para>
+ </note>
+
+ <example id="actors-composite-cb-button-h">
+ <title><filename>cb-button.h</filename>: header file</title>
+
+ <para>This defines the public API for the class, including
+ GObject type macros, class and object structures, and
+ function prototypes.</para>
+
+ <programlisting>
+<xi:include href="examples/cb-button.h" parse="text">
+<xi:fallback>a code sample should be here... but isn't</xi:fallback>
+</xi:include>
+ </programlisting>
+ </example>
+
+ <example id="actors-composite-cb-button-c">
+ <title><filename>cb-button.c</filename>: <type>ClutterActor</type>
+ and GObject implementation</title>
+
+ <para>This is the main C code file which implements both
+ the GObject and Clutter elements of <type>CbButton</type>.
+ The example below is liberally commented, and also gives some samples
+ of annotations to generate
+ <ulink url="http://www.gtk.org/gtk-doc/">gtk-docs</ulink> for the
+ widget. The
+ <link linkend="actors-composite-discussion-clutter-virtual-functions">discussion
+ section</link> comments more specifically about the Clutter-specific
+ parts of it.</para>
+
+ <programlisting>
+<xi:include href="examples/cb-button.c" parse="text">
+<xi:fallback>a code sample should be here... but isn't</xi:fallback>
+</xi:include>
+ </programlisting>
+ </example>
+
+ <example id="actors-composite-actors-composite-main-c">
+ <title><filename>actors-composite-main.c</filename>: trivial
+ application demonstrating usage of <type>CbButton</type></title>
+
+ <para>Note how any of the <type>ClutterActor</type>
+ functions (like <function>clutter_actor_set_size()</function>
+ and <function>clutter_actor_add_constraint()</function>) can
+ be applied to instances of our <type>ClutterActor</type>
+ implementation.</para>
+
+ <programlisting>
+<xi:include href="examples/actors-composite-main.c" parse="text">
+<xi:fallback>a code sample should be here... but isn't</xi:fallback>
+</xi:include>
+ </programlisting>
+ </example>
+
+ </section>
+
+ <section id="actors-composite-discussion">
+ <title>Discussion</title>
+
+ <para>The actor implemented here is based on
+ simple composition: bundling several actors together and wrapping
+ their behavior and properties. In the example here, we make use of a
+ <type>ClutterLayoutManager</type> to handle positioning of
+ the <type>ClutterText</type>; we change the background color of
+ the button by changing the color of the
+ <type>ClutterBox</type>; and we use a <type>ClutterClickAction</type>
+ to simplify implementation of a click signal.</para>
+
+ <para>You may find that this approach is appropriate if you need
+ to implement a simple rectangular actor. However, it puts some
+ constraints on the outline of the actor, making it harder to
+ use a custom outline: for example, a rectangle with rounded corners
+ or a shape which can't be approximated by a rectangle. Such cases
+ require both <function>pick()</function> and <function>paint()</function>
+ implementations using Cogl (or similar): see
+ <link linkend="actors-non-rectangular">this recipe</link>
+ for more details.</para>
+
+ <para>The composition approach may also be inappropriate where
+ you need to do a lot of custom animation and drawing; and it is
+ likely to be inappropriate for implementing a container
+ actor. See the notes on implementing a new actor in the Clutter
+ reference manual for more details of what may be required
+ in these cases.</para>
+
+ <section id="actors-composite-discussion-clutter-virtual-functions">
+ <title>Implementing <type>ClutterActor</type> virtual functions</title>
+
+ <para>While most of the <type>CbButton</type> implementation
+ revolves around GObject, there are some elements of it
+ specific to Clutter. Due to the simplicity of
+ the <type>CbButton</type> actor, the implementation of
+ these functions is fairly trivial, as explained below:</para>
+
+ <itemizedlist>
+
+ <listitem>
+
+ <formalpara>
+ <title>Object destruction:
+ <function>cb_button_destroy()</function></title>
+
+ <para><type>ClutterActor</type> subclasses based
+ on composition should implement the <function>destroy()</function>
+ virtual function. This is called on an actor when its
+ container is destroyed to clean up the resources
+ allocated to the actor; it also emits a
+ <emphasis>destroy</emphasis> signal which other code can
+ hook onto.</para>
+ </formalpara>
+
+ <para>In the case of <type>CbButton</type>, the
+ <function>destroy()</function> implementation calls
+ <function>clutter_actor_destroy()</function> on the child
+ <type>ClutterBox</type>, then sets that child to
+ <constant>NULL</constant>. Finally, it checks for a
+ <function>destroy()</function> implementation on the parent
+ class, then calls it if one exists.</para>
+
+ </listitem>
+
+ <listitem>
+
+ <formalpara>
+ <title>Size requisition:
+ <function>cb_button_get_preferred_height()</function>
+ and <function>cb_button_get_preferred_width()</function></title>
+
+ <para>During the size requisition phase, Clutter asks each
+ actor the minimum size it should be to remain useful,
+ and the maximum size it would be if unconstrained. This is done
+ by calling the <function>get_preferred_height()</function>
+ and <function>get_preferred_width()</function> functions
+ on each actor in turn.</para>
+ </formalpara>
+
+ <para>If an actor will only ever be explictly sized
+ (via <function>clutter_actor_set_size()</function>,
+ <function>clutter_actor_set_height()</function> and/or
+ <function>clutter_actor_set_width()</function>),
+ there is no need to implement the <function>get_preferred_*()</function>
+ functions. (Some actors like <type>ClutterRectangle</type>
+ work this way and require explicit sizing.)</para>
+
+ <para>However, if an actor's size should be negotiated during
+ the size requisition phase, you can implement these functions,
+ using the size of the child actors as a basis for the
+ preferred height and width. In the case of
+ <type>CbButton</type>, a preferred height and width can be
+ computed; these are based on the height and width of
+ the child <type>ClutterBox</type>, plus 20 pixels on each
+ axis. Because the size of the box is itself dependent on
+ the size of the <type>ClutterText</type> inside it, the net
+ result is that the <type>CbButton</type> preferred size
+ is the size of the text actor inside it, plus 20 pixels on each
+ axis.</para>
+
+ </listitem>
+
+ <listitem>
+
+ <formalpara>
+ <title>Allocation:
+ <function>cb_button_allocate()</function></title>
+
+ <para>The requests gathered during size requisition
+ are then negotiated by Clutter, each actor
+ receiving some allocation of the available space. At the
+ end of this process, each actor is allocated a
+ <emphasis>box</emphasis>, representing the space available
+ to it on the stage.</para>
+ </formalpara>
+
+ <para>An actor implementation is responsible for distributing
+ space from its allocation box to its children as it sees
+ fit. In the case of <type>CbButton</type>, there is only a single
+ <type>ClutterBox</type> actor which needs allocation;
+ <function>cb_button_allocate()</function> therefore
+ allocates all of the button's space to its child
+ <type>ClutterBox</type>.</para>
+
+ </listitem>
+
+ <listitem>
+
+ <formalpara>
+ <title>Painting and picking:
+ <function>cb_button_paint()</function></title>
+
+ <para>Clutter works its way through the actors on the
+ stage, following the actor hierarchy (top level
+ actors directly inside the stage first);
+ <function>clutter_actor_paint()</function>
+ is called on each actor. This, in turn, calls the actor's
+ <function>paint()</function> implementation. If the actor
+ is a container, it may iterate over its children,
+ calling <function>paint()</function> on each; the children
+ may call <function>paint()</function> on their children...;
+ and so on, until the leaves of the actor hierarchy are
+ reached.</para>
+ </formalpara>
+
+ <para>As our actor consists of a single <type>ClutterBox</type>
+ child, its <function>paint()</function> implementation simply
+ has to retrieve the reference to that <type>ClutterBox</type>
+ (from its private structure) and call
+ <function>clutter_actor_paint()</function>
+ on it. Painting of the <type>ClutterBox's</type> child
+ (the <type>ClutterText</type>) is handled by the
+ <type>ClutterBox</type>.</para>
+
+ <para>In cases where an actor is non-rectangular, you also
+ need to implement a <function>pick()</function> function.
+ (This is used to determine which actor was the recipient of
+ an event occurring within the stage.) However, because
+ the actor in this recipe is a simple rectangle, there is no
+ need to implement <function>pick()</function>.</para>
+
+ </listitem>
+
+ </itemizedlist>
+
+ </section>
+
+ </section>
+
+ </section>
+
<section id="actors-allocation-notify">
<title>Knowing when an actor's position or size changes</title>
</section>
+ <section id="animations-path">
+ <title>Animating an actor along a curved path</title>
+
+ <section>
+ <title>Problem</title>
+
+ <para>You want to animate an actor along a curved path: for
+ example, to move an actor in a circle or spiral.</para>
+ </section>
+
+ <section>
+ <title>Solution</title>
+
+ <para>Create a <type>ClutterPath</type> to describe the
+ path the actor should move along; then create a
+ <type>ClutterPathConstraint</type> based on that path:</para>
+
+ <informalexample>
+ <programlisting>
+ClutterPath *path;
+ClutterConstraint *constraint;
+
+/* create the path */
+path = clutter_path_new ();
+
+/* first node is at 30,60 */
+clutter_path_add_move_to (path, 30, 60);
+
+/* add a curve to the top-right of the stage, with control
+ * points relative to the start point at 30,60
+ */
+clutter_path_add_rel_curve_to (path,
+ 120, 180,
+ 180, 120,
+ 240, 0);
+
+/* create a constraint based on the path */
+constraint = clutter_path_constraint_new (path, 0.0);
+ </programlisting>
+ </informalexample>
+
+ <note>
+ <para>For more on the types of curve and line segment available,
+ see the <type>ClutterPath</type> API documentation.</para>
+ </note>
+
+ <para>Next, add the constraint to an actor; in this case, the
+ actor is a red rectangle:</para>
+
+ <informalexample>
+ <programlisting>
+ClutterActor *rectangle;
+ClutterActor *stage = clutter_stage_new ();
+
+/* ...set size stage, color, etc... */
+
+const ClutterColor *red_color = clutter_color_new (255, 0, 0, 255);
+
+rectangle = clutter_rectangle_new_with_color (red_color);
+clutter_actor_set_size (rectangle, 60, 60);
+
+/* add the constraint to the rectangle; note that this
+ * puts the rectangle at the start of the path, i.e. at position 30,60;
+ * we also give the constraint a name, so we can use it from an implicit
+ * animation
+ */
+clutter_actor_add_constraint_with_name (rectangle, "path", constraint);
+
+/* add the rectangle to the stage */
+clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle);
+ </programlisting>
+ </informalexample>
+
+ <para>Note how the constraint has to be assigned a name (here, "path")
+ to make it accessible via implicit animations.</para>
+
+ <para>Finally, animate the constraint's <varname>offset</varname>
+ property; which in turn moves the actor along the path:</para>
+
+ <informalexample>
+ <programlisting>
+ClutterTimeline *timeline;
+
+/* create a timeline with 1000 milliseconds duration, which loops
+ * indefinitely and reverses its direction each time it completes
+ */
+timeline = clutter_timeline_new (1000);
+clutter_timeline_set_loop (timeline, TRUE);
+clutter_timeline_set_auto_reverse (timeline, TRUE);
+
+/* animate the offset property on the constraint from 0.0 to 1.0;
+ * note the syntax used to refer to the constraints metadata for the
+ * rectangle actor:
+ *
+ * "@constraints.<constraint name>.<property>"
+ */
+clutter_actor_animate_with_timeline (rectangle, CLUTTER_LINEAR, timeline,
+ "@constraints.path.offset", 1.0,
+ NULL);
+
+/* ...show the stage, run the mainloop, free memory on exit... */
+ </programlisting>
+ </informalexample>
+
+ <para>The <link linkend="animations-path-example-1">full
+ example</link> shows how these fragments fit together.
+ The animation produced by this example looks
+ like this:</para>
+
+ <inlinemediaobject>
+ <videoobject>
+ <videodata fileref="videos/animations-path.ogv"/>
+ </videoobject>
+ <alt>
+ <para>Video showing animation of an actor along a curved
+ path using <type>ClutterPathConstraint</type></para>
+ </alt>
+ </inlinemediaobject>
+
+ <para>The <link linkend="animations-path-example-2">second full
+ example</link> animates an actor around a simulated circle
+ using a more complex <type>ClutterPath</type>.</para>
+
+ </section>
+
+ <section>
+ <title>Discussion</title>
+
+ <para>Animating an actor using <type>ClutterPathConstraint</type>
+ is the recommended way to animate actors along curved paths. It
+ replaces the older <type>ClutterBehaviourPath</type>.</para>
+
+ <para>A <type>ClutterPathConstraint</type> constrains an
+ actor's <varname>x</varname> and <varname>y</varname> properties
+ to a position along such a <type>ClutterPath</type>: a path through
+ 2D space. The <type>ClutterPath</type> itself is composed of nodes
+ (x,y positions in 2D space), connected by straight lines or (cubic)
+ <ulink url="http://en.wikipedia.org/wiki/B%C3%A9zier_curve">Bézier
+ curves</ulink>.</para>
+
+ <note>
+ <para><type>ClutterPath</type> doesn't have to be used in animations:
+ it can also be used in drawing (see the
+ <link linkend="actors-non-rectangular">non-rectangular actor
+ recipe</link>).</para>
+ </note>
+
+ <para>The actor's position along the path is determined by the constraint's
+ <varname>offset</varname> property, which has a
+ value between 0.0 and 1.0. When the offset is 0.0, the actor
+ is at the beginning of the path; when the actor is at 1.0, the
+ actor is at the end of the path. Between 0.0 and 1.0, the actor
+ is some fraction of the way along the path.</para>
+
+ <para>If you immediately set the <varname>offset</varname> for the
+ constraint (e.g. to <code>0.5</code>), the actor is instantly placed
+ at that position along the path: for <code>offset = 0.5</code>,
+ at the halfway point.</para>
+
+ <para>By contrast, to animate an actor along a path, you
+ <emphasis>animate</emphasis> the offset property of a
+ <type>ClutterPathConstraint</type>. The actor's position
+ along the path is dependent on the progress of the animation:
+ when the animation starts, the actor is at the beginning of the path;
+ by the end of the animation, it will have reached its end.</para>
+
+ <para>If you animate the constraint using a linear easing mode,
+ the progress of the animation matches progress along the path: at
+ half-way through the animation, the actor will be half-way along
+ the path.</para>
+
+ <para>However, if you are using a non-linear easing mode
+ (e.g. a quintic or cubic mode), the offset along the path and
+ progress through the animation may differ. This is because the
+ offset along the path is computed from the alpha value at that
+ point in the animation; this in turn depends on the alpha function
+ applied by the animation. (See the
+ <link linkend="animations-introduction">animations introduction</link>
+ for more details about alphas.)</para>
+
+ <para>One way to think about this is to imagine the actor
+ making a journey along the path. The alpha function governs the
+ actor's speed, including how it speeds up and slows down
+ during its journey. The actor's speed may be constant
+ (as in a linear easing mode). Alternatively, the actor's speed
+ may not be constant: it might start out fast then slow down
+ (ease out); or start slow and speed up (ease in); or start and
+ end fast, but slow down in the middle (ease in and ease out); or
+ some other more complex arrangement (as in the bounce and elastic
+ easing modes). So where the actor is on the path at a particular
+ time doesn't directly relate to how long it's been travelling:
+ the position is determined both by how long it's been travelling,
+ and changes in its speed throughout the journey.</para>
+
+ <section>
+ <title>Other ways to animate along a path</title>
+
+ <para><type>ClutterPathConstraint</type> is the only
+ decent way of animating along curves in a predictable
+ and manageable fashion. It can also be used to animate along
+ paths composed of straight lines, though this isn't essential: you
+ can do straight line animations directly with <type>ClutterAnimator</type>,
+ <type>ClutterState</type> or implicit animations. But if
+ you need to animate between more than a half a dozen sets of
+ points joined by straight lines, <type>ClutterPathConstraint</type>
+ makes sense then too.</para>
+
+ <para>It is also possible to animate actors over very simple, non-Bézier
+ curves without using <type>ClutterPathConstraint</type>. This
+ can be done by animating the actor's position properties using
+ a non-linear easing mode (see the <type>ClutterAlpha</type>
+ documentation for available modes, or write your own custom
+ alpha function). <link linkend="animations-path-example-3">This
+ example</link> shows how to animate two actors on
+ curved paths around each other without
+ <type>ClutterPathConstraint</type>.</para>
+
+ <para>However, it is difficult to precisely calculate paths
+ with this approach. It is also only practical where you have a
+ very simple curve: if you want to chain together several curved
+ motions (as in the <link linkend="animations-path-example-2">circle
+ example</link>), this quickly becomes unwieldy.</para>
+
+ <tip>
+ <para>
+ If you want physics-based animation, look at
+ <ulink url="http://git.clutter-project.org/clutter-box2d/">clutter-box2d</ulink>.
+ </para>
+ </tip>
+
+ </section>
+
+ </section>
+
+ <section id="animations-path-examples">
+ <title>Full examples</title>
+
+ <example id="animations-path-example-1">
+ <title>Using a <type>ClutterPathConstraint</type> with
+ implicit animations to move an actor along a curved path</title>
+ <programlisting>
+<xi:include href="examples/animations-path.c" parse="text">
+ <xi:fallback>a code sample should be here... but isn't</xi:fallback>
+</xi:include>
+ </programlisting>
+ </example>
+
+ <example id="animations-path-example-2">
+ <title>Using a <type>ClutterPathConstraint</type> with
+ <type>ClutterAnimator</type> to animate an actor on
+ a simulated circular path</title>
+ <programlisting>
+<xi:include href="examples/animations-path-circle.c" parse="text">
+ <xi:fallback>a code sample should be here... but isn't</xi:fallback>
+</xi:include>
+ </programlisting>
+ </example>
+
+ <example id="animations-path-example-3">
+ <title>Animating actors on curved paths using easing modes</title>
+ <programlisting>
+<xi:include href="examples/animations-path-easing.c" parse="text">
+ <xi:fallback>a code sample should be here... but isn't</xi:fallback>
+</xi:include>
+ </programlisting>
+ </example>
+
+ </section>
+
+ </section>
+
</chapter>
NULL =
noinst_PROGRAMS = \
- animations-complex \
- animations-looping-animator \
- animations-looping-implicit \
- animations-looping-state \
- animations-moving-animator \
- animations-moving-implicit \
- animations-moving-state \
- animations-reuse \
- animations-rotating \
- animations-scaling \
- animations-scaling-zoom \
- text-shadow \
- textures-reflection \
- textures-split-go \
- textures-sub-texture \
+ actors-composite-main \
+ animations-complex \
+ animations-looping-animator \
+ animations-looping-implicit \
+ animations-looping-state \
+ animations-moving-animator \
+ animations-moving-implicit \
+ animations-moving-state \
+ animations-path \
+ animations-path-circle \
+ animations-path-easing \
+ animations-reuse \
+ animations-rotating \
+ animations-scaling \
+ animations-scaling-zoom \
+ text-shadow \
+ textures-reflection \
+ textures-split-go \
+ textures-sub-texture \
layouts-bind-constraint-allocation \
- layouts-bind-constraint-overlay \
- layouts-bind-constraint-stage \
- layouts-box \
- layouts-box-menu \
- layouts-box-property-effects \
- layouts-stacking \
+ layouts-bind-constraint-overlay \
+ layouts-bind-constraint-stage \
+ layouts-box \
+ layouts-box-menu \
+ layouts-box-property-effects \
+ layouts-stacking \
layouts-stacking-diff-sized-actors \
- events-mouse-scroll \
- events-pointer-motion \
- events-pointer-motion-crossing \
- events-pointer-motion-stacked \
- events-pointer-motion-scribbler \
- textures-crossfade \
- textures-crossfade-cogl \
- textures-crossfade-slideshow \
- script-ui \
- script-signals \
- events-buttons \
- events-buttons-click \
- events-buttons-lasso \
+ events-mouse-scroll \
+ events-pointer-motion \
+ events-pointer-motion-crossing \
+ events-pointer-motion-stacked \
+ events-pointer-motion-scribbler \
+ textures-crossfade \
+ textures-crossfade-cogl \
+ textures-crossfade-slideshow \
+ script-ui \
+ script-signals \
+ events-buttons \
+ events-buttons-click \
+ events-buttons-lasso \
$(NULL)
INCLUDES = \
AM_LDFLAGS = $(CLUTTER_LIBS) -export-dynamic
+actors_composite_main_SOURCES = cb-button.c cb-button.h actors-composite-main.c
animations_complex_SOURCES = animations-complex.c
animations_looping_animator_SOURCES = animations-looping-animator.c
animations_looping_implicit_SOURCES = animations-looping-implicit.c
animations_moving_animator_SOURCES = animations-moving-animator.c
animations_moving_implicit_SOURCES = animations-moving-implicit.c
animations_moving_state_SOURCES = animations-moving-state.c
+animations_path_SOURCES = animations-path.c
+animations_path_circle_SOURCES = animations-path-circle.c
+animations_path_easing_SOURCES = animations-path-easing.c
animations_reuse_SOURCES = animations-reuse.c
animations_rotating_SOURCES = animations-rotating.c
animations_scaling_SOURCES = animations-scaling.c
--- /dev/null
+#include <stdlib.h>
+#include "cb-button.h"
+
+/* colors */
+static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
+static const ClutterColor white_color = { 0xff, 0xff, 0xff, 0xff };
+static const ClutterColor yellow_color = { 0x88, 0x88, 0x00, 0xff };
+
+/* click handler */
+static void
+clicked (CbButton *button,
+ gpointer data)
+{
+ const gchar *current_text;
+
+ g_debug ("Clicked");
+
+ current_text = cb_button_get_text (button);
+
+ if (g_strcmp0 (current_text, "hello") == 0)
+ cb_button_set_text (button, "world");
+ else
+ cb_button_set_text (button, "hello");
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ ClutterActor *stage;
+ ClutterActor *button;
+ ClutterConstraint *align_x_constraint;
+ ClutterConstraint *align_y_constraint;
+
+ clutter_init (&argc, &argv);
+
+ stage = clutter_stage_new ();
+ clutter_actor_set_size (stage, 400, 400);
+ clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
+ g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
+
+ button = cb_button_new ();
+ cb_button_set_text (CB_BUTTON (button), "hello");
+
+ /* the following is equivalent to the two lines above:
+ *
+ * button = g_object_new (CB_TYPE_BUTTON,
+ * "text", "winkle",
+ * NULL);
+ *
+ * because we defined a set_property function, which can accept
+ * a PROP_TEXT parameter, GObject can create a button and set one
+ * or more properties with a single call to g_object_new()
+ */
+
+ /* note that the size of the button is left to Clutter's size requisition */
+ cb_button_set_text_color (CB_BUTTON (button), &white_color);
+ cb_button_set_background_color (CB_BUTTON (button), &yellow_color);
+ g_signal_connect (button, "clicked", G_CALLBACK (clicked), NULL);
+
+ align_x_constraint = clutter_align_constraint_new (stage,
+ CLUTTER_ALIGN_X_AXIS,
+ 0.5);
+
+ align_y_constraint = clutter_align_constraint_new (stage,
+ CLUTTER_ALIGN_Y_AXIS,
+ 0.5);
+
+ clutter_actor_add_constraint (button, align_x_constraint);
+ clutter_actor_add_constraint (button, align_y_constraint);
+
+ clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
+
+ clutter_actor_show (stage);
+
+ clutter_main ();
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#include <stdlib.h>
+#include <clutter/clutter.h>
+
+#define STAGE_SIDE 400.0
+
+static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
+static const ClutterColor red_color = { 0xff, 0x00, 0x00, 0xff };
+
+/* Build a "circular" path out of 4 Bezier curves
+ *
+ * code modified from
+ * http://git.clutter-project.org/dax/tree/dax/dax-traverser-clutter.c#n328
+ *
+ * see http://www.whizkidtech.redprince.net/bezier/circle/
+ * for further explanation
+ */
+static ClutterPath *
+build_circular_path (gfloat cx,
+ gfloat cy,
+ gfloat r)
+{
+ ClutterPath *path;
+ static gfloat kappa = 4 * (G_SQRT2 - 1) / 3;
+
+ path = clutter_path_new ();
+
+ clutter_path_add_move_to (path, cx + r, cy);
+ clutter_path_add_curve_to (path,
+ cx + r, cy + r * kappa,
+ cx + r * kappa, cy + r,
+ cx, cy + r);
+ clutter_path_add_curve_to (path,
+ cx - r * kappa, cy + r,
+ cx - r, cy + r * kappa,
+ cx - r, cy);
+ clutter_path_add_curve_to (path,
+ cx - r, cy - r * kappa,
+ cx - r * kappa, cy - r,
+ cx, cy - r);
+ clutter_path_add_curve_to (path,
+ cx + r * kappa, cy - r,
+ cx + r, cy - r * kappa,
+ cx + r, cy);
+ clutter_path_add_close (path);
+
+ return path;
+}
+
+static gboolean
+key_pressed_cb (ClutterActor *actor,
+ ClutterEvent *event,
+ gpointer user_data)
+{
+ ClutterTimeline *timeline = CLUTTER_TIMELINE (user_data);
+
+ if (!clutter_timeline_is_playing (timeline))
+ clutter_timeline_start (timeline);
+
+ return TRUE;
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ ClutterPath *path;
+ ClutterConstraint *constraint;
+ ClutterAnimator *animator;
+ ClutterTimeline *timeline;
+ ClutterActor *stage;
+ ClutterActor *rectangle;
+
+ clutter_init (&argc, &argv);
+
+ stage = clutter_stage_new ();
+ clutter_actor_set_size (stage, STAGE_SIDE, STAGE_SIDE);
+ clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
+ g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
+
+ rectangle = clutter_rectangle_new_with_color (&red_color);
+ clutter_actor_set_size (rectangle, STAGE_SIDE / 8, STAGE_SIDE / 8);
+ clutter_actor_set_position (rectangle,
+ STAGE_SIDE / 2,
+ STAGE_SIDE / 2);
+
+ clutter_container_add_actor (CLUTTER_CONTAINER (stage),
+ rectangle);
+
+ /* set up a path and make a constraint with it */
+ path = build_circular_path (STAGE_SIDE / 2,
+ STAGE_SIDE / 2,
+ STAGE_SIDE / 4);
+ constraint = clutter_path_constraint_new (path, 0.0);
+
+ /* apply the constraint to the rectangle; note that there
+ * is no need to name the constraint, as we will be animating
+ * the constraint's offset property directly using ClutterAnimator
+ */
+ clutter_actor_add_constraint (rectangle, constraint);
+
+ /* animation to animate the path offset */
+ animator = clutter_animator_new ();
+ clutter_animator_set_duration (animator, 5000);
+
+ /* use ClutterAnimator to animate the constraint directly */
+ clutter_animator_set (animator,
+ constraint, "offset", CLUTTER_LINEAR, 0.0, 0.0,
+ constraint, "offset", CLUTTER_LINEAR, 1.0, 1.0,
+ NULL);
+
+ timeline = clutter_animator_get_timeline (animator);
+ clutter_timeline_set_loop (timeline, TRUE);
+ clutter_timeline_set_auto_reverse (timeline, TRUE);
+
+ g_signal_connect (stage,
+ "key-press-event",
+ G_CALLBACK (key_pressed_cb),
+ timeline);
+
+ clutter_actor_show (stage);
+
+ clutter_main ();
+
+ /* clean up */
+ g_object_unref (animator);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#include <stdlib.h>
+#include <clutter/clutter.h>
+
+typedef struct {
+ ClutterActor *red;
+ ClutterActor *green;
+ ClutterTimeline *timeline;
+} State;
+
+static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
+static const ClutterColor red_color = { 0xff, 0x00, 0x00, 0xff };
+static const ClutterColor green_color = { 0x00, 0xff, 0x00, 0xff };
+
+static void
+reverse_timeline (ClutterTimeline *timeline)
+{
+ ClutterTimelineDirection dir = clutter_timeline_get_direction (timeline);
+
+ if (dir == CLUTTER_TIMELINE_FORWARD)
+ dir = CLUTTER_TIMELINE_BACKWARD;
+ else
+ dir = CLUTTER_TIMELINE_FORWARD;
+
+ clutter_timeline_set_direction (timeline, dir);
+}
+
+/* a key press either starts the timeline or reverses it */
+static gboolean
+key_pressed_cb (ClutterActor *actor,
+ ClutterEvent *event,
+ gpointer user_data)
+{
+ State *state = (State *) user_data;
+
+ if (clutter_timeline_is_playing (state->timeline))
+ reverse_timeline (state->timeline);
+ else
+ clutter_timeline_start (state->timeline);
+
+ return TRUE;
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ State *state = g_new0 (State, 1);
+
+ ClutterActor *stage;
+ ClutterAnimator *animator;
+
+ clutter_init (&argc, &argv);
+
+ stage = clutter_stage_new ();
+ clutter_actor_set_size (stage, 400, 400);
+ clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
+ g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
+
+ state->red = clutter_rectangle_new_with_color (&red_color);
+ clutter_actor_set_size (state->red, 100, 100);
+ clutter_actor_set_position (state->red, 300, 300);
+
+ state->green = clutter_rectangle_new_with_color (&green_color);
+ clutter_actor_set_size (state->green, 100, 100);
+ clutter_actor_set_position (state->green, 0, 0);
+
+ animator = clutter_animator_new ();
+ clutter_animator_set_duration (animator, 1000);
+
+ clutter_animator_set (animator,
+ state->red, "x", CLUTTER_LINEAR, 0.0, 300.0,
+ state->red, "y", CLUTTER_LINEAR, 0.0, 300.0,
+ state->red, "x", CLUTTER_LINEAR, 1.0, 0.0,
+ state->red, "y", CLUTTER_EASE_IN_QUINT, 1.0, 0.0,
+ NULL);
+
+ clutter_animator_set (animator,
+ state->green, "x", CLUTTER_LINEAR, 0.0, 0.0,
+ state->green, "y", CLUTTER_LINEAR, 0.0, 0.0,
+ state->green, "x", CLUTTER_LINEAR, 1.0, 300.0,
+ state->green, "y", CLUTTER_EASE_IN_QUINT, 1.0, 300.0,
+ NULL);
+
+ state->timeline = clutter_animator_get_timeline (animator);
+
+ clutter_timeline_set_auto_reverse (state->timeline, TRUE);
+
+ g_signal_connect (stage,
+ "key-press-event",
+ G_CALLBACK (key_pressed_cb),
+ state);
+
+ clutter_container_add (CLUTTER_CONTAINER (stage), state->red, state->green, NULL);
+
+ clutter_actor_show (stage);
+
+ clutter_main ();
+
+ g_object_unref (animator);
+
+ g_free (state);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#include <stdlib.h>
+#include <clutter/clutter.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ ClutterActor *stage;
+ ClutterPath *path;
+ ClutterConstraint *constraint;
+ ClutterActor *rectangle;
+ ClutterTimeline *timeline;
+
+ const ClutterColor *stage_color = clutter_color_new (51, 51, 85, 255);
+ const ClutterColor *red_color = clutter_color_new (255, 0, 0, 255);
+
+ clutter_init (&argc, &argv);
+
+ stage = clutter_stage_new ();
+ clutter_actor_set_size (stage, 360, 300);
+ clutter_stage_set_color (CLUTTER_STAGE (stage), stage_color);
+ g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
+
+ /* create the path */
+ path = clutter_path_new ();
+ clutter_path_add_move_to (path, 30, 60);
+
+ /* add a curve round to the top-right of the stage */
+ clutter_path_add_rel_curve_to (path,
+ 120, 180,
+ 180, 120,
+ 240, 0);
+
+ /* create a constraint based on the path */
+ constraint = clutter_path_constraint_new (path, 0.0);
+
+ /* put a rectangle at the start of the path */
+ rectangle = clutter_rectangle_new_with_color (red_color);
+ clutter_actor_set_size (rectangle, 60, 60);
+
+ /* add the constraint to the rectangle */
+ clutter_actor_add_constraint_with_name (rectangle, "path", constraint);
+
+ /* add the rectangle to the stage */
+ clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle);
+
+ /* set up the timeline */
+ timeline = clutter_timeline_new (1000);
+ clutter_timeline_set_loop (timeline, TRUE);
+ clutter_timeline_set_auto_reverse (timeline, TRUE);
+
+ clutter_actor_animate_with_timeline (rectangle, CLUTTER_LINEAR, timeline,
+ "@constraints.path.offset", 1.0,
+ NULL);
+
+ clutter_actor_show (stage);
+
+ clutter_main ();
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#include "cb-button.h"
+
+/**
+ * SECTION:cb-button
+ * @short_description: Button widget
+ *
+ * A button widget with support for a text label and background color.
+ */
+
+/* convenience macro for GType implementations; see:
+ * http://library.gnome.org/devel/gobject/2.27/gobject-Type-Information.html#G-DEFINE-TYPE:CAPS
+ */
+G_DEFINE_TYPE (CbButton, cb_button, CLUTTER_TYPE_ACTOR);
+
+/* macro for accessing the object's private structure */
+#define CB_BUTTON_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CB_TYPE_BUTTON, CbButtonPrivate))
+
+/* private structure - should only be accessed through the public API;
+ * this is used to store member variables whose properties
+ * need to be accessible from the implementation; for example, if we
+ * intend to create wrapper functions which modify properties on the
+ * actors composing an object, we should keep a reference to the actors
+ * here
+ *
+ * this is also the place where other state variables go:
+ * for example, you might record the current state of the button
+ * (toggled on or off) or a background image
+ */
+struct _CbButtonPrivate
+{
+ ClutterActor *child;
+ ClutterActor *label;
+ ClutterAction *click_action;
+ gchar *text;
+};
+
+/* enumerates property identifiers for this class;
+ * note that property identifiers should be non-zero integers,
+ * so we add an unused PROP_0 to occupy the 0 position in the enum
+ */
+enum {
+ PROP_0,
+ PROP_TEXT
+};
+
+/* enumerates signal identifiers for this class;
+ * LAST_SIGNAL is not used as a signal identifier, but is instead
+ * used to delineate the size of the cache array for signals (see below)
+ */
+enum {
+ CLICKED,
+ LAST_SIGNAL
+};
+
+/* cache array for signals */
+static guint cb_button_signals[LAST_SIGNAL] = { 0, };
+
+/* from http://mail.gnome.org/archives/gtk-devel-list/2004-July/msg00158.html:
+ *
+ * "The finalize method finishes releasing the remaining
+ * resources just before the object itself will be freed from memory, and
+ * therefore it will only be called once. The two step process helps break
+ * cyclic references. Both dispose and finalize must chain up to their
+ * parent objects by calling their parent's respective methods *after* they
+ * have disposed or finalized their own members."
+ */
+static void
+cb_button_finalize (GObject *gobject)
+{
+ CbButtonPrivate *priv = CB_BUTTON (gobject)->priv;
+
+ g_free (priv->text);
+
+ /* call the parent class' finalize() method */
+ G_OBJECT_CLASS (cb_button_parent_class)->finalize (gobject);
+}
+
+/* enables objects to be uniformly treated as GObjects;
+ * also exposes properties so they become scriptable, e.g.
+ * through ClutterScript
+ */
+static void
+cb_button_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CbButton *button = CB_BUTTON (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_TEXT:
+ cb_button_set_text (button, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+/* enables objects to be uniformly treated as GObjects */
+static void
+cb_button_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CbButtonPrivate *priv = CB_BUTTON (gobject)->priv;
+
+ switch (prop_id)
+ {
+ case PROP_TEXT:
+ g_value_set_string (value, priv->text);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+/* ClutterActor implementation
+ *
+ * we only implement destroy(), get_preferred_height(), get_preferred_width(),
+ * allocate(), and paint(), as this is the minimum we can get away with
+ */
+
+/* composite actors should implement destroy(), and inside their
+ * implementation destroy any actors they are composed from;
+ * in this case, we just destroy the child ClutterBox
+ */
+static void
+cb_button_destroy (ClutterActor *self)
+{
+ CbButtonPrivate *priv = CB_BUTTON (self)->priv;
+
+ /* we just destroy the child, and let the child
+ * deal with destroying _its_ children; note that we have a guard
+ * here in case the child has already been destroyed
+ */
+ if (priv->child)
+ {
+ clutter_actor_destroy (priv->child);
+ priv->child = NULL;
+ }
+
+ /* chain up to destroy() on the parent ClutterActorClass;
+ * note that we check the parent class has a destroy() implementation
+ * before calling it
+ */
+ if (CLUTTER_ACTOR_CLASS (cb_button_parent_class)->destroy)
+ CLUTTER_ACTOR_CLASS (cb_button_parent_class)->destroy (self);
+}
+
+/* get_preferred_height and get_preferred_width defer to the
+ * internal ClutterBox, adding 20px padding on each axis;
+ * min_*_p is the minimum height or width the actor should occupy
+ * to be useful; natural_*_p is the height or width the actor
+ * would occupy if not constrained
+ *
+ * note that if we required explicit sizing for CbButtons
+ * (i.e. a developer must set their height and width),
+ * we wouldn't need to implement these functions
+ */
+static void
+cb_button_get_preferred_height (ClutterActor *self,
+ gfloat for_width,
+ gfloat *min_height_p,
+ gfloat *natural_height_p)
+{
+ CbButtonPrivate *priv = CB_BUTTON (self)->priv;
+
+ clutter_actor_get_preferred_height (priv->child,
+ for_width,
+ min_height_p,
+ natural_height_p);
+
+ *min_height_p += 20.0;
+ *natural_height_p += 20.0;
+}
+
+static void
+cb_button_get_preferred_width (ClutterActor *self,
+ gfloat for_height,
+ gfloat *min_width_p,
+ gfloat *natural_width_p)
+{
+ CbButtonPrivate *priv = CB_BUTTON (self)->priv;
+
+ clutter_actor_get_preferred_width (priv->child,
+ for_height,
+ min_width_p,
+ natural_width_p);
+
+ *min_width_p += 20.0;
+ *natural_width_p += 20.0;
+}
+
+/* use the actor's allocation for the ClutterBox */
+static void
+cb_button_allocate (ClutterActor *actor,
+ const ClutterActorBox *box,
+ ClutterAllocationFlags flags)
+{
+ CbButtonPrivate *priv = CB_BUTTON (actor)->priv;
+ ClutterActorBox child_box = { 0, };
+
+ /* set the allocation for the whole button */
+ CLUTTER_ACTOR_CLASS (cb_button_parent_class)->allocate (actor, box, flags);
+
+ /* make the child (the ClutterBox) fill the parent;
+ * note that this allocation box is relative to the
+ * coordinates of the whole button actor, so we can't just
+ * use the box passed into this function; instead, it
+ * is adjusted to span the whole of the actor, from its
+ * top-left corner (0,0) to its bottom-right corner
+ * (width,height)
+ */
+ child_box.x1 = 0.0;
+ child_box.y1 = 0.0;
+ child_box.x2 = clutter_actor_box_get_width (box);
+ child_box.y2 = clutter_actor_box_get_height (box);
+
+ clutter_actor_allocate (priv->child, &child_box, flags);
+}
+
+/* paint function implementation: just calls paint() on the ClutterBox */
+static void
+cb_button_paint (ClutterActor *actor)
+{
+ CbButtonPrivate *priv = CB_BUTTON (actor)->priv;
+
+ clutter_actor_paint (priv->child);
+}
+
+/* proxy ClickAction signals so they become signals from the actor */
+static void
+cb_button_clicked (ClutterClickAction *action,
+ ClutterActor *actor,
+ gpointer user_data)
+{
+ /* emit signal via the cache array */
+ g_signal_emit (actor, cb_button_signals[CLICKED], 0);
+}
+
+/* GObject class and instance initialization functions; note that
+ * these have been placed after the Clutter implementation, as
+ * they refer to the static function implementations above
+ */
+
+/* class init: attach functions to superclasses, define properties
+ * and signals
+ */
+static void
+cb_button_class_init (CbButtonClass *klass)
+{
+ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GParamSpec *pspec;
+
+ gobject_class->finalize = cb_button_finalize;
+ gobject_class->set_property = cb_button_set_property;
+ gobject_class->get_property = cb_button_get_property;
+
+ actor_class->destroy = cb_button_destroy;
+ actor_class->get_preferred_height = cb_button_get_preferred_height;
+ actor_class->get_preferred_width = cb_button_get_preferred_width;
+ actor_class->allocate = cb_button_allocate;
+ actor_class->paint = cb_button_paint;
+
+ g_type_class_add_private (klass, sizeof (CbButtonPrivate));
+
+ /**
+ * CbButton:text:
+ *
+ * The text shown on the #CbButton
+ */
+ pspec = g_param_spec_string ("text",
+ "Text",
+ "Text of the button",
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_TEXT, pspec);
+
+ /**
+ * CbButton::clicked:
+ * @button: the #CbButton that emitted the signal
+ *
+ * The ::clicked signal is emitted when the internal #ClutterClickAction
+ * associated with a #CbButton emits its own ::clicked signal
+ */
+ cb_button_signals[CLICKED] =
+ g_signal_new ("clicked",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CbButtonClass, clicked),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+/* object init: create a private structure and pack
+ * composed ClutterActors into it
+ */
+static void
+cb_button_init (CbButton *self)
+{
+ CbButtonPrivate *priv;
+ ClutterLayoutManager *layout;
+
+ priv = self->priv = CB_BUTTON_GET_PRIVATE (self);
+
+ clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
+
+ /* the only child of this actor is a ClutterBox with a
+ * ClutterBinLayout: painting and allocation of the actor basically
+ * involves painting and allocating this child box
+ */
+ layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
+ CLUTTER_BIN_ALIGNMENT_CENTER);
+
+ priv->child = clutter_box_new (layout);
+
+ /* set the parent of the ClutterBox to this instance */
+ clutter_actor_set_parent (priv->child,
+ CLUTTER_ACTOR (self));
+
+ /* add text label to the button; see the ClutterText API docs
+ * for more information about available properties
+ */
+ priv->label = g_object_new (CLUTTER_TYPE_TEXT,
+ "line-alignment", PANGO_ALIGN_CENTER,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+
+ clutter_container_add_actor (CLUTTER_CONTAINER (priv->child),
+ priv->label);
+
+ /* add a ClutterClickAction on this actor, so we can proxy its
+ * "clicked" signal into a signal from this actor
+ */
+ priv->click_action = clutter_click_action_new ();
+ clutter_actor_add_action (CLUTTER_ACTOR (self), priv->click_action);
+
+ g_signal_connect (priv->click_action,
+ "clicked",
+ G_CALLBACK (cb_button_clicked),
+ NULL);
+}
+
+/* public API */
+/* examples of public API functions which wrap functions
+ * on internal actors
+ */
+
+/**
+ * cb_button_set_text:
+ * @self: a #CbButton
+ * @text: the text to display on the button
+ *
+ * Set the text on the button
+ */
+void
+cb_button_set_text (CbButton *self,
+ const gchar *text)
+{
+ CbButtonPrivate *priv;
+
+ /* public API should check its arguments;
+ * see also g_return_val_if_fail for functions which
+ * return a value
+ */
+ g_return_if_fail (CB_IS_BUTTON (self));
+
+ priv = self->priv;
+
+ g_free (priv->text);
+
+ if (text)
+ priv->text = g_strdup (text);
+ else
+ priv->text = g_strdup ("");
+
+ /* call a function on the ClutterText inside the layout */
+ clutter_text_set_text (CLUTTER_TEXT (priv->label), priv->text);
+}
+
+/**
+ * cb_button_set_background_color:
+ * @self: a #CbButton
+ * @color: the #ClutterColor to use for the button's background
+ *
+ * Set the color of the button's background
+ */
+void
+cb_button_set_background_color (CbButton *self,
+ const ClutterColor *color)
+{
+ g_return_if_fail (CB_IS_BUTTON (self));
+
+ clutter_box_set_color (CLUTTER_BOX (self->priv->child), color);
+}
+
+/**
+ * cb_button_set_text_color:
+ * @self: a #CbButton
+ * @color: the #ClutterColor to use as the color for the button text
+ *
+ * Set the color of the text on the button
+ */
+void
+cb_button_set_text_color (CbButton *self,
+ const ClutterColor *color)
+{
+ g_return_if_fail (CB_IS_BUTTON (self));
+
+ clutter_text_set_color (CLUTTER_TEXT (self->priv->label), color);
+}
+
+/**
+ * cb_button_get_text:
+ * @self: a #CbButton
+ *
+ * Get the text displayed on the button
+ *
+ * Returns: the button's text. This must not be freed by the application.
+ */
+G_CONST_RETURN gchar *
+cb_button_get_text (CbButton *self)
+{
+ g_return_val_if_fail (CB_IS_BUTTON (self), NULL);
+
+ return self->priv->text;
+}
+
+/**
+ * cb_button_new:
+ *
+ * Creates a new #CbButton instance
+ *
+ * Returns: a new #CbButton
+ */
+ClutterActor *
+cb_button_new (void)
+{
+ return g_object_new (CB_TYPE_BUTTON, NULL);
+}
--- /dev/null
+/* inclusion guard */
+#ifndef __CB_BUTTON_H__
+#define __CB_BUTTON_H__
+
+/* include any dependencies */
+#include <clutter/clutter.h>
+
+/* GObject implementation */
+
+/* declare this function signature to remove compilation errors with -Wall;
+ * the cb_button_get_type() function is actually added via the
+ * G_DEFINE_TYPE macro in the .c file
+ */
+GType cb_button_get_type (void);
+
+/* GObject type macros */
+/* returns the class type identifier (GType) for CbButton */
+#define CB_TYPE_BUTTON (cb_button_get_type ())
+
+/* cast obj to a CbButton object structure*/
+#define CB_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CB_TYPE_BUTTON, CbButton))
+
+/* check whether obj is a CbButton */
+#define CB_IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CB_TYPE_BUTTON))
+
+/* cast klass to CbButtonClass class structure */
+#define CB_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CB_TYPE_BUTTON, CbButtonClass))
+
+/* check whether klass is a member of the CbButtonClass */
+#define CB_IS_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CB_TYPE_BUTTON))
+
+/* get the CbButtonClass structure for a CbButton obj */
+#define CB_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CB_TYPE_BUTTON, CbButtonClass))
+
+/*
+ * Private instance fields; see
+ * http://www.gotw.ca/gotw/024.htm for the rationale
+ */
+typedef struct _CbButtonPrivate CbButtonPrivate;
+typedef struct _CbButton CbButton;
+typedef struct _CbButtonClass CbButtonClass;
+
+/* object structure */
+struct _CbButton
+{
+ /*<private>*/
+ ClutterActor parent_instance;
+
+ /* structure containing private members */
+ /*<private>*/
+ CbButtonPrivate *priv;
+};
+
+/* class structure */
+struct _CbButtonClass
+{
+ /* signals */
+ void (* clicked)(CbButton *button);
+
+ /*<private>*/
+ ClutterActorClass parent_class;
+};
+
+/* public API */
+
+/* constructor - note this returns a ClutterActor instance */
+ClutterActor *cb_button_new (void);
+
+/* getter */
+G_CONST_RETURN gchar * cb_button_get_text (CbButton *self);
+
+/* setters - these are wrappers round functions
+ * which change properties of the internal actors
+ */
+void cb_button_set_text (CbButton *self,
+ const gchar *text);
+
+void cb_button_set_background_color (CbButton *self,
+ const ClutterColor *color);
+
+void cb_button_set_text_color (CbButton *self,
+ const ClutterColor *color);
+
+#endif /* __CB_BUTTON_H__ */
clutter-backend-private.h \
clutter-bezier.h \
clutter-color-static.h \
+ clutter-config.h \
clutter-debug.h \
clutter-deprecated.h \
clutter-device-manager-private.h \
clutter-enum-types.h \
+ clutter-event-translator.h \
clutter-id-pool.h \
clutter-keysyms.h \
clutter-keysyms-compat.h \
<SECTION>
<FILE>clutter-backend</FILE>
<TITLE>ClutterBackend</TITLE>
+ClutterBackend
clutter_get_default_backend
clutter_backend_set_resolution
clutter_backend_get_resolution
CLUTTER_BACKEND_GET_CLASS
CLUTTER_TYPE_BACKEND
<SUBSECTION Private>
-ClutterBackend
ClutterBackendClass
-ClutterBackendPrivate
clutter_backend_get_type
</SECTION>
clutter_event_get_source
clutter_event_get_stage
clutter_event_get_flags
+clutter_event_get_axes
<SUBSECTION>
clutter_event_get
clutter_event_get_scroll_direction
<SUBSECTION>
+clutter_event_set_device
clutter_event_get_device
clutter_event_get_device_id
clutter_event_get_device_type
+clutter_event_get_source_device
<SUBSECTION>
clutter_get_current_event_time
<FILE>clutter-input-device</FILE>
<TITLE>ClutterInputDevice</TITLE>
ClutterInputDeviceType
+ClutterInputAxis
+ClutterInputMode
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_mode
+clutter_input_device_get_has_cursor
+clutter_input_device_set_enabled
+clutter_input_device_get_enabled
+clutter_input_device_get_associated_device
+clutter_input_device_get_slave_devices
+
+<SUBSECTION>
+clutter_input_device_get_n_keys
+clutter_input_device_set_key
+clutter_input_device_get_key
+
+<SUBSECTION>
+clutter_input_device_get_n_axes
+clutter_input_device_get_axis
+clutter_input_device_get_axis_value
+
+<SUBSECTION>
clutter_input_device_get_device_coords
clutter_input_device_get_pointer_actor
clutter_input_device_get_pointer_stage
+
+<SUBSECTION>
clutter_input_device_update_from_event
<SUBSECTION Standard>
CLUTTER_INPUT_DEVICE_GET_CLASS
<SUBSECTION Private>
+ClutterInputDeviceClass
clutter_input_device_get_type
</SECTION>
CLUTTER_TYPE_BINDING_POOL
<SUBSECTION Private>
+ClutterBindingPoolClass
clutter_binding_pool_get_type
</SECTION>
clutter_bind_constraint_get_coordinate
clutter_bind_constraint_set_offset
clutter_bind_constraint_get_offset
-
<SUBSECTION Standard>
CLUTTER_TYPE_BIND_CONSTRAINT
CLUTTER_BIND_CONSTRAINT
CLUTTER_IS_BIND_CONSTRAINT
+<SUBSECTION Private>
+ClutterBindConstraintClass
clutter_bind_constraint_get_type
</SECTION>
CLUTTER_TYPE_ALIGN_CONSTRAINT
CLUTTER_ALIGN_CONSTRAINT
CLUTTER_IS_ALIGN_CONSTRAINT
+
+<SUBSECTION Private>
+ClutterAlignConstraintClass
clutter_align_constraint_get_type
</SECTION>
ClutterClickActionClass
clutter_click_action_new
clutter_click_action_get_button
+clutter_click_action_get_state
+
+<SUBSECTION>
clutter_click_action_release
<SUBSECTION Standard>
CLUTTER_BLUR_EFFECT
CLUTTER_IS_BLUR_EFFECT
<SUBSECTION Private>
+ClutterBlurEffectClass
clutter_blur_effect_get_type
</SECTION>
CLUTTER_COLORIZE_EFFECT
CLUTTER_IS_COLORIZE_EFFECT
<SUBSECTION Private>
+ClutterColorizeEffectClass
clutter_colorize_effect_get_type
</SECTION>
CLUTTER_DESATURATE_EFFECT
CLUTTER_IS_DESATURATE_EFFECT
<SUBSECTION Private>
+ClutterDesaturateEffectClass
clutter_desaturate_effect_get_type
</SECTION>
CLUTTER_PAGE_TURN_EFFECT
CLUTTER_IS_PAGE_TURN_EFFECT
<SUBSECTION Private>
+ClutterPageTurnEffectClass
clutter_page_turn_effect_get_type
</SECTION>
CLUTTER_SETTINGS
CLUTTER_IS_SETTINGS
<SUBSECTION Private>
+ClutterSettingsClass
clutter_settings_get_type
</SECTION>
CLUTTER_IS_PATH_CONSTRAINT
CLUTTER_TYPE_PATH_CONSTRAINT
<SUBSECTION Private>
+ClutterPathConstraintClass
clutter_path_constraint_get_type
</SECTION>
CLUTTER_IS_SNAP_CONSTRAINT
CLUTTER_TYPE_SNAP_CONSTRAINT
<SUBSECTION Private>
+ClutterSnapConstraintClass
clutter_snap_constraint_get_type
</SECTION>
<section id="cogl-buffer-layout-apis">
<title>Describing the layout of GPU Memory</title>
- <xi:include href="xml/cogl-vertex-attribute.xml"/>
+ <xi:include href="xml/cogl-attribute.xml"/>
<xi:include href="xml/cogl-indices.xml"/>
</section>
<xi:include href="xml/cogl-matrix.xml"/>
<xi:include href="xml/cogl-shaders.xml"/>
<xi:include href="xml/cogl-offscreen.xml"/>
+ <xi:include href="xml/cogl-bitmap.xml"/>
<xi:include href="xml/cogl-fixed.xml"/>
<xi:include href="xml/cogl-gtype.xml"/>
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: clutter 1.5.10\n"
+"Project-Id-Version: clutter 1.6.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.clutter-project.org/enter_bug.cgi?"
"product=clutter\n"
-"POT-Creation-Date: 2010-12-17 15:51+0000\n"
+"POT-Creation-Date: 2011-02-07 15:50+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
-#: clutter/clutter-actor.c:3480
+#: clutter/clutter-actor.c:3478
msgid "X coordinate"
msgstr ""
-#: clutter/clutter-actor.c:3481
+#: clutter/clutter-actor.c:3479
msgid "X coordinate of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3496
+#: clutter/clutter-actor.c:3494
msgid "Y coordinate"
msgstr ""
-#: clutter/clutter-actor.c:3497
+#: clutter/clutter-actor.c:3495
msgid "Y coordinate of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3512 clutter/clutter-behaviour-ellipse.c:475
+#: clutter/clutter-actor.c:3510 clutter/clutter-behaviour-ellipse.c:474
msgid "Width"
msgstr ""
-#: clutter/clutter-actor.c:3513
+#: clutter/clutter-actor.c:3511
msgid "Width of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3527 clutter/clutter-behaviour-ellipse.c:491
+#: clutter/clutter-actor.c:3525 clutter/clutter-behaviour-ellipse.c:490
msgid "Height"
msgstr ""
-#: clutter/clutter-actor.c:3528
+#: clutter/clutter-actor.c:3526
msgid "Height of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3546
+#: clutter/clutter-actor.c:3544
msgid "Fixed X"
msgstr ""
-#: clutter/clutter-actor.c:3547
+#: clutter/clutter-actor.c:3545
msgid "Forced X position of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3565
+#: clutter/clutter-actor.c:3563
msgid "Fixed Y"
msgstr ""
-#: clutter/clutter-actor.c:3566
+#: clutter/clutter-actor.c:3564
msgid "Forced Y position of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3582
+#: clutter/clutter-actor.c:3580
msgid "Fixed position set"
msgstr ""
-#: clutter/clutter-actor.c:3583
+#: clutter/clutter-actor.c:3581
msgid "Whether to use fixed positioning for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3605
+#: clutter/clutter-actor.c:3603
msgid "Min Width"
msgstr ""
-#: clutter/clutter-actor.c:3606
+#: clutter/clutter-actor.c:3604
msgid "Forced minimum width request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3625
+#: clutter/clutter-actor.c:3623
msgid "Min Height"
msgstr ""
-#: clutter/clutter-actor.c:3626
+#: clutter/clutter-actor.c:3624
msgid "Forced minimum height request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3645
+#: clutter/clutter-actor.c:3643
msgid "Natural Width"
msgstr ""
-#: clutter/clutter-actor.c:3646
+#: clutter/clutter-actor.c:3644
msgid "Forced natural width request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3665
+#: clutter/clutter-actor.c:3663
msgid "Natural Height"
msgstr ""
-#: clutter/clutter-actor.c:3666
+#: clutter/clutter-actor.c:3664
msgid "Forced natural height request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3682
+#: clutter/clutter-actor.c:3680
msgid "Minimum width set"
msgstr ""
-#: clutter/clutter-actor.c:3683
+#: clutter/clutter-actor.c:3681
msgid "Whether to use the min-width property"
msgstr ""
-#: clutter/clutter-actor.c:3698
+#: clutter/clutter-actor.c:3696
msgid "Minimum height set"
msgstr ""
-#: clutter/clutter-actor.c:3699
+#: clutter/clutter-actor.c:3697
msgid "Whether to use the min-height property"
msgstr ""
-#: clutter/clutter-actor.c:3714
+#: clutter/clutter-actor.c:3712
msgid "Natural width set"
msgstr ""
-#: clutter/clutter-actor.c:3715
+#: clutter/clutter-actor.c:3713
msgid "Whether to use the natural-width property"
msgstr ""
-#: clutter/clutter-actor.c:3732
+#: clutter/clutter-actor.c:3730
msgid "Natural height set"
msgstr ""
-#: clutter/clutter-actor.c:3733
+#: clutter/clutter-actor.c:3731
msgid "Whether to use the natural-height property"
msgstr ""
-#: clutter/clutter-actor.c:3752
+#: clutter/clutter-actor.c:3750
msgid "Allocation"
msgstr ""
-#: clutter/clutter-actor.c:3753
+#: clutter/clutter-actor.c:3751
msgid "The actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:3809
+#: clutter/clutter-actor.c:3807
msgid "Request Mode"
msgstr ""
-#: clutter/clutter-actor.c:3810
+#: clutter/clutter-actor.c:3808
msgid "The actor's request mode"
msgstr ""
-#: clutter/clutter-actor.c:3825
+#: clutter/clutter-actor.c:3823
msgid "Depth"
msgstr ""
-#: clutter/clutter-actor.c:3826
+#: clutter/clutter-actor.c:3824
msgid "Position on the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:3840
+#: clutter/clutter-actor.c:3838
msgid "Opacity"
msgstr ""
-#: clutter/clutter-actor.c:3841
+#: clutter/clutter-actor.c:3839
msgid "Opacity of an actor"
msgstr ""
-#: clutter/clutter-actor.c:3856
+#: clutter/clutter-actor.c:3854
msgid "Visible"
msgstr ""
-#: clutter/clutter-actor.c:3857
+#: clutter/clutter-actor.c:3855
msgid "Whether the actor is visible or not"
msgstr ""
-#: clutter/clutter-actor.c:3872
+#: clutter/clutter-actor.c:3870
msgid "Mapped"
msgstr ""
-#: clutter/clutter-actor.c:3873
+#: clutter/clutter-actor.c:3871
msgid "Whether the actor will be painted"
msgstr ""
-#: clutter/clutter-actor.c:3887
+#: clutter/clutter-actor.c:3885
msgid "Realized"
msgstr ""
-#: clutter/clutter-actor.c:3888
+#: clutter/clutter-actor.c:3886
msgid "Whether the actor has been realized"
msgstr ""
-#: clutter/clutter-actor.c:3904
+#: clutter/clutter-actor.c:3902
msgid "Reactive"
msgstr ""
-#: clutter/clutter-actor.c:3905
+#: clutter/clutter-actor.c:3903
msgid "Whether the actor is reactive to events"
msgstr ""
-#: clutter/clutter-actor.c:3917
+#: clutter/clutter-actor.c:3915
msgid "Has Clip"
msgstr ""
-#: clutter/clutter-actor.c:3918
+#: clutter/clutter-actor.c:3916
msgid "Whether the actor has a clip set"
msgstr ""
-#: clutter/clutter-actor.c:3933
+#: clutter/clutter-actor.c:3931
msgid "Clip"
msgstr ""
-#: clutter/clutter-actor.c:3934
+#: clutter/clutter-actor.c:3932
msgid "The clip region for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3948 clutter/clutter-actor-meta.c:205
-#: clutter/clutter-binding-pool.c:320 clutter/clutter-input-device.c:151
+#: clutter/clutter-actor.c:3946 clutter/clutter-actor-meta.c:205
+#: clutter/clutter-binding-pool.c:319 clutter/clutter-input-device.c:235
msgid "Name"
msgstr ""
-#: clutter/clutter-actor.c:3949
+#: clutter/clutter-actor.c:3947
msgid "Name of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3963
+#: clutter/clutter-actor.c:3961
msgid "Scale X"
msgstr ""
-#: clutter/clutter-actor.c:3964
+#: clutter/clutter-actor.c:3962
msgid "Scale factor on the X axis"
msgstr ""
-#: clutter/clutter-actor.c:3979
+#: clutter/clutter-actor.c:3977
msgid "Scale Y"
msgstr ""
-#: clutter/clutter-actor.c:3980
+#: clutter/clutter-actor.c:3978
msgid "Scale factor on the Y axis"
msgstr ""
-#: clutter/clutter-actor.c:3995
+#: clutter/clutter-actor.c:3993
msgid "Scale Center X"
msgstr ""
-#: clutter/clutter-actor.c:3996
+#: clutter/clutter-actor.c:3994
msgid "Horizontal scale center"
msgstr ""
-#: clutter/clutter-actor.c:4011
+#: clutter/clutter-actor.c:4009
msgid "Scale Center Y"
msgstr ""
-#: clutter/clutter-actor.c:4012
+#: clutter/clutter-actor.c:4010
msgid "Vertical scale center"
msgstr ""
-#: clutter/clutter-actor.c:4027
+#: clutter/clutter-actor.c:4025
msgid "Scale Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4028
+#: clutter/clutter-actor.c:4026
msgid "The center of scaling"
msgstr ""
-#: clutter/clutter-actor.c:4045
+#: clutter/clutter-actor.c:4043
msgid "Rotation Angle X"
msgstr ""
-#: clutter/clutter-actor.c:4046
+#: clutter/clutter-actor.c:4044
msgid "The rotation angle on the X axis"
msgstr ""
-#: clutter/clutter-actor.c:4061
+#: clutter/clutter-actor.c:4059
msgid "Rotation Angle Y"
msgstr ""
-#: clutter/clutter-actor.c:4062
+#: clutter/clutter-actor.c:4060
msgid "The rotation angle on the Y axis"
msgstr ""
-#: clutter/clutter-actor.c:4077
+#: clutter/clutter-actor.c:4075
msgid "Rotation Angle Z"
msgstr ""
-#: clutter/clutter-actor.c:4078
+#: clutter/clutter-actor.c:4076
msgid "The rotation angle on the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:4093
+#: clutter/clutter-actor.c:4091
msgid "Rotation Center X"
msgstr ""
-#: clutter/clutter-actor.c:4094
+#: clutter/clutter-actor.c:4092
msgid "The rotation center on the X axis"
msgstr ""
-#: clutter/clutter-actor.c:4110
+#: clutter/clutter-actor.c:4108
msgid "Rotation Center Y"
msgstr ""
-#: clutter/clutter-actor.c:4111
+#: clutter/clutter-actor.c:4109
msgid "The rotation center on the Y axis"
msgstr ""
-#: clutter/clutter-actor.c:4127
+#: clutter/clutter-actor.c:4125
msgid "Rotation Center Z"
msgstr ""
-#: clutter/clutter-actor.c:4128
+#: clutter/clutter-actor.c:4126
msgid "The rotation center on the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:4144
+#: clutter/clutter-actor.c:4142
msgid "Rotation Center Z Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4145
+#: clutter/clutter-actor.c:4143
msgid "Center point for rotation around the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:4163
+#: clutter/clutter-actor.c:4161
msgid "Anchor X"
msgstr ""
-#: clutter/clutter-actor.c:4164
+#: clutter/clutter-actor.c:4162
msgid "X coordinate of the anchor point"
msgstr ""
-#: clutter/clutter-actor.c:4180
+#: clutter/clutter-actor.c:4178
msgid "Anchor Y"
msgstr ""
-#: clutter/clutter-actor.c:4181
+#: clutter/clutter-actor.c:4179
msgid "Y coordinate of the anchor point"
msgstr ""
-#: clutter/clutter-actor.c:4196
+#: clutter/clutter-actor.c:4194
msgid "Anchor Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4197
+#: clutter/clutter-actor.c:4195
msgid "The anchor point as a ClutterGravity"
msgstr ""
-#: clutter/clutter-actor.c:4216
+#: clutter/clutter-actor.c:4214
msgid "Show on set parent"
msgstr ""
-#: clutter/clutter-actor.c:4217
+#: clutter/clutter-actor.c:4215
msgid "Whether the actor is shown when parented"
msgstr ""
-#: clutter/clutter-actor.c:4237
+#: clutter/clutter-actor.c:4235
msgid "Clip to Allocation"
msgstr ""
-#: clutter/clutter-actor.c:4238
+#: clutter/clutter-actor.c:4236
msgid "Sets the clip region to track the actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:4248
+#: clutter/clutter-actor.c:4246
msgid "Text Direction"
msgstr ""
-#: clutter/clutter-actor.c:4249
+#: clutter/clutter-actor.c:4247
msgid "Direction of the text"
msgstr ""
-#: clutter/clutter-actor.c:4267
+#: clutter/clutter-actor.c:4265
msgid "Has Pointer"
msgstr ""
-#: clutter/clutter-actor.c:4268
+#: clutter/clutter-actor.c:4266
msgid "Whether the actor contains the pointer of an input device"
msgstr ""
-#: clutter/clutter-actor.c:4285
+#: clutter/clutter-actor.c:4283
msgid "Actions"
msgstr ""
-#: clutter/clutter-actor.c:4286
+#: clutter/clutter-actor.c:4284
msgid "Adds an action to the actor"
msgstr ""
-#: clutter/clutter-actor.c:4300
+#: clutter/clutter-actor.c:4298
msgid "Constraints"
msgstr ""
-#: clutter/clutter-actor.c:4301
+#: clutter/clutter-actor.c:4299
msgid "Adds a constraint to the actor"
msgstr ""
msgid "The name of the meta"
msgstr ""
-#: clutter/clutter-actor-meta.c:219 clutter/clutter-shader.c:261
+#: clutter/clutter-actor-meta.c:219 clutter/clutter-input-device.c:314
+#: clutter/clutter-shader.c:295
msgid "Enabled"
msgstr ""
msgid "Whether the meta is enabled"
msgstr ""
-#: clutter/clutter-align-constraint.c:231
-#: clutter/clutter-bind-constraint.c:286 clutter/clutter-clone.c:322
+#: clutter/clutter-align-constraint.c:252
+#: clutter/clutter-bind-constraint.c:316 clutter/clutter-clone.c:322
msgid "Source"
msgstr ""
-#: clutter/clutter-align-constraint.c:232
+#: clutter/clutter-align-constraint.c:253
msgid "The source of the alignment"
msgstr ""
-#: clutter/clutter-align-constraint.c:245
+#: clutter/clutter-align-constraint.c:266
msgid "Align Axis"
msgstr ""
-#: clutter/clutter-align-constraint.c:246
+#: clutter/clutter-align-constraint.c:267
msgid "The axis to align the position to"
msgstr ""
-#: clutter/clutter-align-constraint.c:265
-#: clutter/clutter-desaturate-effect.c:309
+#: clutter/clutter-align-constraint.c:286
+#: clutter/clutter-desaturate-effect.c:307
msgid "Factor"
msgstr ""
-#: clutter/clutter-align-constraint.c:266
+#: clutter/clutter-align-constraint.c:287
msgid "The alignment factor, between 0.0 and 1.0"
msgstr ""
#: clutter/clutter-alpha.c:339 clutter/clutter-animation.c:523
-#: clutter/clutter-animator.c:1801
+#: clutter/clutter-animator.c:1802
msgid "Timeline"
msgstr ""
msgid "The mode of the animation"
msgstr ""
-#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1785
+#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1786
#: clutter/clutter-media.c:194 clutter/clutter-state.c:1282
msgid "Duration"
msgstr ""
msgid "The timeline used by the animation"
msgstr ""
-#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:299
+#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:298
msgid "Alpha"
msgstr ""
msgid "The alpha used by the animation"
msgstr ""
-#: clutter/clutter-animator.c:1786
+#: clutter/clutter-animator.c:1787
msgid "The duration of the animation"
msgstr ""
-#: clutter/clutter-animator.c:1802
+#: clutter/clutter-animator.c:1803
msgid "The timeline of the animation"
msgstr ""
-#: clutter/clutter-behaviour.c:300
+#: clutter/clutter-behaviour.c:299
msgid "Alpha Object to drive the behaviour"
msgstr ""
-#: clutter/clutter-behaviour-depth.c:175
+#: clutter/clutter-behaviour-depth.c:174
msgid "Start Depth"
msgstr ""
-#: clutter/clutter-behaviour-depth.c:176
+#: clutter/clutter-behaviour-depth.c:175
msgid "Initial depth to apply"
msgstr ""
-#: clutter/clutter-behaviour-depth.c:191
+#: clutter/clutter-behaviour-depth.c:190
msgid "End Depth"
msgstr ""
-#: clutter/clutter-behaviour-depth.c:192
+#: clutter/clutter-behaviour-depth.c:191
msgid "Final depth to apply"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-ellipse.c:394
msgid "Start Angle"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:396
-#: clutter/clutter-behaviour-rotate.c:277
+#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-rotate.c:276
msgid "Initial angle"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-ellipse.c:410
msgid "End Angle"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:412
-#: clutter/clutter-behaviour-rotate.c:295
+#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-rotate.c:294
msgid "Final angle"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:427
+#: clutter/clutter-behaviour-ellipse.c:426
msgid "Angle x tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:428
+#: clutter/clutter-behaviour-ellipse.c:427
msgid "Tilt of the ellipse around x axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:443
+#: clutter/clutter-behaviour-ellipse.c:442
msgid "Angle y tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:444
+#: clutter/clutter-behaviour-ellipse.c:443
msgid "Tilt of the ellipse around y axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:459
+#: clutter/clutter-behaviour-ellipse.c:458
msgid "Angle z tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:460
+#: clutter/clutter-behaviour-ellipse.c:459
msgid "Tilt of the ellipse around z axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:476
+#: clutter/clutter-behaviour-ellipse.c:475
msgid "Width of the ellipse"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:492
+#: clutter/clutter-behaviour-ellipse.c:491
msgid "Height of ellipse"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:507
+#: clutter/clutter-behaviour-ellipse.c:506
msgid "Center"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:508
+#: clutter/clutter-behaviour-ellipse.c:507
msgid "Center of ellipse"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:522
-#: clutter/clutter-behaviour-rotate.c:330
+#: clutter/clutter-behaviour-ellipse.c:521
+#: clutter/clutter-behaviour-rotate.c:329
msgid "Direction"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:523
-#: clutter/clutter-behaviour-rotate.c:331
+#: clutter/clutter-behaviour-ellipse.c:522
+#: clutter/clutter-behaviour-rotate.c:330
msgid "Direction of rotation"
msgstr ""
-#: clutter/clutter-behaviour-opacity.c:178
+#: clutter/clutter-behaviour-opacity.c:177
msgid "Opacity Start"
msgstr ""
-#: clutter/clutter-behaviour-opacity.c:179
+#: clutter/clutter-behaviour-opacity.c:178
msgid "Initial opacity level"
msgstr ""
-#: clutter/clutter-behaviour-opacity.c:196
+#: clutter/clutter-behaviour-opacity.c:195
msgid "Opacity End"
msgstr ""
-#: clutter/clutter-behaviour-opacity.c:197
+#: clutter/clutter-behaviour-opacity.c:196
msgid "Final opacity level"
msgstr ""
-#: clutter/clutter-behaviour-path.c:220
+#: clutter/clutter-behaviour-path.c:219
msgid "Path"
msgstr ""
-#: clutter/clutter-behaviour-path.c:221
+#: clutter/clutter-behaviour-path.c:220
msgid "The ClutterPath object representing the path to animate along"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:276
+#: clutter/clutter-behaviour-rotate.c:275
msgid "Angle Begin"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:294
+#: clutter/clutter-behaviour-rotate.c:293
msgid "Angle End"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:312
+#: clutter/clutter-behaviour-rotate.c:311
msgid "Axis"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:313
+#: clutter/clutter-behaviour-rotate.c:312
msgid "Axis of rotation"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:348
+#: clutter/clutter-behaviour-rotate.c:347
msgid "Center X"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:349
+#: clutter/clutter-behaviour-rotate.c:348
msgid "X coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:366
+#: clutter/clutter-behaviour-rotate.c:365
msgid "Center Y"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:367
+#: clutter/clutter-behaviour-rotate.c:366
msgid "Y coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:384
+#: clutter/clutter-behaviour-rotate.c:383
msgid "Center Z"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:385
+#: clutter/clutter-behaviour-rotate.c:384
msgid "Z coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:219
+#: clutter/clutter-behaviour-scale.c:218
msgid "X Start Scale"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:220
+#: clutter/clutter-behaviour-scale.c:219
msgid "Initial scale on the X axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:238
+#: clutter/clutter-behaviour-scale.c:237
msgid "X End Scale"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:239
+#: clutter/clutter-behaviour-scale.c:238
msgid "Final scale on the X axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:257
+#: clutter/clutter-behaviour-scale.c:256
msgid "Y Start Scale"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:258
+#: clutter/clutter-behaviour-scale.c:257
msgid "Initial scale on the Y axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:276
+#: clutter/clutter-behaviour-scale.c:275
msgid "Y End Scale"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:277
+#: clutter/clutter-behaviour-scale.c:276
msgid "Final scale on the Y axis"
msgstr ""
-#: clutter/clutter-bind-constraint.c:287
+#: clutter/clutter-bind-constraint.c:317
msgid "The source of the binding"
msgstr ""
-#: clutter/clutter-bind-constraint.c:300
+#: clutter/clutter-bind-constraint.c:330
msgid "Coordinate"
msgstr ""
-#: clutter/clutter-bind-constraint.c:301
+#: clutter/clutter-bind-constraint.c:331
msgid "The coordinate to bind"
msgstr ""
-#: clutter/clutter-bind-constraint.c:315
+#: clutter/clutter-bind-constraint.c:345
msgid "Offset"
msgstr ""
-#: clutter/clutter-bind-constraint.c:316
+#: clutter/clutter-bind-constraint.c:346
msgid "The offset in pixels to apply to the binding"
msgstr ""
msgid "Default vertical alignment for the actors inside the layout manager"
msgstr ""
-#: clutter/clutter-binding-pool.c:321
+#: clutter/clutter-binding-pool.c:320
msgid "The unique name of the binding pool"
msgstr ""
msgstr ""
#: clutter/clutter-box.c:514 clutter/clutter-rectangle.c:258
-#: clutter/clutter-stage.c:1307
+#: clutter/clutter-stage.c:1317
msgid "Color"
msgstr ""
msgid "The actor wrapped by this data"
msgstr ""
-#: clutter/clutter-click-action.c:283
+#: clutter/clutter-click-action.c:302
msgid "Pressed"
msgstr ""
-#: clutter/clutter-click-action.c:284
+#: clutter/clutter-click-action.c:303
msgid "Whether the clickable should be in pressed state"
msgstr ""
-#: clutter/clutter-click-action.c:297
+#: clutter/clutter-click-action.c:316
msgid "Held"
msgstr ""
-#: clutter/clutter-click-action.c:298
+#: clutter/clutter-click-action.c:317
msgid "Whether the clickable has a grab"
msgstr ""
msgid "Specifies the actor to be cloned"
msgstr ""
-#: clutter/clutter-colorize-effect.c:309
+#: clutter/clutter-colorize-effect.c:307
msgid "Tint"
msgstr ""
-#: clutter/clutter-colorize-effect.c:310
+#: clutter/clutter-colorize-effect.c:308
msgid "The tint to apply"
msgstr ""
msgid "The material to be used when painting the back of the actor"
msgstr ""
-#: clutter/clutter-desaturate-effect.c:310
+#: clutter/clutter-desaturate-effect.c:308
msgid "The desaturation factor"
msgstr ""
-#: clutter/clutter-device-manager.c:130
+#: clutter/clutter-device-manager.c:130 clutter/clutter-input-device.c:343
msgid "Backend"
msgstr ""
msgid "The ClutterBackend of the device manager"
msgstr ""
-#: clutter/clutter-drag-action.c:490
+#: clutter/clutter-drag-action.c:491
msgid "Horizontal Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:491
+#: clutter/clutter-drag-action.c:492
msgid "The horizontal amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:510
+#: clutter/clutter-drag-action.c:511
msgid "Vertical Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:511
+#: clutter/clutter-drag-action.c:512
msgid "The vertical amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:532
+#: clutter/clutter-drag-action.c:533
msgid "Drag Handle"
msgstr ""
-#: clutter/clutter-drag-action.c:533
+#: clutter/clutter-drag-action.c:534
msgid "The actor that is being dragged"
msgstr ""
-#: clutter/clutter-drag-action.c:546
+#: clutter/clutter-drag-action.c:547
msgid "Drag Axis"
msgstr ""
-#: clutter/clutter-drag-action.c:547
+#: clutter/clutter-drag-action.c:548
msgid "Constraints the dragging to an axis"
msgstr ""
msgid "Maximum height for each row"
msgstr ""
-#: clutter/clutter-input-device.c:134
+#: clutter/clutter-input-device.c:219
msgid "Id"
msgstr ""
-#: clutter/clutter-input-device.c:135
+#: clutter/clutter-input-device.c:220
msgid "Unique identifier of the device"
msgstr ""
-#: clutter/clutter-input-device.c:152
+#: clutter/clutter-input-device.c:236
msgid "The name of the device"
msgstr ""
-#: clutter/clutter-input-device.c:167
+#: clutter/clutter-input-device.c:250
msgid "Device Type"
msgstr ""
-#: clutter/clutter-input-device.c:168
+#: clutter/clutter-input-device.c:251
msgid "The type of the device"
msgstr ""
+#: clutter/clutter-input-device.c:266
+msgid "Device Manager"
+msgstr ""
+
+#: clutter/clutter-input-device.c:267
+msgid "The device manager instance"
+msgstr ""
+
+#: clutter/clutter-input-device.c:280
+msgid "Device Mode"
+msgstr ""
+
+#: clutter/clutter-input-device.c:281
+msgid "The mode of the device"
+msgstr ""
+
+#: clutter/clutter-input-device.c:295
+msgid "Has Cursor"
+msgstr ""
+
+#: clutter/clutter-input-device.c:296
+msgid "Whether the device has a cursor"
+msgstr ""
+
+#: clutter/clutter-input-device.c:315
+msgid "Whether the device is enabled"
+msgstr ""
+
+#: clutter/clutter-input-device.c:328
+msgid "Number of Axes"
+msgstr ""
+
+#: clutter/clutter-input-device.c:329
+msgid "The number of axes on the device"
+msgstr ""
+
+#: clutter/clutter-input-device.c:344
+msgid "The backend instance"
+msgstr ""
+
#: clutter/clutter-interval.c:397
msgid "Value Type"
msgstr ""
msgid "The manager that created this data"
msgstr ""
-#: clutter/clutter-main.c:756
+#: clutter/clutter-main.c:753
msgid "default:LTR"
msgstr ""
-#: clutter/clutter-main.c:1560
+#: clutter/clutter-main.c:1557
msgid "Show frames per second"
msgstr ""
-#: clutter/clutter-main.c:1562
+#: clutter/clutter-main.c:1559
msgid "Default frame rate"
msgstr ""
-#: clutter/clutter-main.c:1564
+#: clutter/clutter-main.c:1561
msgid "Make all warnings fatal"
msgstr ""
-#: clutter/clutter-main.c:1567
+#: clutter/clutter-main.c:1564
msgid "Direction for the text"
msgstr ""
-#: clutter/clutter-main.c:1570
+#: clutter/clutter-main.c:1567
msgid "Disable mipmapping on text"
msgstr ""
-#: clutter/clutter-main.c:1573
+#: clutter/clutter-main.c:1570
msgid "Use 'fuzzy' picking"
msgstr ""
-#: clutter/clutter-main.c:1576
+#: clutter/clutter-main.c:1573
msgid "Clutter debugging flags to set"
msgstr ""
-#: clutter/clutter-main.c:1578
+#: clutter/clutter-main.c:1575
msgid "Clutter debugging flags to unset"
msgstr ""
-#: clutter/clutter-main.c:1582
+#: clutter/clutter-main.c:1579
msgid "Clutter profiling flags to set"
msgstr ""
-#: clutter/clutter-main.c:1584
+#: clutter/clutter-main.c:1581
msgid "Clutter profiling flags to unset"
msgstr ""
-#: clutter/clutter-main.c:1587
+#: clutter/clutter-main.c:1584
msgid "Enable accessibility"
msgstr ""
-#: clutter/clutter-main.c:1774
+#: clutter/clutter-main.c:1771
msgid "Clutter Options"
msgstr ""
-#: clutter/clutter-main.c:1775
+#: clutter/clutter-main.c:1772
msgid "Show Clutter Options"
msgstr ""
msgid "The path of the currently parsed file"
msgstr ""
-#: clutter/clutter-shader.c:215
+#: clutter/clutter-shader.c:249
msgid "Vertex Source"
msgstr ""
-#: clutter/clutter-shader.c:216
+#: clutter/clutter-shader.c:250
msgid "Source of vertex shader"
msgstr ""
-#: clutter/clutter-shader.c:230
+#: clutter/clutter-shader.c:264
msgid "Fragment Source"
msgstr ""
-#: clutter/clutter-shader.c:231
+#: clutter/clutter-shader.c:265
msgid "Source of fragment shader"
msgstr ""
-#: clutter/clutter-shader.c:246
+#: clutter/clutter-shader.c:280
msgid "Compiled"
msgstr ""
-#: clutter/clutter-shader.c:247
+#: clutter/clutter-shader.c:281
msgid "Whether the shader is compiled and linked"
msgstr ""
-#: clutter/clutter-shader.c:262
+#: clutter/clutter-shader.c:296
msgid "Whether the shader is enabled"
msgstr ""
-#: clutter/clutter-shader.c:467
+#: clutter/clutter-shader.c:501
#, c-format
msgid "%s compilation failed: %s"
msgstr ""
-#: clutter/clutter-shader.c:468
+#: clutter/clutter-shader.c:502
msgid "Vertex shader"
msgstr ""
-#: clutter/clutter-shader.c:469
+#: clutter/clutter-shader.c:503
msgid "Fragment shader"
msgstr ""
msgid "The type of shader used"
msgstr ""
-#: clutter/clutter-stage.c:1249
+#: clutter/clutter-stage.c:1259
msgid "Fullscreen Set"
msgstr ""
-#: clutter/clutter-stage.c:1250
+#: clutter/clutter-stage.c:1260
msgid "Whether the main stage is fullscreen"
msgstr ""
-#: clutter/clutter-stage.c:1266
+#: clutter/clutter-stage.c:1276
msgid "Offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1267
+#: clutter/clutter-stage.c:1277
msgid "Whether the main stage should be rendered offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1279 clutter/clutter-text.c:2643
+#: clutter/clutter-stage.c:1289 clutter/clutter-text.c:2667
msgid "Cursor Visible"
msgstr ""
-#: clutter/clutter-stage.c:1280
+#: clutter/clutter-stage.c:1290
msgid "Whether the mouse pointer is visible on the main stage"
msgstr ""
-#: clutter/clutter-stage.c:1294
+#: clutter/clutter-stage.c:1304
msgid "User Resizable"
msgstr ""
-#: clutter/clutter-stage.c:1295
+#: clutter/clutter-stage.c:1305
msgid "Whether the stage is able to be resized via user interaction"
msgstr ""
-#: clutter/clutter-stage.c:1308
+#: clutter/clutter-stage.c:1318
msgid "The color of the stage"
msgstr ""
-#: clutter/clutter-stage.c:1322
+#: clutter/clutter-stage.c:1332
msgid "Perspective"
msgstr ""
-#: clutter/clutter-stage.c:1323
+#: clutter/clutter-stage.c:1333
msgid "Perspective projection parameters"
msgstr ""
-#: clutter/clutter-stage.c:1338
+#: clutter/clutter-stage.c:1348
msgid "Title"
msgstr ""
-#: clutter/clutter-stage.c:1339
+#: clutter/clutter-stage.c:1349
msgid "Stage Title"
msgstr ""
-#: clutter/clutter-stage.c:1354
+#: clutter/clutter-stage.c:1364
msgid "Use Fog"
msgstr ""
-#: clutter/clutter-stage.c:1355
+#: clutter/clutter-stage.c:1365
msgid "Whether to enable depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1369
+#: clutter/clutter-stage.c:1379
msgid "Fog"
msgstr ""
-#: clutter/clutter-stage.c:1370
+#: clutter/clutter-stage.c:1380
msgid "Settings for the depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1386
+#: clutter/clutter-stage.c:1396
msgid "Use Alpha"
msgstr ""
-#: clutter/clutter-stage.c:1387
+#: clutter/clutter-stage.c:1397
msgid "Whether to honour the alpha component of the stage color"
msgstr ""
-#: clutter/clutter-stage.c:1403
+#: clutter/clutter-stage.c:1413
msgid "Key Focus"
msgstr ""
-#: clutter/clutter-stage.c:1404
+#: clutter/clutter-stage.c:1414
msgid "The currently key focused actor"
msgstr ""
-#: clutter/clutter-stage.c:1420
+#: clutter/clutter-stage.c:1430
msgid "No Clear Hint"
msgstr ""
-#: clutter/clutter-stage.c:1421
+#: clutter/clutter-stage.c:1431
msgid "Whether the stage should clear its contents"
msgstr ""
+#: clutter/clutter-stage.c:1444
+msgid "Accept Focus"
+msgstr ""
+
+#: clutter/clutter-stage.c:1445
+msgid "Whether the stage should accept focus on show"
+msgstr ""
+
#: clutter/clutter-state.c:1268
msgid "State"
msgstr ""
msgid "Default transition duration"
msgstr ""
-#: clutter/clutter-text.c:2530
+#: clutter/clutter-text.c:2554
msgid "Font Name"
msgstr ""
-#: clutter/clutter-text.c:2531
+#: clutter/clutter-text.c:2555
msgid "The font to be used by the text"
msgstr ""
-#: clutter/clutter-text.c:2548
+#: clutter/clutter-text.c:2572
msgid "Font Description"
msgstr ""
-#: clutter/clutter-text.c:2549
+#: clutter/clutter-text.c:2573
msgid "The font description to be used"
msgstr ""
-#: clutter/clutter-text.c:2565
+#: clutter/clutter-text.c:2589
msgid "Text"
msgstr ""
-#: clutter/clutter-text.c:2566
+#: clutter/clutter-text.c:2590
msgid "The text to render"
msgstr ""
-#: clutter/clutter-text.c:2580
+#: clutter/clutter-text.c:2604
msgid "Font Color"
msgstr ""
-#: clutter/clutter-text.c:2581
+#: clutter/clutter-text.c:2605
msgid "Color of the font used by the text"
msgstr ""
-#: clutter/clutter-text.c:2595
+#: clutter/clutter-text.c:2619
msgid "Editable"
msgstr ""
-#: clutter/clutter-text.c:2596
+#: clutter/clutter-text.c:2620
msgid "Whether the text is editable"
msgstr ""
-#: clutter/clutter-text.c:2611
+#: clutter/clutter-text.c:2635
msgid "Selectable"
msgstr ""
-#: clutter/clutter-text.c:2612
+#: clutter/clutter-text.c:2636
msgid "Whether the text is selectable"
msgstr ""
-#: clutter/clutter-text.c:2626
+#: clutter/clutter-text.c:2650
msgid "Activatable"
msgstr ""
-#: clutter/clutter-text.c:2627
+#: clutter/clutter-text.c:2651
msgid "Whether pressing return causes the activate signal to be emitted"
msgstr ""
-#: clutter/clutter-text.c:2644
+#: clutter/clutter-text.c:2668
msgid "Whether the input cursor is visible"
msgstr ""
-#: clutter/clutter-text.c:2658 clutter/clutter-text.c:2659
+#: clutter/clutter-text.c:2682 clutter/clutter-text.c:2683
msgid "Cursor Color"
msgstr ""
-#: clutter/clutter-text.c:2673
+#: clutter/clutter-text.c:2697
msgid "Cursor Color Set"
msgstr ""
-#: clutter/clutter-text.c:2674
+#: clutter/clutter-text.c:2698
msgid "Whether the cursor color has been set"
msgstr ""
-#: clutter/clutter-text.c:2689
+#: clutter/clutter-text.c:2713
msgid "Cursor Size"
msgstr ""
-#: clutter/clutter-text.c:2690
+#: clutter/clutter-text.c:2714
msgid "The width of the cursor, in pixels"
msgstr ""
-#: clutter/clutter-text.c:2704
+#: clutter/clutter-text.c:2728
msgid "Cursor Position"
msgstr ""
-#: clutter/clutter-text.c:2705
+#: clutter/clutter-text.c:2729
msgid "The cursor position"
msgstr ""
-#: clutter/clutter-text.c:2720
+#: clutter/clutter-text.c:2744
msgid "Selection-bound"
msgstr ""
-#: clutter/clutter-text.c:2721
+#: clutter/clutter-text.c:2745
msgid "The cursor position of the other end of the selection"
msgstr ""
-#: clutter/clutter-text.c:2736 clutter/clutter-text.c:2737
+#: clutter/clutter-text.c:2760 clutter/clutter-text.c:2761
msgid "Selection Color"
msgstr ""
-#: clutter/clutter-text.c:2751
+#: clutter/clutter-text.c:2775
msgid "Selection Color Set"
msgstr ""
-#: clutter/clutter-text.c:2752
+#: clutter/clutter-text.c:2776
msgid "Whether the selection color has been set"
msgstr ""
-#: clutter/clutter-text.c:2767
+#: clutter/clutter-text.c:2791
msgid "Attributes"
msgstr ""
-#: clutter/clutter-text.c:2768
+#: clutter/clutter-text.c:2792
msgid "A list of style attributes to apply to the contents of the actor"
msgstr ""
-#: clutter/clutter-text.c:2790
+#: clutter/clutter-text.c:2814
msgid "Use markup"
msgstr ""
-#: clutter/clutter-text.c:2791
+#: clutter/clutter-text.c:2815
msgid "Whether or not the text includes Pango markup"
msgstr ""
-#: clutter/clutter-text.c:2807
+#: clutter/clutter-text.c:2831
msgid "Line wrap"
msgstr ""
-#: clutter/clutter-text.c:2808
+#: clutter/clutter-text.c:2832
msgid "If set, wrap the lines if the text becomes too wide"
msgstr ""
-#: clutter/clutter-text.c:2823
+#: clutter/clutter-text.c:2847
msgid "Line wrap mode"
msgstr ""
-#: clutter/clutter-text.c:2824
+#: clutter/clutter-text.c:2848
msgid "Control how line-wrapping is done"
msgstr ""
-#: clutter/clutter-text.c:2839
+#: clutter/clutter-text.c:2863
msgid "Ellipsize"
msgstr ""
-#: clutter/clutter-text.c:2840
+#: clutter/clutter-text.c:2864
msgid "The preferred place to ellipsize the string"
msgstr ""
-#: clutter/clutter-text.c:2856
+#: clutter/clutter-text.c:2880
msgid "Line Alignment"
msgstr ""
-#: clutter/clutter-text.c:2857
+#: clutter/clutter-text.c:2881
msgid "The preferred alignment for the string, for multi-line text"
msgstr ""
-#: clutter/clutter-text.c:2873
+#: clutter/clutter-text.c:2897
msgid "Justify"
msgstr ""
-#: clutter/clutter-text.c:2874
+#: clutter/clutter-text.c:2898
msgid "Whether the text should be justified"
msgstr ""
-#: clutter/clutter-text.c:2889
+#: clutter/clutter-text.c:2913
msgid "Password Character"
msgstr ""
-#: clutter/clutter-text.c:2890
+#: clutter/clutter-text.c:2914
msgid "If non-zero, use this character to display the actor's contents"
msgstr ""
-#: clutter/clutter-text.c:2904
+#: clutter/clutter-text.c:2928
msgid "Max Length"
msgstr ""
-#: clutter/clutter-text.c:2905
+#: clutter/clutter-text.c:2929
msgid "Maximum length of the text inside the actor"
msgstr ""
-#: clutter/clutter-text.c:2928
+#: clutter/clutter-text.c:2952
msgid "Single Line Mode"
msgstr ""
-#: clutter/clutter-text.c:2929
+#: clutter/clutter-text.c:2953
msgid "Whether the text should be a single line"
msgstr ""
msgid "Shape actor with alpha channel when picking"
msgstr ""
-#: clutter/glx/clutter-backend-glx.c:128
+#: clutter/glx/clutter-backend-glx.c:131
msgid "VBlank method to be used (none, dri or glx)"
msgstr ""
-#: clutter/x11/clutter-backend-x11.c:364
+#: clutter/x11/clutter-backend-x11.c:473
msgid "X display to use"
msgstr ""
-#: clutter/x11/clutter-backend-x11.c:370
+#: clutter/x11/clutter-backend-x11.c:479
msgid "X screen to use"
msgstr ""
-#: clutter/x11/clutter-backend-x11.c:375
+#: clutter/x11/clutter-backend-x11.c:484
msgid "Make X calls synchronous"
msgstr ""
-#: clutter/x11/clutter-backend-x11.c:382
+#: clutter/x11/clutter-backend-x11.c:491
msgid "Enable XInput support"
msgstr ""
"Project-Id-Version: clutter_1.0 1.0.8\n"
"Report-Msgid-Bugs-To: http://bugzilla.clutter-project.org/enter_bug.cgi?"
"product=clutter\n"
-"POT-Creation-Date: 2010-12-17 15:51+0000\n"
+"POT-Creation-Date: 2011-02-07 15:50+0000\n"
"PO-Revision-Date: 2009-11-24 21:04+0100\n"
"Last-Translator: Chris Leick <c.leick@vollbio.de>\n"
"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-#: clutter/clutter-actor.c:3480
+#: clutter/clutter-actor.c:3478
msgid "X coordinate"
msgstr "X-Koordinate"
-#: clutter/clutter-actor.c:3481
+#: clutter/clutter-actor.c:3479
msgid "X coordinate of the actor"
msgstr "X-Koordinate des Akteurs"
-#: clutter/clutter-actor.c:3496
+#: clutter/clutter-actor.c:3494
msgid "Y coordinate"
msgstr "Y-Koordinate"
-#: clutter/clutter-actor.c:3497
+#: clutter/clutter-actor.c:3495
msgid "Y coordinate of the actor"
msgstr "Y-Koordinate des Aktuers"
-#: clutter/clutter-actor.c:3512 clutter/clutter-behaviour-ellipse.c:475
+#: clutter/clutter-actor.c:3510 clutter/clutter-behaviour-ellipse.c:474
msgid "Width"
msgstr "Breite"
-#: clutter/clutter-actor.c:3513
+#: clutter/clutter-actor.c:3511
msgid "Width of the actor"
msgstr "Breite des Akteurs"
-#: clutter/clutter-actor.c:3527 clutter/clutter-behaviour-ellipse.c:491
+#: clutter/clutter-actor.c:3525 clutter/clutter-behaviour-ellipse.c:490
msgid "Height"
msgstr "Höhe"
-#: clutter/clutter-actor.c:3528
+#: clutter/clutter-actor.c:3526
msgid "Height of the actor"
msgstr "Höhe des Akteurs"
-#: clutter/clutter-actor.c:3546
+#: clutter/clutter-actor.c:3544
msgid "Fixed X"
msgstr "Fixiertes X"
-#: clutter/clutter-actor.c:3547
+#: clutter/clutter-actor.c:3545
msgid "Forced X position of the actor"
msgstr "Forcierte X-Position des Akteurs"
-#: clutter/clutter-actor.c:3565
+#: clutter/clutter-actor.c:3563
msgid "Fixed Y"
msgstr "Fixiertes Y"
-#: clutter/clutter-actor.c:3566
+#: clutter/clutter-actor.c:3564
msgid "Forced Y position of the actor"
msgstr "Forcierte Y-Position des Akteurs"
-#: clutter/clutter-actor.c:3582
+#: clutter/clutter-actor.c:3580
msgid "Fixed position set"
msgstr "Fixierte Position gesetzt"
-#: clutter/clutter-actor.c:3583
+#: clutter/clutter-actor.c:3581
#, fuzzy
msgid "Whether to use fixed positioning for the actor"
msgstr "Benutze fixierte Position für den Akteur"
-#: clutter/clutter-actor.c:3605
+#: clutter/clutter-actor.c:3603
msgid "Min Width"
msgstr "Minimale Breite"
-#: clutter/clutter-actor.c:3606
+#: clutter/clutter-actor.c:3604
msgid "Forced minimum width request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3625
+#: clutter/clutter-actor.c:3623
msgid "Min Height"
msgstr "Minimale Höhe"
-#: clutter/clutter-actor.c:3626
+#: clutter/clutter-actor.c:3624
msgid "Forced minimum height request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3645
+#: clutter/clutter-actor.c:3643
msgid "Natural Width"
msgstr "Natürliche Breite"
-#: clutter/clutter-actor.c:3646
+#: clutter/clutter-actor.c:3644
msgid "Forced natural width request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3665
+#: clutter/clutter-actor.c:3663
msgid "Natural Height"
msgstr "Natürliche Höhe"
-#: clutter/clutter-actor.c:3666
+#: clutter/clutter-actor.c:3664
msgid "Forced natural height request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3682
+#: clutter/clutter-actor.c:3680
msgid "Minimum width set"
msgstr "Minimale Breite gesetzt"
-#: clutter/clutter-actor.c:3683
+#: clutter/clutter-actor.c:3681
#, fuzzy
msgid "Whether to use the min-width property"
msgstr "Benutze min-width Eigenschaft"
-#: clutter/clutter-actor.c:3698
+#: clutter/clutter-actor.c:3696
msgid "Minimum height set"
msgstr "Minimale Höhe gesetzt"
-#: clutter/clutter-actor.c:3699
+#: clutter/clutter-actor.c:3697
#, fuzzy
msgid "Whether to use the min-height property"
msgstr "Benutze min-height Eigenschaft"
-#: clutter/clutter-actor.c:3714
+#: clutter/clutter-actor.c:3712
msgid "Natural width set"
msgstr "Natürliche Breite gesetzt"
-#: clutter/clutter-actor.c:3715
+#: clutter/clutter-actor.c:3713
#, fuzzy
msgid "Whether to use the natural-width property"
msgstr "Benutze natural-width Eigenschaft"
-#: clutter/clutter-actor.c:3732
+#: clutter/clutter-actor.c:3730
msgid "Natural height set"
msgstr "Natürliche Höhe gesetzt"
-#: clutter/clutter-actor.c:3733
+#: clutter/clutter-actor.c:3731
#, fuzzy
msgid "Whether to use the natural-height property"
msgstr "Benutze natural-height Eigenschaft"
-#: clutter/clutter-actor.c:3752
+#: clutter/clutter-actor.c:3750
msgid "Allocation"
msgstr ""
-#: clutter/clutter-actor.c:3753
+#: clutter/clutter-actor.c:3751
msgid "The actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:3809
+#: clutter/clutter-actor.c:3807
msgid "Request Mode"
msgstr ""
-#: clutter/clutter-actor.c:3810
+#: clutter/clutter-actor.c:3808
msgid "The actor's request mode"
msgstr ""
-#: clutter/clutter-actor.c:3825
+#: clutter/clutter-actor.c:3823
msgid "Depth"
msgstr "Tiefe"
-#: clutter/clutter-actor.c:3826
+#: clutter/clutter-actor.c:3824
msgid "Position on the Z axis"
msgstr "Position auf der Z-Achse"
-#: clutter/clutter-actor.c:3840
+#: clutter/clutter-actor.c:3838
msgid "Opacity"
msgstr "Undurchsichtigkeit"
-#: clutter/clutter-actor.c:3841
+#: clutter/clutter-actor.c:3839
msgid "Opacity of an actor"
msgstr "Undurchsichtigkeit des Akteurs"
-#: clutter/clutter-actor.c:3856
+#: clutter/clutter-actor.c:3854
msgid "Visible"
msgstr "Sichtbar"
-#: clutter/clutter-actor.c:3857
+#: clutter/clutter-actor.c:3855
msgid "Whether the actor is visible or not"
msgstr "Ob der Akteur sichtbar ist oder nicht"
-#: clutter/clutter-actor.c:3872
+#: clutter/clutter-actor.c:3870
msgid "Mapped"
msgstr ""
-#: clutter/clutter-actor.c:3873
+#: clutter/clutter-actor.c:3871
msgid "Whether the actor will be painted"
msgstr "Ob der Akteur gezeichnet wird"
-#: clutter/clutter-actor.c:3887
+#: clutter/clutter-actor.c:3885
msgid "Realized"
msgstr ""
-#: clutter/clutter-actor.c:3888
+#: clutter/clutter-actor.c:3886
msgid "Whether the actor has been realized"
msgstr ""
-#: clutter/clutter-actor.c:3904
+#: clutter/clutter-actor.c:3902
msgid "Reactive"
msgstr ""
-#: clutter/clutter-actor.c:3905
+#: clutter/clutter-actor.c:3903
msgid "Whether the actor is reactive to events"
msgstr ""
-#: clutter/clutter-actor.c:3917
+#: clutter/clutter-actor.c:3915
msgid "Has Clip"
msgstr ""
-#: clutter/clutter-actor.c:3918
+#: clutter/clutter-actor.c:3916
msgid "Whether the actor has a clip set"
msgstr ""
-#: clutter/clutter-actor.c:3933
+#: clutter/clutter-actor.c:3931
msgid "Clip"
msgstr ""
-#: clutter/clutter-actor.c:3934
+#: clutter/clutter-actor.c:3932
#, fuzzy
msgid "The clip region for the actor"
msgstr "Richtung des Textes"
-#: clutter/clutter-actor.c:3948 clutter/clutter-actor-meta.c:205
-#: clutter/clutter-binding-pool.c:320 clutter/clutter-input-device.c:151
+#: clutter/clutter-actor.c:3946 clutter/clutter-actor-meta.c:205
+#: clutter/clutter-binding-pool.c:319 clutter/clutter-input-device.c:235
msgid "Name"
msgstr "Name"
-#: clutter/clutter-actor.c:3949
+#: clutter/clutter-actor.c:3947
msgid "Name of the actor"
msgstr "Name des Akteurs"
-#: clutter/clutter-actor.c:3963
+#: clutter/clutter-actor.c:3961
#, fuzzy
msgid "Scale X"
msgstr "Skaliere X"
-#: clutter/clutter-actor.c:3964
+#: clutter/clutter-actor.c:3962
msgid "Scale factor on the X axis"
msgstr "Skalierungsfaktor auf der X-Achse"
-#: clutter/clutter-actor.c:3979
+#: clutter/clutter-actor.c:3977
#, fuzzy
msgid "Scale Y"
msgstr "Skaliere Y"
-#: clutter/clutter-actor.c:3980
+#: clutter/clutter-actor.c:3978
msgid "Scale factor on the Y axis"
msgstr "Skalierungsfaktor auf der Y-Achse"
-#: clutter/clutter-actor.c:3995
+#: clutter/clutter-actor.c:3993
msgid "Scale Center X"
msgstr "Skalierungszentrum X"
-#: clutter/clutter-actor.c:3996
+#: clutter/clutter-actor.c:3994
msgid "Horizontal scale center"
msgstr "Horizontales Skalierungszentrum"
-#: clutter/clutter-actor.c:4011
+#: clutter/clutter-actor.c:4009
msgid "Scale Center Y"
msgstr "Skalierungszentrum Y"
-#: clutter/clutter-actor.c:4012
+#: clutter/clutter-actor.c:4010
msgid "Vertical scale center"
msgstr "Vertikales Skalierungszentrum"
-#: clutter/clutter-actor.c:4027
+#: clutter/clutter-actor.c:4025
msgid "Scale Gravity"
msgstr "Skalierungsanziehungskraft"
-#: clutter/clutter-actor.c:4028
+#: clutter/clutter-actor.c:4026
msgid "The center of scaling"
msgstr "Skalierungszentrum"
-#: clutter/clutter-actor.c:4045
+#: clutter/clutter-actor.c:4043
msgid "Rotation Angle X"
msgstr "Rotationswinkel X"
-#: clutter/clutter-actor.c:4046
+#: clutter/clutter-actor.c:4044
msgid "The rotation angle on the X axis"
msgstr "Der Rotationswinkel auf der X-Achse"
-#: clutter/clutter-actor.c:4061
+#: clutter/clutter-actor.c:4059
msgid "Rotation Angle Y"
msgstr "Rotationswinkel Y"
-#: clutter/clutter-actor.c:4062
+#: clutter/clutter-actor.c:4060
msgid "The rotation angle on the Y axis"
msgstr "Der Rotationswinkel auf der Y-Achse"
-#: clutter/clutter-actor.c:4077
+#: clutter/clutter-actor.c:4075
msgid "Rotation Angle Z"
msgstr "Rotationswinkel Z"
-#: clutter/clutter-actor.c:4078
+#: clutter/clutter-actor.c:4076
msgid "The rotation angle on the Z axis"
msgstr "Der Rotationswinkel auf der Z-Achse"
-#: clutter/clutter-actor.c:4093
+#: clutter/clutter-actor.c:4091
msgid "Rotation Center X"
msgstr "Rotationszentrum X"
-#: clutter/clutter-actor.c:4094
+#: clutter/clutter-actor.c:4092
msgid "The rotation center on the X axis"
msgstr "Das Rotationszentrum auf der X-Achse"
-#: clutter/clutter-actor.c:4110
+#: clutter/clutter-actor.c:4108
msgid "Rotation Center Y"
msgstr "Rotationszentrum Y"
-#: clutter/clutter-actor.c:4111
+#: clutter/clutter-actor.c:4109
msgid "The rotation center on the Y axis"
msgstr "Das Rotationszentrum auf der Y-Achse"
-#: clutter/clutter-actor.c:4127
+#: clutter/clutter-actor.c:4125
msgid "Rotation Center Z"
msgstr "Rotationszentrum Z"
-#: clutter/clutter-actor.c:4128
+#: clutter/clutter-actor.c:4126
msgid "The rotation center on the Z axis"
msgstr "Das Rotationszentrum auf der Z-Achse"
-#: clutter/clutter-actor.c:4144
+#: clutter/clutter-actor.c:4142
#, fuzzy
msgid "Rotation Center Z Gravity"
msgstr "Rotationszentrum Z Anziehungskraft"
-#: clutter/clutter-actor.c:4145
+#: clutter/clutter-actor.c:4143
msgid "Center point for rotation around the Z axis"
msgstr "Rotationsmittelpunkt um die Z-Achse"
-#: clutter/clutter-actor.c:4163
+#: clutter/clutter-actor.c:4161
msgid "Anchor X"
msgstr "Anker X"
-#: clutter/clutter-actor.c:4164
+#: clutter/clutter-actor.c:4162
msgid "X coordinate of the anchor point"
msgstr "X-Koordinate des Ankerpunktes"
-#: clutter/clutter-actor.c:4180
+#: clutter/clutter-actor.c:4178
msgid "Anchor Y"
msgstr "Anker Y"
-#: clutter/clutter-actor.c:4181
+#: clutter/clutter-actor.c:4179
msgid "Y coordinate of the anchor point"
msgstr "Y-Koordinate des Ankerpunktes"
-#: clutter/clutter-actor.c:4196
+#: clutter/clutter-actor.c:4194
msgid "Anchor Gravity"
msgstr "Anker-Anziehungskraft"
-#: clutter/clutter-actor.c:4197
+#: clutter/clutter-actor.c:4195
msgid "The anchor point as a ClutterGravity"
msgstr ""
-#: clutter/clutter-actor.c:4216
+#: clutter/clutter-actor.c:4214
msgid "Show on set parent"
msgstr ""
-#: clutter/clutter-actor.c:4217
+#: clutter/clutter-actor.c:4215
msgid "Whether the actor is shown when parented"
msgstr ""
-#: clutter/clutter-actor.c:4237
+#: clutter/clutter-actor.c:4235
msgid "Clip to Allocation"
msgstr ""
-#: clutter/clutter-actor.c:4238
+#: clutter/clutter-actor.c:4236
msgid "Sets the clip region to track the actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:4248
+#: clutter/clutter-actor.c:4246
msgid "Text Direction"
msgstr "Textrichtung"
-#: clutter/clutter-actor.c:4249
+#: clutter/clutter-actor.c:4247
msgid "Direction of the text"
msgstr "Richtung des Textes"
-#: clutter/clutter-actor.c:4267
+#: clutter/clutter-actor.c:4265
msgid "Has Pointer"
msgstr ""
-#: clutter/clutter-actor.c:4268
+#: clutter/clutter-actor.c:4266
msgid "Whether the actor contains the pointer of an input device"
msgstr ""
-#: clutter/clutter-actor.c:4285
+#: clutter/clutter-actor.c:4283
msgid "Actions"
msgstr "Aktionen"
-#: clutter/clutter-actor.c:4286
+#: clutter/clutter-actor.c:4284
msgid "Adds an action to the actor"
msgstr "Fügt dem Akteur eine Aktion hinzu"
-#: clutter/clutter-actor.c:4300
+#: clutter/clutter-actor.c:4298
msgid "Constraints"
msgstr "Einschränkungen"
-#: clutter/clutter-actor.c:4301
+#: clutter/clutter-actor.c:4299
msgid "Adds a constraint to the actor"
msgstr "Fügt dem Akteur eine Beschränkung hinzu"
msgid "The name of the meta"
msgstr ""
-#: clutter/clutter-actor-meta.c:219 clutter/clutter-shader.c:261
+#: clutter/clutter-actor-meta.c:219 clutter/clutter-input-device.c:314
+#: clutter/clutter-shader.c:295
#, fuzzy
msgid "Enabled"
msgstr "Aktiv"
msgid "Whether the meta is enabled"
msgstr ""
-#: clutter/clutter-align-constraint.c:231
-#: clutter/clutter-bind-constraint.c:286 clutter/clutter-clone.c:322
+#: clutter/clutter-align-constraint.c:252
+#: clutter/clutter-bind-constraint.c:316 clutter/clutter-clone.c:322
msgid "Source"
msgstr "Quelle"
-#: clutter/clutter-align-constraint.c:232
+#: clutter/clutter-align-constraint.c:253
msgid "The source of the alignment"
msgstr ""
-#: clutter/clutter-align-constraint.c:245
+#: clutter/clutter-align-constraint.c:266
msgid "Align Axis"
msgstr ""
-#: clutter/clutter-align-constraint.c:246
+#: clutter/clutter-align-constraint.c:267
msgid "The axis to align the position to"
msgstr ""
-#: clutter/clutter-align-constraint.c:265
-#: clutter/clutter-desaturate-effect.c:309
+#: clutter/clutter-align-constraint.c:286
+#: clutter/clutter-desaturate-effect.c:307
msgid "Factor"
msgstr "Faktor"
-#: clutter/clutter-align-constraint.c:266
+#: clutter/clutter-align-constraint.c:287
msgid "The alignment factor, between 0.0 and 1.0"
msgstr ""
#: clutter/clutter-alpha.c:339 clutter/clutter-animation.c:523
-#: clutter/clutter-animator.c:1801
+#: clutter/clutter-animator.c:1802
msgid "Timeline"
msgstr "Zeitleiste"
msgid "The mode of the animation"
msgstr "Animationsmodus"
-#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1785
+#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1786
#: clutter/clutter-media.c:194 clutter/clutter-state.c:1282
msgid "Duration"
msgstr "Dauer"
msgid "The timeline used by the animation"
msgstr "Die von der Animation benutzte Zeitleiste"
-#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:299
+#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:298
#, fuzzy
msgid "Alpha"
msgstr "Alpha"
msgid "The alpha used by the animation"
msgstr ""
-#: clutter/clutter-animator.c:1786
+#: clutter/clutter-animator.c:1787
msgid "The duration of the animation"
msgstr "Die Dauer der Animation"
-#: clutter/clutter-animator.c:1802
+#: clutter/clutter-animator.c:1803
msgid "The timeline of the animation"
msgstr "Die Zeitleiste der Animation"
-#: clutter/clutter-behaviour.c:300
+#: clutter/clutter-behaviour.c:299
msgid "Alpha Object to drive the behaviour"
msgstr ""
-#: clutter/clutter-behaviour-depth.c:175
+#: clutter/clutter-behaviour-depth.c:174
msgid "Start Depth"
msgstr "Starttiefe"
-#: clutter/clutter-behaviour-depth.c:176
+#: clutter/clutter-behaviour-depth.c:175
msgid "Initial depth to apply"
msgstr "Anzuwendende initiale Tiefe"
-#: clutter/clutter-behaviour-depth.c:191
+#: clutter/clutter-behaviour-depth.c:190
msgid "End Depth"
msgstr "Endtiefe"
-#: clutter/clutter-behaviour-depth.c:192
+#: clutter/clutter-behaviour-depth.c:191
msgid "Final depth to apply"
msgstr "Anzuwendende finale Tiefe"
-#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-ellipse.c:394
msgid "Start Angle"
msgstr "Startwinkel"
-#: clutter/clutter-behaviour-ellipse.c:396
-#: clutter/clutter-behaviour-rotate.c:277
+#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-rotate.c:276
msgid "Initial angle"
msgstr "Initialer Winkel"
-#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-ellipse.c:410
msgid "End Angle"
msgstr "Endwinkel"
-#: clutter/clutter-behaviour-ellipse.c:412
-#: clutter/clutter-behaviour-rotate.c:295
+#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-rotate.c:294
msgid "Final angle"
msgstr "Finaler Winkel"
-#: clutter/clutter-behaviour-ellipse.c:427
+#: clutter/clutter-behaviour-ellipse.c:426
msgid "Angle x tilt"
msgstr "Winkel Neigung x"
-#: clutter/clutter-behaviour-ellipse.c:428
+#: clutter/clutter-behaviour-ellipse.c:427
msgid "Tilt of the ellipse around x axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:443
+#: clutter/clutter-behaviour-ellipse.c:442
msgid "Angle y tilt"
msgstr "Winkel Neigung y"
-#: clutter/clutter-behaviour-ellipse.c:444
+#: clutter/clutter-behaviour-ellipse.c:443
msgid "Tilt of the ellipse around y axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:459
+#: clutter/clutter-behaviour-ellipse.c:458
msgid "Angle z tilt"
msgstr "Winkel Neigung z"
-#: clutter/clutter-behaviour-ellipse.c:460
+#: clutter/clutter-behaviour-ellipse.c:459
msgid "Tilt of the ellipse around z axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:476
+#: clutter/clutter-behaviour-ellipse.c:475
msgid "Width of the ellipse"
msgstr "Breite der Ellipse"
-#: clutter/clutter-behaviour-ellipse.c:492
+#: clutter/clutter-behaviour-ellipse.c:491
msgid "Height of ellipse"
msgstr "Höhe der Ellipse"
-#: clutter/clutter-behaviour-ellipse.c:507
+#: clutter/clutter-behaviour-ellipse.c:506
#, fuzzy
msgid "Center"
msgstr "Zentrum/Mittelpunk"
-#: clutter/clutter-behaviour-ellipse.c:508
+#: clutter/clutter-behaviour-ellipse.c:507
#, fuzzy
msgid "Center of ellipse"
msgstr "Zentrum/Mittelpunkt der Ellipse"
-#: clutter/clutter-behaviour-ellipse.c:522
-#: clutter/clutter-behaviour-rotate.c:330
+#: clutter/clutter-behaviour-ellipse.c:521
+#: clutter/clutter-behaviour-rotate.c:329
msgid "Direction"
msgstr "Richtung"
-#: clutter/clutter-behaviour-ellipse.c:523
-#: clutter/clutter-behaviour-rotate.c:331
+#: clutter/clutter-behaviour-ellipse.c:522
+#: clutter/clutter-behaviour-rotate.c:330
msgid "Direction of rotation"
msgstr "Rotationsrichtung"
-#: clutter/clutter-behaviour-opacity.c:178
+#: clutter/clutter-behaviour-opacity.c:177
msgid "Opacity Start"
msgstr "Start-Deckungskraft"
-#: clutter/clutter-behaviour-opacity.c:179
+#: clutter/clutter-behaviour-opacity.c:178
msgid "Initial opacity level"
msgstr "Initialer Deckungskraftgrad"
-#: clutter/clutter-behaviour-opacity.c:196
+#: clutter/clutter-behaviour-opacity.c:195
msgid "Opacity End"
msgstr "End-Deckungskraft"
-#: clutter/clutter-behaviour-opacity.c:197
+#: clutter/clutter-behaviour-opacity.c:196
msgid "Final opacity level"
msgstr "Finaler Deckungskraftgrad"
-#: clutter/clutter-behaviour-path.c:220
+#: clutter/clutter-behaviour-path.c:219
msgid "Path"
msgstr "Pfad"
-#: clutter/clutter-behaviour-path.c:221
+#: clutter/clutter-behaviour-path.c:220
msgid "The ClutterPath object representing the path to animate along"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:276
+#: clutter/clutter-behaviour-rotate.c:275
msgid "Angle Begin"
msgstr "Winkel Anfang"
-#: clutter/clutter-behaviour-rotate.c:294
+#: clutter/clutter-behaviour-rotate.c:293
msgid "Angle End"
msgstr "Winkel Ende"
-#: clutter/clutter-behaviour-rotate.c:312
+#: clutter/clutter-behaviour-rotate.c:311
msgid "Axis"
msgstr "Achse"
-#: clutter/clutter-behaviour-rotate.c:313
+#: clutter/clutter-behaviour-rotate.c:312
msgid "Axis of rotation"
msgstr "Rotationsachse"
-#: clutter/clutter-behaviour-rotate.c:348
+#: clutter/clutter-behaviour-rotate.c:347
#, fuzzy
msgid "Center X"
msgstr "Zentrum/Mittelpunkt X"
-#: clutter/clutter-behaviour-rotate.c:349
+#: clutter/clutter-behaviour-rotate.c:348
msgid "X coordinate of the center of rotation"
msgstr "X-Koordinate des Rotationszentrums"
-#: clutter/clutter-behaviour-rotate.c:366
+#: clutter/clutter-behaviour-rotate.c:365
#, fuzzy
msgid "Center Y"
msgstr "Zentrum/Mittelpunkt Y"
-#: clutter/clutter-behaviour-rotate.c:367
+#: clutter/clutter-behaviour-rotate.c:366
msgid "Y coordinate of the center of rotation"
msgstr "Y-Koordinate des Rotationszentrums"
-#: clutter/clutter-behaviour-rotate.c:384
+#: clutter/clutter-behaviour-rotate.c:383
#, fuzzy
msgid "Center Z"
msgstr "Zentrum/Mittelpunkt Y"
-#: clutter/clutter-behaviour-rotate.c:385
+#: clutter/clutter-behaviour-rotate.c:384
msgid "Z coordinate of the center of rotation"
msgstr "Z-Koordinate des Rotationszentrums"
-#: clutter/clutter-behaviour-scale.c:219
+#: clutter/clutter-behaviour-scale.c:218
#, fuzzy
msgid "X Start Scale"
msgstr "Startskalierung X"
-#: clutter/clutter-behaviour-scale.c:220
+#: clutter/clutter-behaviour-scale.c:219
msgid "Initial scale on the X axis"
msgstr "Initiale Skalierung auf der X-Achse"
-#: clutter/clutter-behaviour-scale.c:238
+#: clutter/clutter-behaviour-scale.c:237
#, fuzzy
msgid "X End Scale"
msgstr "Endskalierung X"
-#: clutter/clutter-behaviour-scale.c:239
+#: clutter/clutter-behaviour-scale.c:238
msgid "Final scale on the X axis"
msgstr "Finale Skalierung auf der X-Achse"
-#: clutter/clutter-behaviour-scale.c:257
+#: clutter/clutter-behaviour-scale.c:256
#, fuzzy
msgid "Y Start Scale"
msgstr "Startskalierung Y"
-#: clutter/clutter-behaviour-scale.c:258
+#: clutter/clutter-behaviour-scale.c:257
msgid "Initial scale on the Y axis"
msgstr "Initiale Skalierung auf der Y-Achse"
-#: clutter/clutter-behaviour-scale.c:276
+#: clutter/clutter-behaviour-scale.c:275
#, fuzzy
msgid "Y End Scale"
msgstr "Endskalierung Y"
-#: clutter/clutter-behaviour-scale.c:277
+#: clutter/clutter-behaviour-scale.c:276
msgid "Final scale on the Y axis"
msgstr "Finale Skalierung auf der Y-Achse"
-#: clutter/clutter-bind-constraint.c:287
+#: clutter/clutter-bind-constraint.c:317
msgid "The source of the binding"
msgstr ""
-#: clutter/clutter-bind-constraint.c:300
+#: clutter/clutter-bind-constraint.c:330
msgid "Coordinate"
msgstr "Koordinate"
-#: clutter/clutter-bind-constraint.c:301
+#: clutter/clutter-bind-constraint.c:331
msgid "The coordinate to bind"
msgstr ""
-#: clutter/clutter-bind-constraint.c:315
+#: clutter/clutter-bind-constraint.c:345
msgid "Offset"
msgstr ""
-#: clutter/clutter-bind-constraint.c:316
+#: clutter/clutter-bind-constraint.c:346
msgid "The offset in pixels to apply to the binding"
msgstr ""
msgid "Default vertical alignment for the actors inside the layout manager"
msgstr ""
-#: clutter/clutter-binding-pool.c:321
+#: clutter/clutter-binding-pool.c:320
msgid "The unique name of the binding pool"
msgstr ""
msgstr ""
#: clutter/clutter-box.c:514 clutter/clutter-rectangle.c:258
-#: clutter/clutter-stage.c:1307
+#: clutter/clutter-stage.c:1317
msgid "Color"
msgstr "Farbe"
msgid "The actor wrapped by this data"
msgstr ""
-#: clutter/clutter-click-action.c:283
+#: clutter/clutter-click-action.c:302
msgid "Pressed"
msgstr ""
-#: clutter/clutter-click-action.c:284
+#: clutter/clutter-click-action.c:303
msgid "Whether the clickable should be in pressed state"
msgstr ""
-#: clutter/clutter-click-action.c:297
+#: clutter/clutter-click-action.c:316
msgid "Held"
msgstr ""
-#: clutter/clutter-click-action.c:298
+#: clutter/clutter-click-action.c:317
msgid "Whether the clickable has a grab"
msgstr ""
msgid "Specifies the actor to be cloned"
msgstr ""
-#: clutter/clutter-colorize-effect.c:309
+#: clutter/clutter-colorize-effect.c:307
msgid "Tint"
msgstr ""
-#: clutter/clutter-colorize-effect.c:310
+#: clutter/clutter-colorize-effect.c:308
msgid "The tint to apply"
msgstr ""
msgid "The material to be used when painting the back of the actor"
msgstr ""
-#: clutter/clutter-desaturate-effect.c:310
+#: clutter/clutter-desaturate-effect.c:308
msgid "The desaturation factor"
msgstr ""
-#: clutter/clutter-device-manager.c:130
+#: clutter/clutter-device-manager.c:130 clutter/clutter-input-device.c:343
msgid "Backend"
msgstr ""
msgid "The ClutterBackend of the device manager"
msgstr ""
-#: clutter/clutter-drag-action.c:490
+#: clutter/clutter-drag-action.c:491
msgid "Horizontal Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:491
+#: clutter/clutter-drag-action.c:492
msgid "The horizontal amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:510
+#: clutter/clutter-drag-action.c:511
msgid "Vertical Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:511
+#: clutter/clutter-drag-action.c:512
msgid "The vertical amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:532
+#: clutter/clutter-drag-action.c:533
msgid "Drag Handle"
msgstr ""
-#: clutter/clutter-drag-action.c:533
+#: clutter/clutter-drag-action.c:534
msgid "The actor that is being dragged"
msgstr ""
-#: clutter/clutter-drag-action.c:546
+#: clutter/clutter-drag-action.c:547
msgid "Drag Axis"
msgstr ""
-#: clutter/clutter-drag-action.c:547
+#: clutter/clutter-drag-action.c:548
msgid "Constraints the dragging to an axis"
msgstr ""
msgid "Maximum height for each row"
msgstr ""
-#: clutter/clutter-input-device.c:134
+#: clutter/clutter-input-device.c:219
msgid "Id"
msgstr ""
-#: clutter/clutter-input-device.c:135
+#: clutter/clutter-input-device.c:220
msgid "Unique identifier of the device"
msgstr ""
-#: clutter/clutter-input-device.c:152
+#: clutter/clutter-input-device.c:236
msgid "The name of the device"
msgstr ""
-#: clutter/clutter-input-device.c:167
+#: clutter/clutter-input-device.c:250
msgid "Device Type"
msgstr ""
-#: clutter/clutter-input-device.c:168
+#: clutter/clutter-input-device.c:251
msgid "The type of the device"
msgstr ""
+#: clutter/clutter-input-device.c:266
+msgid "Device Manager"
+msgstr ""
+
+#: clutter/clutter-input-device.c:267
+msgid "The device manager instance"
+msgstr ""
+
+#: clutter/clutter-input-device.c:280
+msgid "Device Mode"
+msgstr ""
+
+#: clutter/clutter-input-device.c:281
+#, fuzzy
+msgid "The mode of the device"
+msgstr "Animationsmodus"
+
+#: clutter/clutter-input-device.c:295
+msgid "Has Cursor"
+msgstr ""
+
+#: clutter/clutter-input-device.c:296
+msgid "Whether the device has a cursor"
+msgstr ""
+
+#: clutter/clutter-input-device.c:315
+#, fuzzy
+msgid "Whether the device is enabled"
+msgstr "Ob der Akteur gezeichnet wird"
+
+#: clutter/clutter-input-device.c:328
+msgid "Number of Axes"
+msgstr ""
+
+#: clutter/clutter-input-device.c:329
+msgid "The number of axes on the device"
+msgstr ""
+
+#: clutter/clutter-input-device.c:344
+msgid "The backend instance"
+msgstr ""
+
#: clutter/clutter-interval.c:397
msgid "Value Type"
msgstr ""
msgid "The manager that created this data"
msgstr ""
-#: clutter/clutter-main.c:756
+#: clutter/clutter-main.c:753
msgid "default:LTR"
msgstr "default:LTR"
-#: clutter/clutter-main.c:1560
+#: clutter/clutter-main.c:1557
msgid "Show frames per second"
msgstr "Bilder pro Sekunde anzeigen"
-#: clutter/clutter-main.c:1562
+#: clutter/clutter-main.c:1559
msgid "Default frame rate"
msgstr "Vorgabebildfrequenz"
-#: clutter/clutter-main.c:1564
+#: clutter/clutter-main.c:1561
msgid "Make all warnings fatal"
msgstr "Alle Warnungen fatal machen"
-#: clutter/clutter-main.c:1567
+#: clutter/clutter-main.c:1564
msgid "Direction for the text"
msgstr "Richtung des Textes"
-#: clutter/clutter-main.c:1570
+#: clutter/clutter-main.c:1567
msgid "Disable mipmapping on text"
msgstr "Mip-Mapping für Text ausschalten"
-#: clutter/clutter-main.c:1573
+#: clutter/clutter-main.c:1570
msgid "Use 'fuzzy' picking"
msgstr "»Unscharfes« Herausgreifen benutzen"
-#: clutter/clutter-main.c:1576
+#: clutter/clutter-main.c:1573
msgid "Clutter debugging flags to set"
msgstr "zu setzende Clutter-Fehlersuchmerkmale"
-#: clutter/clutter-main.c:1578
+#: clutter/clutter-main.c:1575
msgid "Clutter debugging flags to unset"
msgstr "zu entfernende Clutter-Fehlersuchmerkmale"
-#: clutter/clutter-main.c:1582
+#: clutter/clutter-main.c:1579
#, fuzzy
msgid "Clutter profiling flags to set"
msgstr "zu setzende Clutter-Fehlersuchmerkmale"
-#: clutter/clutter-main.c:1584
+#: clutter/clutter-main.c:1581
#, fuzzy
msgid "Clutter profiling flags to unset"
msgstr "zu entfernende Clutter-Fehlersuchmerkmale"
-#: clutter/clutter-main.c:1587
+#: clutter/clutter-main.c:1584
msgid "Enable accessibility"
msgstr ""
-#: clutter/clutter-main.c:1774
+#: clutter/clutter-main.c:1771
msgid "Clutter Options"
msgstr "Clutter-Optionen"
-#: clutter/clutter-main.c:1775
+#: clutter/clutter-main.c:1772
msgid "Show Clutter Options"
msgstr "Clutter-Optionen anzeigen"
msgid "The path of the currently parsed file"
msgstr ""
-#: clutter/clutter-shader.c:215
+#: clutter/clutter-shader.c:249
#, fuzzy
msgid "Vertex Source"
msgstr "Vertex-Shader"
-#: clutter/clutter-shader.c:216
+#: clutter/clutter-shader.c:250
#, fuzzy
msgid "Source of vertex shader"
msgstr "Vertex-Shader"
-#: clutter/clutter-shader.c:230
+#: clutter/clutter-shader.c:264
#, fuzzy
msgid "Fragment Source"
msgstr "Fragment-Shader"
-#: clutter/clutter-shader.c:231
+#: clutter/clutter-shader.c:265
#, fuzzy
msgid "Source of fragment shader"
msgstr "Fragment-Shader"
-#: clutter/clutter-shader.c:246
+#: clutter/clutter-shader.c:280
msgid "Compiled"
msgstr ""
-#: clutter/clutter-shader.c:247
+#: clutter/clutter-shader.c:281
msgid "Whether the shader is compiled and linked"
msgstr ""
-#: clutter/clutter-shader.c:262
+#: clutter/clutter-shader.c:296
msgid "Whether the shader is enabled"
msgstr ""
-#: clutter/clutter-shader.c:467
+#: clutter/clutter-shader.c:501
#, c-format
msgid "%s compilation failed: %s"
msgstr "%s-Kompilierung fehlgeschlagen: %s"
-#: clutter/clutter-shader.c:468
+#: clutter/clutter-shader.c:502
msgid "Vertex shader"
msgstr "Vertex-Shader"
-#: clutter/clutter-shader.c:469
+#: clutter/clutter-shader.c:503
msgid "Fragment shader"
msgstr "Fragment-Shader"
msgid "The type of shader used"
msgstr ""
-#: clutter/clutter-stage.c:1249
+#: clutter/clutter-stage.c:1259
msgid "Fullscreen Set"
msgstr ""
-#: clutter/clutter-stage.c:1250
+#: clutter/clutter-stage.c:1260
msgid "Whether the main stage is fullscreen"
msgstr ""
-#: clutter/clutter-stage.c:1266
+#: clutter/clutter-stage.c:1276
msgid "Offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1267
+#: clutter/clutter-stage.c:1277
msgid "Whether the main stage should be rendered offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1279 clutter/clutter-text.c:2643
+#: clutter/clutter-stage.c:1289 clutter/clutter-text.c:2667
msgid "Cursor Visible"
msgstr ""
-#: clutter/clutter-stage.c:1280
+#: clutter/clutter-stage.c:1290
msgid "Whether the mouse pointer is visible on the main stage"
msgstr ""
-#: clutter/clutter-stage.c:1294
+#: clutter/clutter-stage.c:1304
msgid "User Resizable"
msgstr ""
-#: clutter/clutter-stage.c:1295
+#: clutter/clutter-stage.c:1305
msgid "Whether the stage is able to be resized via user interaction"
msgstr ""
-#: clutter/clutter-stage.c:1308
+#: clutter/clutter-stage.c:1318
msgid "The color of the stage"
msgstr ""
-#: clutter/clutter-stage.c:1322
+#: clutter/clutter-stage.c:1332
msgid "Perspective"
msgstr ""
-#: clutter/clutter-stage.c:1323
+#: clutter/clutter-stage.c:1333
msgid "Perspective projection parameters"
msgstr ""
-#: clutter/clutter-stage.c:1338
+#: clutter/clutter-stage.c:1348
msgid "Title"
msgstr ""
-#: clutter/clutter-stage.c:1339
+#: clutter/clutter-stage.c:1349
msgid "Stage Title"
msgstr ""
-#: clutter/clutter-stage.c:1354
+#: clutter/clutter-stage.c:1364
msgid "Use Fog"
msgstr ""
-#: clutter/clutter-stage.c:1355
+#: clutter/clutter-stage.c:1365
msgid "Whether to enable depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1369
+#: clutter/clutter-stage.c:1379
msgid "Fog"
msgstr ""
-#: clutter/clutter-stage.c:1370
+#: clutter/clutter-stage.c:1380
msgid "Settings for the depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1386
+#: clutter/clutter-stage.c:1396
msgid "Use Alpha"
msgstr ""
-#: clutter/clutter-stage.c:1387
+#: clutter/clutter-stage.c:1397
msgid "Whether to honour the alpha component of the stage color"
msgstr ""
-#: clutter/clutter-stage.c:1403
+#: clutter/clutter-stage.c:1413
msgid "Key Focus"
msgstr ""
-#: clutter/clutter-stage.c:1404
+#: clutter/clutter-stage.c:1414
msgid "The currently key focused actor"
msgstr ""
-#: clutter/clutter-stage.c:1420
+#: clutter/clutter-stage.c:1430
msgid "No Clear Hint"
msgstr ""
-#: clutter/clutter-stage.c:1421
+#: clutter/clutter-stage.c:1431
msgid "Whether the stage should clear its contents"
msgstr ""
+#: clutter/clutter-stage.c:1444
+msgid "Accept Focus"
+msgstr ""
+
+#: clutter/clutter-stage.c:1445
+msgid "Whether the stage should accept focus on show"
+msgstr ""
+
#: clutter/clutter-state.c:1268
msgid "State"
msgstr ""
msgid "Default transition duration"
msgstr "Vorgabebildfrequenz"
-#: clutter/clutter-text.c:2530
+#: clutter/clutter-text.c:2554
msgid "Font Name"
msgstr ""
-#: clutter/clutter-text.c:2531
+#: clutter/clutter-text.c:2555
msgid "The font to be used by the text"
msgstr ""
-#: clutter/clutter-text.c:2548
+#: clutter/clutter-text.c:2572
msgid "Font Description"
msgstr ""
-#: clutter/clutter-text.c:2549
+#: clutter/clutter-text.c:2573
msgid "The font description to be used"
msgstr ""
-#: clutter/clutter-text.c:2565
+#: clutter/clutter-text.c:2589
msgid "Text"
msgstr ""
-#: clutter/clutter-text.c:2566
+#: clutter/clutter-text.c:2590
msgid "The text to render"
msgstr ""
-#: clutter/clutter-text.c:2580
+#: clutter/clutter-text.c:2604
msgid "Font Color"
msgstr ""
-#: clutter/clutter-text.c:2581
+#: clutter/clutter-text.c:2605
msgid "Color of the font used by the text"
msgstr ""
-#: clutter/clutter-text.c:2595
+#: clutter/clutter-text.c:2619
msgid "Editable"
msgstr ""
-#: clutter/clutter-text.c:2596
+#: clutter/clutter-text.c:2620
msgid "Whether the text is editable"
msgstr ""
-#: clutter/clutter-text.c:2611
+#: clutter/clutter-text.c:2635
msgid "Selectable"
msgstr ""
-#: clutter/clutter-text.c:2612
+#: clutter/clutter-text.c:2636
msgid "Whether the text is selectable"
msgstr ""
-#: clutter/clutter-text.c:2626
+#: clutter/clutter-text.c:2650
msgid "Activatable"
msgstr ""
-#: clutter/clutter-text.c:2627
+#: clutter/clutter-text.c:2651
msgid "Whether pressing return causes the activate signal to be emitted"
msgstr ""
-#: clutter/clutter-text.c:2644
+#: clutter/clutter-text.c:2668
msgid "Whether the input cursor is visible"
msgstr ""
-#: clutter/clutter-text.c:2658 clutter/clutter-text.c:2659
+#: clutter/clutter-text.c:2682 clutter/clutter-text.c:2683
msgid "Cursor Color"
msgstr ""
-#: clutter/clutter-text.c:2673
+#: clutter/clutter-text.c:2697
msgid "Cursor Color Set"
msgstr ""
-#: clutter/clutter-text.c:2674
+#: clutter/clutter-text.c:2698
msgid "Whether the cursor color has been set"
msgstr ""
-#: clutter/clutter-text.c:2689
+#: clutter/clutter-text.c:2713
msgid "Cursor Size"
msgstr ""
-#: clutter/clutter-text.c:2690
+#: clutter/clutter-text.c:2714
msgid "The width of the cursor, in pixels"
msgstr ""
-#: clutter/clutter-text.c:2704
+#: clutter/clutter-text.c:2728
msgid "Cursor Position"
msgstr ""
-#: clutter/clutter-text.c:2705
+#: clutter/clutter-text.c:2729
msgid "The cursor position"
msgstr ""
-#: clutter/clutter-text.c:2720
+#: clutter/clutter-text.c:2744
msgid "Selection-bound"
msgstr ""
-#: clutter/clutter-text.c:2721
+#: clutter/clutter-text.c:2745
msgid "The cursor position of the other end of the selection"
msgstr ""
-#: clutter/clutter-text.c:2736 clutter/clutter-text.c:2737
+#: clutter/clutter-text.c:2760 clutter/clutter-text.c:2761
msgid "Selection Color"
msgstr ""
-#: clutter/clutter-text.c:2751
+#: clutter/clutter-text.c:2775
msgid "Selection Color Set"
msgstr ""
-#: clutter/clutter-text.c:2752
+#: clutter/clutter-text.c:2776
msgid "Whether the selection color has been set"
msgstr ""
-#: clutter/clutter-text.c:2767
+#: clutter/clutter-text.c:2791
msgid "Attributes"
msgstr ""
-#: clutter/clutter-text.c:2768
+#: clutter/clutter-text.c:2792
msgid "A list of style attributes to apply to the contents of the actor"
msgstr ""
-#: clutter/clutter-text.c:2790
+#: clutter/clutter-text.c:2814
msgid "Use markup"
msgstr ""
-#: clutter/clutter-text.c:2791
+#: clutter/clutter-text.c:2815
msgid "Whether or not the text includes Pango markup"
msgstr ""
-#: clutter/clutter-text.c:2807
+#: clutter/clutter-text.c:2831
msgid "Line wrap"
msgstr ""
-#: clutter/clutter-text.c:2808
+#: clutter/clutter-text.c:2832
msgid "If set, wrap the lines if the text becomes too wide"
msgstr ""
-#: clutter/clutter-text.c:2823
+#: clutter/clutter-text.c:2847
msgid "Line wrap mode"
msgstr ""
-#: clutter/clutter-text.c:2824
+#: clutter/clutter-text.c:2848
msgid "Control how line-wrapping is done"
msgstr ""
-#: clutter/clutter-text.c:2839
+#: clutter/clutter-text.c:2863
msgid "Ellipsize"
msgstr ""
-#: clutter/clutter-text.c:2840
+#: clutter/clutter-text.c:2864
msgid "The preferred place to ellipsize the string"
msgstr ""
-#: clutter/clutter-text.c:2856
+#: clutter/clutter-text.c:2880
msgid "Line Alignment"
msgstr ""
-#: clutter/clutter-text.c:2857
+#: clutter/clutter-text.c:2881
msgid "The preferred alignment for the string, for multi-line text"
msgstr ""
-#: clutter/clutter-text.c:2873
+#: clutter/clutter-text.c:2897
msgid "Justify"
msgstr ""
-#: clutter/clutter-text.c:2874
+#: clutter/clutter-text.c:2898
msgid "Whether the text should be justified"
msgstr ""
-#: clutter/clutter-text.c:2889
+#: clutter/clutter-text.c:2913
msgid "Password Character"
msgstr ""
-#: clutter/clutter-text.c:2890
+#: clutter/clutter-text.c:2914
msgid "If non-zero, use this character to display the actor's contents"
msgstr ""
-#: clutter/clutter-text.c:2904
+#: clutter/clutter-text.c:2928
msgid "Max Length"
msgstr ""
-#: clutter/clutter-text.c:2905
+#: clutter/clutter-text.c:2929
msgid "Maximum length of the text inside the actor"
msgstr ""
-#: clutter/clutter-text.c:2928
+#: clutter/clutter-text.c:2952
msgid "Single Line Mode"
msgstr ""
-#: clutter/clutter-text.c:2929
+#: clutter/clutter-text.c:2953
msgid "Whether the text should be a single line"
msgstr ""
msgid "Shape actor with alpha channel when picking"
msgstr ""
-#: clutter/glx/clutter-backend-glx.c:128
+#: clutter/glx/clutter-backend-glx.c:131
msgid "VBlank method to be used (none, dri or glx)"
msgstr "zu benutzende VBlank-Methode (none, dri oder glx)"
-#: clutter/x11/clutter-backend-x11.c:364
+#: clutter/x11/clutter-backend-x11.c:473
msgid "X display to use"
msgstr "zu benutzende X-Anzeige"
-#: clutter/x11/clutter-backend-x11.c:370
+#: clutter/x11/clutter-backend-x11.c:479
msgid "X screen to use"
msgstr "zu benutzender X-Bildschirm"
-#: clutter/x11/clutter-backend-x11.c:375
+#: clutter/x11/clutter-backend-x11.c:484
msgid "Make X calls synchronous"
msgstr "X-Aufrufe synchronisieren"
-#: clutter/x11/clutter-backend-x11.c:382
+#: clutter/x11/clutter-backend-x11.c:491
msgid "Enable XInput support"
msgstr "XInput-Unterstützung einschalten"
"Project-Id-Version: clutter 1.3.14\n"
"Report-Msgid-Bugs-To: http://bugzilla.clutter-project.org/enter_bug.cgi?"
"product=clutter\n"
-"POT-Creation-Date: 2010-12-17 15:51+0000\n"
+"POT-Creation-Date: 2011-02-07 15:50+0000\n"
"PO-Revision-Date: 2010-10-05 09:02+0100\n"
"Last-Translator: Damien Lespiau <damien.lespiau@gmail.com>\n"
"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
"X-Poedit-Language: French\n"
"X-Poedit-Country: FRANCE\n"
-#: clutter/clutter-actor.c:3480
+#: clutter/clutter-actor.c:3478
msgid "X coordinate"
msgstr "Coordonnée X"
-#: clutter/clutter-actor.c:3481
+#: clutter/clutter-actor.c:3479
msgid "X coordinate of the actor"
msgstr "Coordonnée X de l'acteur"
-#: clutter/clutter-actor.c:3496
+#: clutter/clutter-actor.c:3494
msgid "Y coordinate"
msgstr "Coordonnée Y"
-#: clutter/clutter-actor.c:3497
+#: clutter/clutter-actor.c:3495
msgid "Y coordinate of the actor"
msgstr "Coordonnée X de l'acteur"
-#: clutter/clutter-actor.c:3512 clutter/clutter-behaviour-ellipse.c:475
+#: clutter/clutter-actor.c:3510 clutter/clutter-behaviour-ellipse.c:474
msgid "Width"
msgstr "Largeur"
-#: clutter/clutter-actor.c:3513
+#: clutter/clutter-actor.c:3511
msgid "Width of the actor"
msgstr "Largeur de l'acteur"
-#: clutter/clutter-actor.c:3527 clutter/clutter-behaviour-ellipse.c:491
+#: clutter/clutter-actor.c:3525 clutter/clutter-behaviour-ellipse.c:490
msgid "Height"
msgstr "Hauteur"
-#: clutter/clutter-actor.c:3528
+#: clutter/clutter-actor.c:3526
msgid "Height of the actor"
msgstr "Hauteur de l'acteur"
-#: clutter/clutter-actor.c:3546
+#: clutter/clutter-actor.c:3544
msgid "Fixed X"
msgstr "Position fixe selon l'axe X"
-#: clutter/clutter-actor.c:3547
+#: clutter/clutter-actor.c:3545
msgid "Forced X position of the actor"
msgstr "Position fixe de l'acteur selon l'axe X"
-#: clutter/clutter-actor.c:3565
+#: clutter/clutter-actor.c:3563
msgid "Fixed Y"
msgstr "Position fixe selon l'axe Y"
-#: clutter/clutter-actor.c:3566
+#: clutter/clutter-actor.c:3564
msgid "Forced Y position of the actor"
msgstr "Position fixe de l'acteur selon l'axe Y"
-#: clutter/clutter-actor.c:3582
+#: clutter/clutter-actor.c:3580
msgid "Fixed position set"
msgstr "Position fixe renseignée"
-#: clutter/clutter-actor.c:3583
+#: clutter/clutter-actor.c:3581
msgid "Whether to use fixed positioning for the actor"
msgstr "Si l'acteur utilise un positionnement fixe ou non"
-#: clutter/clutter-actor.c:3605
+#: clutter/clutter-actor.c:3603
msgid "Min Width"
msgstr "Largeur minimale"
-#: clutter/clutter-actor.c:3606
+#: clutter/clutter-actor.c:3604
msgid "Forced minimum width request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3625
+#: clutter/clutter-actor.c:3623
msgid "Min Height"
msgstr "Hauteur maximale"
-#: clutter/clutter-actor.c:3626
+#: clutter/clutter-actor.c:3624
msgid "Forced minimum height request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3645
+#: clutter/clutter-actor.c:3643
msgid "Natural Width"
msgstr "Largeur naturelle"
-#: clutter/clutter-actor.c:3646
+#: clutter/clutter-actor.c:3644
msgid "Forced natural width request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3665
+#: clutter/clutter-actor.c:3663
msgid "Natural Height"
msgstr "Hauteur Naturelle"
-#: clutter/clutter-actor.c:3666
+#: clutter/clutter-actor.c:3664
msgid "Forced natural height request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3682
+#: clutter/clutter-actor.c:3680
msgid "Minimum width set"
msgstr "Largeur minimale renseignée"
-#: clutter/clutter-actor.c:3683
+#: clutter/clutter-actor.c:3681
msgid "Whether to use the min-width property"
msgstr "Si la largeur minimale a été renseignée ou non"
-#: clutter/clutter-actor.c:3698
+#: clutter/clutter-actor.c:3696
msgid "Minimum height set"
msgstr "Hauteur minimale renseignée"
-#: clutter/clutter-actor.c:3699
+#: clutter/clutter-actor.c:3697
msgid "Whether to use the min-height property"
msgstr "Si la hauteur minimale a été renseignée ou non"
-#: clutter/clutter-actor.c:3714
+#: clutter/clutter-actor.c:3712
msgid "Natural width set"
msgstr "Largeur naturelle renseignée"
-#: clutter/clutter-actor.c:3715
+#: clutter/clutter-actor.c:3713
msgid "Whether to use the natural-width property"
msgstr "Si la largeur naturelle a été renseignée ou non"
-#: clutter/clutter-actor.c:3732
+#: clutter/clutter-actor.c:3730
msgid "Natural height set"
msgstr "Haueur naturelle renseignée"
-#: clutter/clutter-actor.c:3733
+#: clutter/clutter-actor.c:3731
msgid "Whether to use the natural-height property"
msgstr "Si la hauteur naturelle a été renseignée ou non"
-#: clutter/clutter-actor.c:3752
+#: clutter/clutter-actor.c:3750
msgid "Allocation"
msgstr "Allocation"
-#: clutter/clutter-actor.c:3753
+#: clutter/clutter-actor.c:3751
msgid "The actor's allocation"
msgstr "L'allocation de l'acteur"
-#: clutter/clutter-actor.c:3809
+#: clutter/clutter-actor.c:3807
msgid "Request Mode"
msgstr ""
-#: clutter/clutter-actor.c:3810
+#: clutter/clutter-actor.c:3808
msgid "The actor's request mode"
msgstr ""
-#: clutter/clutter-actor.c:3825
+#: clutter/clutter-actor.c:3823
msgid "Depth"
msgstr "Profondeur"
-#: clutter/clutter-actor.c:3826
+#: clutter/clutter-actor.c:3824
msgid "Position on the Z axis"
msgstr "Position sur l'axe Z"
-#: clutter/clutter-actor.c:3840
+#: clutter/clutter-actor.c:3838
msgid "Opacity"
msgstr "Opacité"
-#: clutter/clutter-actor.c:3841
+#: clutter/clutter-actor.c:3839
msgid "Opacity of an actor"
msgstr "Opacité d'un acteur"
-#: clutter/clutter-actor.c:3856
+#: clutter/clutter-actor.c:3854
msgid "Visible"
msgstr "Visible"
-#: clutter/clutter-actor.c:3857
+#: clutter/clutter-actor.c:3855
msgid "Whether the actor is visible or not"
msgstr "Si un acteur est visible ou non"
-#: clutter/clutter-actor.c:3872
+#: clutter/clutter-actor.c:3870
msgid "Mapped"
msgstr ""
-#: clutter/clutter-actor.c:3873
+#: clutter/clutter-actor.c:3871
msgid "Whether the actor will be painted"
msgstr "Si l'acteur sera peint"
-#: clutter/clutter-actor.c:3887
+#: clutter/clutter-actor.c:3885
msgid "Realized"
msgstr "Réalisé"
-#: clutter/clutter-actor.c:3888
+#: clutter/clutter-actor.c:3886
msgid "Whether the actor has been realized"
msgstr "Si l'acteur a été réalisé"
-#: clutter/clutter-actor.c:3904
+#: clutter/clutter-actor.c:3902
msgid "Reactive"
msgstr "Réactif"
-#: clutter/clutter-actor.c:3905
+#: clutter/clutter-actor.c:3903
msgid "Whether the actor is reactive to events"
msgstr "Si l'acteur est réactif ou pas"
-#: clutter/clutter-actor.c:3917
+#: clutter/clutter-actor.c:3915
msgid "Has Clip"
msgstr "A une région de rognage"
-#: clutter/clutter-actor.c:3918
+#: clutter/clutter-actor.c:3916
msgid "Whether the actor has a clip set"
msgstr "Si l'acteur a une région de rognage ou pas"
-#: clutter/clutter-actor.c:3933
+#: clutter/clutter-actor.c:3931
msgid "Clip"
msgstr "Rognage"
-#: clutter/clutter-actor.c:3934
+#: clutter/clutter-actor.c:3932
msgid "The clip region for the actor"
msgstr "Le région de rognage de l'acteur"
-#: clutter/clutter-actor.c:3948 clutter/clutter-actor-meta.c:205
-#: clutter/clutter-binding-pool.c:320 clutter/clutter-input-device.c:151
+#: clutter/clutter-actor.c:3946 clutter/clutter-actor-meta.c:205
+#: clutter/clutter-binding-pool.c:319 clutter/clutter-input-device.c:235
msgid "Name"
msgstr "Nom"
-#: clutter/clutter-actor.c:3949
+#: clutter/clutter-actor.c:3947
msgid "Name of the actor"
msgstr "Nom de l'acteur"
-#: clutter/clutter-actor.c:3963
+#: clutter/clutter-actor.c:3961
msgid "Scale X"
msgstr "Homothétie (X)"
-#: clutter/clutter-actor.c:3964
+#: clutter/clutter-actor.c:3962
msgid "Scale factor on the X axis"
msgstr "Facteur d'homothétie sur l'axe X"
-#: clutter/clutter-actor.c:3979
+#: clutter/clutter-actor.c:3977
msgid "Scale Y"
msgstr "Homothétie (Y)"
-#: clutter/clutter-actor.c:3980
+#: clutter/clutter-actor.c:3978
msgid "Scale factor on the Y axis"
msgstr "Facteur d'homothétie sur l'axe Y"
-#: clutter/clutter-actor.c:3995
+#: clutter/clutter-actor.c:3993
msgid "Scale Center X"
msgstr "Centre d'homothétie (X)"
-#: clutter/clutter-actor.c:3996
+#: clutter/clutter-actor.c:3994
msgid "Horizontal scale center"
msgstr ""
-#: clutter/clutter-actor.c:4011
+#: clutter/clutter-actor.c:4009
msgid "Scale Center Y"
msgstr "Centre d'homothétie (Y)"
-#: clutter/clutter-actor.c:4012
+#: clutter/clutter-actor.c:4010
msgid "Vertical scale center"
msgstr ""
-#: clutter/clutter-actor.c:4027
+#: clutter/clutter-actor.c:4025
msgid "Scale Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4028
+#: clutter/clutter-actor.c:4026
msgid "The center of scaling"
msgstr "Le centre d'homothétie"
-#: clutter/clutter-actor.c:4045
+#: clutter/clutter-actor.c:4043
msgid "Rotation Angle X"
msgstr "Angle de rotation (X)"
-#: clutter/clutter-actor.c:4046
+#: clutter/clutter-actor.c:4044
msgid "The rotation angle on the X axis"
msgstr "L'angle de rotation autour de l'axe X"
-#: clutter/clutter-actor.c:4061
+#: clutter/clutter-actor.c:4059
msgid "Rotation Angle Y"
msgstr "Angle de rotation (Y)"
-#: clutter/clutter-actor.c:4062
+#: clutter/clutter-actor.c:4060
msgid "The rotation angle on the Y axis"
msgstr "L'angle de rotation autour de l'axe Y"
-#: clutter/clutter-actor.c:4077
+#: clutter/clutter-actor.c:4075
msgid "Rotation Angle Z"
msgstr "Angle de rotation (Z)"
-#: clutter/clutter-actor.c:4078
+#: clutter/clutter-actor.c:4076
msgid "The rotation angle on the Z axis"
msgstr "L'angle de rotation autour de l'axe Z"
-#: clutter/clutter-actor.c:4093
+#: clutter/clutter-actor.c:4091
msgid "Rotation Center X"
msgstr "Centre de rotation (X)"
-#: clutter/clutter-actor.c:4094
+#: clutter/clutter-actor.c:4092
msgid "The rotation center on the X axis"
msgstr "Le centre de rotation sur l'axe X"
-#: clutter/clutter-actor.c:4110
+#: clutter/clutter-actor.c:4108
msgid "Rotation Center Y"
msgstr "Centre de rotation (Y)"
-#: clutter/clutter-actor.c:4111
+#: clutter/clutter-actor.c:4109
msgid "The rotation center on the Y axis"
msgstr "Le centre de rotation sur l'axe Y"
-#: clutter/clutter-actor.c:4127
+#: clutter/clutter-actor.c:4125
msgid "Rotation Center Z"
msgstr "Centre de rotation (Z)"
-#: clutter/clutter-actor.c:4128
+#: clutter/clutter-actor.c:4126
msgid "The rotation center on the Z axis"
msgstr "Le centre de rotation sur l'axe Y"
-#: clutter/clutter-actor.c:4144
+#: clutter/clutter-actor.c:4142
msgid "Rotation Center Z Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4145
+#: clutter/clutter-actor.c:4143
msgid "Center point for rotation around the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:4163
+#: clutter/clutter-actor.c:4161
msgid "Anchor X"
msgstr ""
-#: clutter/clutter-actor.c:4164
+#: clutter/clutter-actor.c:4162
msgid "X coordinate of the anchor point"
msgstr ""
-#: clutter/clutter-actor.c:4180
+#: clutter/clutter-actor.c:4178
msgid "Anchor Y"
msgstr ""
-#: clutter/clutter-actor.c:4181
+#: clutter/clutter-actor.c:4179
msgid "Y coordinate of the anchor point"
msgstr ""
-#: clutter/clutter-actor.c:4196
+#: clutter/clutter-actor.c:4194
msgid "Anchor Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4197
+#: clutter/clutter-actor.c:4195
msgid "The anchor point as a ClutterGravity"
msgstr ""
-#: clutter/clutter-actor.c:4216
+#: clutter/clutter-actor.c:4214
msgid "Show on set parent"
msgstr ""
-#: clutter/clutter-actor.c:4217
+#: clutter/clutter-actor.c:4215
msgid "Whether the actor is shown when parented"
msgstr ""
-#: clutter/clutter-actor.c:4237
+#: clutter/clutter-actor.c:4235
msgid "Clip to Allocation"
msgstr ""
-#: clutter/clutter-actor.c:4238
+#: clutter/clutter-actor.c:4236
msgid "Sets the clip region to track the actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:4248
+#: clutter/clutter-actor.c:4246
msgid "Text Direction"
msgstr "Direction du texte"
-#: clutter/clutter-actor.c:4249
+#: clutter/clutter-actor.c:4247
msgid "Direction of the text"
msgstr "La direction du texte"
-#: clutter/clutter-actor.c:4267
+#: clutter/clutter-actor.c:4265
msgid "Has Pointer"
msgstr "Contient pointeur"
-#: clutter/clutter-actor.c:4268
+#: clutter/clutter-actor.c:4266
msgid "Whether the actor contains the pointer of an input device"
msgstr "Si l'acteur contient le pointer d'un périphérique d'entrée"
-#: clutter/clutter-actor.c:4285
+#: clutter/clutter-actor.c:4283
msgid "Actions"
msgstr "Actions"
-#: clutter/clutter-actor.c:4286
+#: clutter/clutter-actor.c:4284
msgid "Adds an action to the actor"
msgstr "Ajoute une action à l'acteur"
-#: clutter/clutter-actor.c:4300
+#: clutter/clutter-actor.c:4298
msgid "Constraints"
msgstr "Contraintes"
-#: clutter/clutter-actor.c:4301
+#: clutter/clutter-actor.c:4299
msgid "Adds a constraint to the actor"
msgstr "Ajoute une contrainte à l'acteur"
msgid "The name of the meta"
msgstr "Le nom du méta"
-#: clutter/clutter-actor-meta.c:219 clutter/clutter-shader.c:261
+#: clutter/clutter-actor-meta.c:219 clutter/clutter-input-device.c:314
+#: clutter/clutter-shader.c:295
msgid "Enabled"
msgstr "Activé"
msgid "Whether the meta is enabled"
msgstr "Si le méta est activé"
-#: clutter/clutter-align-constraint.c:231
-#: clutter/clutter-bind-constraint.c:286 clutter/clutter-clone.c:322
+#: clutter/clutter-align-constraint.c:252
+#: clutter/clutter-bind-constraint.c:316 clutter/clutter-clone.c:322
msgid "Source"
msgstr "Source"
-#: clutter/clutter-align-constraint.c:232
+#: clutter/clutter-align-constraint.c:253
msgid "The source of the alignment"
msgstr "La source de l'alignement"
-#: clutter/clutter-align-constraint.c:245
+#: clutter/clutter-align-constraint.c:266
msgid "Align Axis"
msgstr "L'axe d'alignement"
-#: clutter/clutter-align-constraint.c:246
+#: clutter/clutter-align-constraint.c:267
msgid "The axis to align the position to"
msgstr "L'axe par rapport auquel aligner la position"
-#: clutter/clutter-align-constraint.c:265
-#: clutter/clutter-desaturate-effect.c:309
+#: clutter/clutter-align-constraint.c:286
+#: clutter/clutter-desaturate-effect.c:307
msgid "Factor"
msgstr "Facteur"
-#: clutter/clutter-align-constraint.c:266
+#: clutter/clutter-align-constraint.c:287
msgid "The alignment factor, between 0.0 and 1.0"
msgstr "Le facteur d'alignement, entre 0.0 et 1.0"
#: clutter/clutter-alpha.c:339 clutter/clutter-animation.c:523
-#: clutter/clutter-animator.c:1801
+#: clutter/clutter-animator.c:1802
msgid "Timeline"
msgstr ""
msgid "The mode of the animation"
msgstr "Le mode d'animation"
-#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1785
+#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1786
#: clutter/clutter-media.c:194 clutter/clutter-state.c:1282
msgid "Duration"
msgstr "Durée"
msgid "The timeline used by the animation"
msgstr ""
-#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:299
+#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:298
msgid "Alpha"
msgstr "Alpha"
msgid "The alpha used by the animation"
msgstr "L'alpha utilisé pour l'animation"
-#: clutter/clutter-animator.c:1786
+#: clutter/clutter-animator.c:1787
msgid "The duration of the animation"
msgstr "La durée de l'animation"
-#: clutter/clutter-animator.c:1802
+#: clutter/clutter-animator.c:1803
msgid "The timeline of the animation"
msgstr ""
-#: clutter/clutter-behaviour.c:300
+#: clutter/clutter-behaviour.c:299
msgid "Alpha Object to drive the behaviour"
msgstr "Object alpha a partir duquel dériver le comportement"
-#: clutter/clutter-behaviour-depth.c:175
+#: clutter/clutter-behaviour-depth.c:174
msgid "Start Depth"
msgstr "Profondeur de départ"
-#: clutter/clutter-behaviour-depth.c:176
+#: clutter/clutter-behaviour-depth.c:175
msgid "Initial depth to apply"
msgstr "Profondeur initiale à appliquer"
-#: clutter/clutter-behaviour-depth.c:191
+#: clutter/clutter-behaviour-depth.c:190
msgid "End Depth"
msgstr "Profondeur d'arrivée"
-#: clutter/clutter-behaviour-depth.c:192
+#: clutter/clutter-behaviour-depth.c:191
msgid "Final depth to apply"
msgstr "Profondeur finale à appliquer"
-#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-ellipse.c:394
msgid "Start Angle"
msgstr "Angle de départ"
-#: clutter/clutter-behaviour-ellipse.c:396
-#: clutter/clutter-behaviour-rotate.c:277
+#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-rotate.c:276
msgid "Initial angle"
msgstr "Angle initial"
-#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-ellipse.c:410
msgid "End Angle"
msgstr "Angle d'arrivée"
-#: clutter/clutter-behaviour-ellipse.c:412
-#: clutter/clutter-behaviour-rotate.c:295
+#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-rotate.c:294
msgid "Final angle"
msgstr "Angle final"
-#: clutter/clutter-behaviour-ellipse.c:427
+#: clutter/clutter-behaviour-ellipse.c:426
msgid "Angle x tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:428
+#: clutter/clutter-behaviour-ellipse.c:427
msgid "Tilt of the ellipse around x axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:443
+#: clutter/clutter-behaviour-ellipse.c:442
msgid "Angle y tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:444
+#: clutter/clutter-behaviour-ellipse.c:443
msgid "Tilt of the ellipse around y axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:459
+#: clutter/clutter-behaviour-ellipse.c:458
msgid "Angle z tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:460
+#: clutter/clutter-behaviour-ellipse.c:459
msgid "Tilt of the ellipse around z axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:476
+#: clutter/clutter-behaviour-ellipse.c:475
msgid "Width of the ellipse"
msgstr "Largeur de l'éllipse"
-#: clutter/clutter-behaviour-ellipse.c:492
+#: clutter/clutter-behaviour-ellipse.c:491
msgid "Height of ellipse"
msgstr "Hauteur de l'éllipse"
-#: clutter/clutter-behaviour-ellipse.c:507
+#: clutter/clutter-behaviour-ellipse.c:506
msgid "Center"
msgstr "Centre"
-#: clutter/clutter-behaviour-ellipse.c:508
+#: clutter/clutter-behaviour-ellipse.c:507
msgid "Center of ellipse"
msgstr "Centre de l'éllipse"
-#: clutter/clutter-behaviour-ellipse.c:522
-#: clutter/clutter-behaviour-rotate.c:330
+#: clutter/clutter-behaviour-ellipse.c:521
+#: clutter/clutter-behaviour-rotate.c:329
msgid "Direction"
msgstr "Direction"
-#: clutter/clutter-behaviour-ellipse.c:523
-#: clutter/clutter-behaviour-rotate.c:331
+#: clutter/clutter-behaviour-ellipse.c:522
+#: clutter/clutter-behaviour-rotate.c:330
msgid "Direction of rotation"
msgstr "Direction de la rotation"
-#: clutter/clutter-behaviour-opacity.c:178
+#: clutter/clutter-behaviour-opacity.c:177
msgid "Opacity Start"
msgstr "Opacité de départ"
-#: clutter/clutter-behaviour-opacity.c:179
+#: clutter/clutter-behaviour-opacity.c:178
msgid "Initial opacity level"
msgstr "Niveau initial d'opacité"
-#: clutter/clutter-behaviour-opacity.c:196
+#: clutter/clutter-behaviour-opacity.c:195
msgid "Opacity End"
msgstr "Opactité d'arrivée"
-#: clutter/clutter-behaviour-opacity.c:197
+#: clutter/clutter-behaviour-opacity.c:196
msgid "Final opacity level"
msgstr "Niveau final d'opacité"
-#: clutter/clutter-behaviour-path.c:220
+#: clutter/clutter-behaviour-path.c:219
msgid "Path"
msgstr "Chemin"
-#: clutter/clutter-behaviour-path.c:221
+#: clutter/clutter-behaviour-path.c:220
msgid "The ClutterPath object representing the path to animate along"
msgstr "L'objet ClutterPatch qui représente le chemin que l'animation suit"
-#: clutter/clutter-behaviour-rotate.c:276
+#: clutter/clutter-behaviour-rotate.c:275
msgid "Angle Begin"
msgstr "Angle de départ"
-#: clutter/clutter-behaviour-rotate.c:294
+#: clutter/clutter-behaviour-rotate.c:293
msgid "Angle End"
msgstr "Angle d'arrivée"
-#: clutter/clutter-behaviour-rotate.c:312
+#: clutter/clutter-behaviour-rotate.c:311
msgid "Axis"
msgstr "Axe"
-#: clutter/clutter-behaviour-rotate.c:313
+#: clutter/clutter-behaviour-rotate.c:312
msgid "Axis of rotation"
msgstr "Axe de rotation"
-#: clutter/clutter-behaviour-rotate.c:348
+#: clutter/clutter-behaviour-rotate.c:347
msgid "Center X"
msgstr "Centre (X)"
-#: clutter/clutter-behaviour-rotate.c:349
+#: clutter/clutter-behaviour-rotate.c:348
msgid "X coordinate of the center of rotation"
msgstr "Coordonnée X du centre de rotation"
-#: clutter/clutter-behaviour-rotate.c:366
+#: clutter/clutter-behaviour-rotate.c:365
msgid "Center Y"
msgstr "Centre (Y)"
-#: clutter/clutter-behaviour-rotate.c:367
+#: clutter/clutter-behaviour-rotate.c:366
msgid "Y coordinate of the center of rotation"
msgstr "Coordonnée Y du centre de rotation"
-#: clutter/clutter-behaviour-rotate.c:384
+#: clutter/clutter-behaviour-rotate.c:383
msgid "Center Z"
msgstr "Centre (Z)"
-#: clutter/clutter-behaviour-rotate.c:385
+#: clutter/clutter-behaviour-rotate.c:384
msgid "Z coordinate of the center of rotation"
msgstr "Coordonnée Z du centre de rotation"
-#: clutter/clutter-behaviour-scale.c:219
+#: clutter/clutter-behaviour-scale.c:218
msgid "X Start Scale"
msgstr "Homothétie (X) de départ"
-#: clutter/clutter-behaviour-scale.c:220
+#: clutter/clutter-behaviour-scale.c:219
msgid "Initial scale on the X axis"
msgstr "Facteur initial d'homothétie selon l'axe X"
-#: clutter/clutter-behaviour-scale.c:238
+#: clutter/clutter-behaviour-scale.c:237
msgid "X End Scale"
msgstr "Homothétie (X) de départ"
-#: clutter/clutter-behaviour-scale.c:239
+#: clutter/clutter-behaviour-scale.c:238
msgid "Final scale on the X axis"
msgstr "Facteur final d'homothétie selon l'axe X"
-#: clutter/clutter-behaviour-scale.c:257
+#: clutter/clutter-behaviour-scale.c:256
msgid "Y Start Scale"
msgstr "Homothétie (Y) de départ"
-#: clutter/clutter-behaviour-scale.c:258
+#: clutter/clutter-behaviour-scale.c:257
msgid "Initial scale on the Y axis"
msgstr "Facteur initial d'homothétie selon l'axe Y"
-#: clutter/clutter-behaviour-scale.c:276
+#: clutter/clutter-behaviour-scale.c:275
msgid "Y End Scale"
msgstr "Homothétie (Y) de départ"
-#: clutter/clutter-behaviour-scale.c:277
+#: clutter/clutter-behaviour-scale.c:276
msgid "Final scale on the Y axis"
msgstr "Facteur final d'homothétie selon l'axe X"
-#: clutter/clutter-bind-constraint.c:287
+#: clutter/clutter-bind-constraint.c:317
msgid "The source of the binding"
msgstr "La source du lien"
-#: clutter/clutter-bind-constraint.c:300
+#: clutter/clutter-bind-constraint.c:330
msgid "Coordinate"
msgstr "Coordonnée"
-#: clutter/clutter-bind-constraint.c:301
+#: clutter/clutter-bind-constraint.c:331
msgid "The coordinate to bind"
msgstr "La coordonnée à lier"
-#: clutter/clutter-bind-constraint.c:315
+#: clutter/clutter-bind-constraint.c:345
msgid "Offset"
msgstr "Décalage"
-#: clutter/clutter-bind-constraint.c:316
+#: clutter/clutter-bind-constraint.c:346
msgid "The offset in pixels to apply to the binding"
msgstr "Le décalage, en pixels, à appliquer au lien"
msgid "Default vertical alignment for the actors inside the layout manager"
msgstr ""
-#: clutter/clutter-binding-pool.c:321
+#: clutter/clutter-binding-pool.c:320
msgid "The unique name of the binding pool"
msgstr ""
msgstr ""
#: clutter/clutter-box.c:514 clutter/clutter-rectangle.c:258
-#: clutter/clutter-stage.c:1307
+#: clutter/clutter-stage.c:1317
msgid "Color"
msgstr "Couleur"
msgid "The actor wrapped by this data"
msgstr ""
-#: clutter/clutter-click-action.c:283
+#: clutter/clutter-click-action.c:302
msgid "Pressed"
msgstr ""
-#: clutter/clutter-click-action.c:284
+#: clutter/clutter-click-action.c:303
msgid "Whether the clickable should be in pressed state"
msgstr ""
-#: clutter/clutter-click-action.c:297
+#: clutter/clutter-click-action.c:316
msgid "Held"
msgstr ""
-#: clutter/clutter-click-action.c:298
+#: clutter/clutter-click-action.c:317
msgid "Whether the clickable has a grab"
msgstr ""
msgid "Specifies the actor to be cloned"
msgstr ""
-#: clutter/clutter-colorize-effect.c:309
+#: clutter/clutter-colorize-effect.c:307
msgid "Tint"
msgstr "Teinte"
-#: clutter/clutter-colorize-effect.c:310
+#: clutter/clutter-colorize-effect.c:308
msgid "The tint to apply"
msgstr "La teinte à appliquer"
msgid "The material to be used when painting the back of the actor"
msgstr ""
-#: clutter/clutter-desaturate-effect.c:310
+#: clutter/clutter-desaturate-effect.c:308
msgid "The desaturation factor"
msgstr ""
-#: clutter/clutter-device-manager.c:130
+#: clutter/clutter-device-manager.c:130 clutter/clutter-input-device.c:343
msgid "Backend"
msgstr ""
msgid "The ClutterBackend of the device manager"
msgstr ""
-#: clutter/clutter-drag-action.c:490
+#: clutter/clutter-drag-action.c:491
msgid "Horizontal Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:491
+#: clutter/clutter-drag-action.c:492
msgid "The horizontal amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:510
+#: clutter/clutter-drag-action.c:511
msgid "Vertical Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:511
+#: clutter/clutter-drag-action.c:512
msgid "The vertical amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:532
+#: clutter/clutter-drag-action.c:533
msgid "Drag Handle"
msgstr ""
-#: clutter/clutter-drag-action.c:533
+#: clutter/clutter-drag-action.c:534
msgid "The actor that is being dragged"
msgstr ""
-#: clutter/clutter-drag-action.c:546
+#: clutter/clutter-drag-action.c:547
msgid "Drag Axis"
msgstr ""
-#: clutter/clutter-drag-action.c:547
+#: clutter/clutter-drag-action.c:548
msgid "Constraints the dragging to an axis"
msgstr ""
msgid "Maximum height for each row"
msgstr ""
-#: clutter/clutter-input-device.c:134
+#: clutter/clutter-input-device.c:219
msgid "Id"
msgstr ""
-#: clutter/clutter-input-device.c:135
+#: clutter/clutter-input-device.c:220
msgid "Unique identifier of the device"
msgstr ""
-#: clutter/clutter-input-device.c:152
+#: clutter/clutter-input-device.c:236
msgid "The name of the device"
msgstr "Le nom du périphérique"
-#: clutter/clutter-input-device.c:167
+#: clutter/clutter-input-device.c:250
msgid "Device Type"
msgstr "Type de périphérique"
-#: clutter/clutter-input-device.c:168
+#: clutter/clutter-input-device.c:251
msgid "The type of the device"
msgstr "Le type du périphérique"
+#: clutter/clutter-input-device.c:266
+#, fuzzy
+msgid "Device Manager"
+msgstr "Gestionnaire"
+
+#: clutter/clutter-input-device.c:267
+msgid "The device manager instance"
+msgstr ""
+
+#: clutter/clutter-input-device.c:280
+#, fuzzy
+msgid "Device Mode"
+msgstr "Type de périphérique"
+
+#: clutter/clutter-input-device.c:281
+#, fuzzy
+msgid "The mode of the device"
+msgstr "Le nom du périphérique"
+
+#: clutter/clutter-input-device.c:295
+msgid "Has Cursor"
+msgstr ""
+
+#: clutter/clutter-input-device.c:296
+#, fuzzy
+msgid "Whether the device has a cursor"
+msgstr "Si l'acteur a une région de rognage ou pas"
+
+#: clutter/clutter-input-device.c:315
+#, fuzzy
+msgid "Whether the device is enabled"
+msgstr "Si le méta est activé"
+
+#: clutter/clutter-input-device.c:328
+msgid "Number of Axes"
+msgstr ""
+
+#: clutter/clutter-input-device.c:329
+#, fuzzy
+msgid "The number of axes on the device"
+msgstr "Le nom du périphérique"
+
+#: clutter/clutter-input-device.c:344
+msgid "The backend instance"
+msgstr ""
+
#: clutter/clutter-interval.c:397
msgid "Value Type"
msgstr "Type de valeur"
msgid "The manager that created this data"
msgstr "Le gestionnaire qui a créé ces données"
-#: clutter/clutter-main.c:756
+#: clutter/clutter-main.c:753
msgid "default:LTR"
msgstr "default:LTR"
-#: clutter/clutter-main.c:1560
+#: clutter/clutter-main.c:1557
msgid "Show frames per second"
msgstr ""
-#: clutter/clutter-main.c:1562
+#: clutter/clutter-main.c:1559
msgid "Default frame rate"
msgstr ""
-#: clutter/clutter-main.c:1564
+#: clutter/clutter-main.c:1561
msgid "Make all warnings fatal"
msgstr ""
-#: clutter/clutter-main.c:1567
+#: clutter/clutter-main.c:1564
msgid "Direction for the text"
msgstr ""
-#: clutter/clutter-main.c:1570
+#: clutter/clutter-main.c:1567
msgid "Disable mipmapping on text"
msgstr ""
-#: clutter/clutter-main.c:1573
+#: clutter/clutter-main.c:1570
msgid "Use 'fuzzy' picking"
msgstr ""
-#: clutter/clutter-main.c:1576
+#: clutter/clutter-main.c:1573
msgid "Clutter debugging flags to set"
msgstr ""
-#: clutter/clutter-main.c:1578
+#: clutter/clutter-main.c:1575
msgid "Clutter debugging flags to unset"
msgstr ""
-#: clutter/clutter-main.c:1582
+#: clutter/clutter-main.c:1579
msgid "Clutter profiling flags to set"
msgstr ""
-#: clutter/clutter-main.c:1584
+#: clutter/clutter-main.c:1581
msgid "Clutter profiling flags to unset"
msgstr ""
-#: clutter/clutter-main.c:1587
+#: clutter/clutter-main.c:1584
msgid "Enable accessibility"
msgstr ""
-#: clutter/clutter-main.c:1774
+#: clutter/clutter-main.c:1771
msgid "Clutter Options"
msgstr ""
-#: clutter/clutter-main.c:1775
+#: clutter/clutter-main.c:1772
msgid "Show Clutter Options"
msgstr ""
msgid "The path of the currently parsed file"
msgstr ""
-#: clutter/clutter-shader.c:215
+#: clutter/clutter-shader.c:249
msgid "Vertex Source"
msgstr ""
-#: clutter/clutter-shader.c:216
+#: clutter/clutter-shader.c:250
msgid "Source of vertex shader"
msgstr ""
-#: clutter/clutter-shader.c:230
+#: clutter/clutter-shader.c:264
msgid "Fragment Source"
msgstr ""
-#: clutter/clutter-shader.c:231
+#: clutter/clutter-shader.c:265
msgid "Source of fragment shader"
msgstr ""
-#: clutter/clutter-shader.c:246
+#: clutter/clutter-shader.c:280
msgid "Compiled"
msgstr ""
-#: clutter/clutter-shader.c:247
+#: clutter/clutter-shader.c:281
msgid "Whether the shader is compiled and linked"
msgstr ""
-#: clutter/clutter-shader.c:262
+#: clutter/clutter-shader.c:296
msgid "Whether the shader is enabled"
msgstr ""
-#: clutter/clutter-shader.c:467
+#: clutter/clutter-shader.c:501
#, c-format
msgid "%s compilation failed: %s"
msgstr ""
-#: clutter/clutter-shader.c:468
+#: clutter/clutter-shader.c:502
msgid "Vertex shader"
msgstr ""
-#: clutter/clutter-shader.c:469
+#: clutter/clutter-shader.c:503
msgid "Fragment shader"
msgstr ""
msgid "The type of shader used"
msgstr ""
-#: clutter/clutter-stage.c:1249
+#: clutter/clutter-stage.c:1259
msgid "Fullscreen Set"
msgstr ""
-#: clutter/clutter-stage.c:1250
+#: clutter/clutter-stage.c:1260
msgid "Whether the main stage is fullscreen"
msgstr ""
-#: clutter/clutter-stage.c:1266
+#: clutter/clutter-stage.c:1276
msgid "Offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1267
+#: clutter/clutter-stage.c:1277
msgid "Whether the main stage should be rendered offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1279 clutter/clutter-text.c:2643
+#: clutter/clutter-stage.c:1289 clutter/clutter-text.c:2667
msgid "Cursor Visible"
msgstr ""
-#: clutter/clutter-stage.c:1280
+#: clutter/clutter-stage.c:1290
msgid "Whether the mouse pointer is visible on the main stage"
msgstr ""
-#: clutter/clutter-stage.c:1294
+#: clutter/clutter-stage.c:1304
msgid "User Resizable"
msgstr ""
-#: clutter/clutter-stage.c:1295
+#: clutter/clutter-stage.c:1305
msgid "Whether the stage is able to be resized via user interaction"
msgstr ""
-#: clutter/clutter-stage.c:1308
+#: clutter/clutter-stage.c:1318
msgid "The color of the stage"
msgstr ""
-#: clutter/clutter-stage.c:1322
+#: clutter/clutter-stage.c:1332
msgid "Perspective"
msgstr ""
-#: clutter/clutter-stage.c:1323
+#: clutter/clutter-stage.c:1333
msgid "Perspective projection parameters"
msgstr ""
-#: clutter/clutter-stage.c:1338
+#: clutter/clutter-stage.c:1348
msgid "Title"
msgstr ""
-#: clutter/clutter-stage.c:1339
+#: clutter/clutter-stage.c:1349
msgid "Stage Title"
msgstr "Titre de la scène"
-#: clutter/clutter-stage.c:1354
+#: clutter/clutter-stage.c:1364
msgid "Use Fog"
msgstr "Utilise le brouillard"
-#: clutter/clutter-stage.c:1355
+#: clutter/clutter-stage.c:1365
msgid "Whether to enable depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1369
+#: clutter/clutter-stage.c:1379
msgid "Fog"
msgstr "Brouillard"
-#: clutter/clutter-stage.c:1370
+#: clutter/clutter-stage.c:1380
msgid "Settings for the depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1386
+#: clutter/clutter-stage.c:1396
msgid "Use Alpha"
msgstr ""
-#: clutter/clutter-stage.c:1387
+#: clutter/clutter-stage.c:1397
msgid "Whether to honour the alpha component of the stage color"
msgstr ""
-#: clutter/clutter-stage.c:1403
+#: clutter/clutter-stage.c:1413
msgid "Key Focus"
msgstr ""
-#: clutter/clutter-stage.c:1404
+#: clutter/clutter-stage.c:1414
msgid "The currently key focused actor"
msgstr ""
-#: clutter/clutter-stage.c:1420
+#: clutter/clutter-stage.c:1430
msgid "No Clear Hint"
msgstr ""
-#: clutter/clutter-stage.c:1421
+#: clutter/clutter-stage.c:1431
msgid "Whether the stage should clear its contents"
msgstr ""
+#: clutter/clutter-stage.c:1444
+msgid "Accept Focus"
+msgstr ""
+
+#: clutter/clutter-stage.c:1445
+#, fuzzy
+msgid "Whether the stage should accept focus on show"
+msgstr "Si le texte doit être affiché en une seule ligne ou non"
+
#: clutter/clutter-state.c:1268
msgid "State"
msgstr "État"
msgid "Default transition duration"
msgstr ""
-#: clutter/clutter-text.c:2530
+#: clutter/clutter-text.c:2554
msgid "Font Name"
msgstr "Nom de la police"
-#: clutter/clutter-text.c:2531
+#: clutter/clutter-text.c:2555
msgid "The font to be used by the text"
msgstr "La police à utiliser par le texte"
-#: clutter/clutter-text.c:2548
+#: clutter/clutter-text.c:2572
msgid "Font Description"
msgstr "Description de la police"
-#: clutter/clutter-text.c:2549
+#: clutter/clutter-text.c:2573
msgid "The font description to be used"
msgstr "La description de la police à utiliser"
-#: clutter/clutter-text.c:2565
+#: clutter/clutter-text.c:2589
msgid "Text"
msgstr "Texte"
-#: clutter/clutter-text.c:2566
+#: clutter/clutter-text.c:2590
msgid "The text to render"
msgstr "Le texte à afficher"
-#: clutter/clutter-text.c:2580
+#: clutter/clutter-text.c:2604
msgid "Font Color"
msgstr "Couleur de la police"
-#: clutter/clutter-text.c:2581
+#: clutter/clutter-text.c:2605
msgid "Color of the font used by the text"
msgstr "La Couleur de la police utilisée par le texte"
-#: clutter/clutter-text.c:2595
+#: clutter/clutter-text.c:2619
msgid "Editable"
msgstr "Éditable"
-#: clutter/clutter-text.c:2596
+#: clutter/clutter-text.c:2620
msgid "Whether the text is editable"
msgstr ""
-#: clutter/clutter-text.c:2611
+#: clutter/clutter-text.c:2635
msgid "Selectable"
msgstr ""
-#: clutter/clutter-text.c:2612
+#: clutter/clutter-text.c:2636
msgid "Whether the text is selectable"
msgstr ""
-#: clutter/clutter-text.c:2626
+#: clutter/clutter-text.c:2650
msgid "Activatable"
msgstr ""
-#: clutter/clutter-text.c:2627
+#: clutter/clutter-text.c:2651
msgid "Whether pressing return causes the activate signal to be emitted"
msgstr ""
-#: clutter/clutter-text.c:2644
+#: clutter/clutter-text.c:2668
msgid "Whether the input cursor is visible"
msgstr ""
-#: clutter/clutter-text.c:2658 clutter/clutter-text.c:2659
+#: clutter/clutter-text.c:2682 clutter/clutter-text.c:2683
msgid "Cursor Color"
msgstr "La couleur du curseur"
-#: clutter/clutter-text.c:2673
+#: clutter/clutter-text.c:2697
msgid "Cursor Color Set"
msgstr "Couleur du curseur renseignée"
-#: clutter/clutter-text.c:2674
+#: clutter/clutter-text.c:2698
msgid "Whether the cursor color has been set"
msgstr "Si la couleur du curseur a été renseignée ou non"
-#: clutter/clutter-text.c:2689
+#: clutter/clutter-text.c:2713
msgid "Cursor Size"
msgstr "Taille du curseur"
-#: clutter/clutter-text.c:2690
+#: clutter/clutter-text.c:2714
msgid "The width of the cursor, in pixels"
msgstr "La taille du curseur, en pixels"
-#: clutter/clutter-text.c:2704
+#: clutter/clutter-text.c:2728
#, fuzzy
msgid "Cursor Position"
msgstr "La position du curseur"
-#: clutter/clutter-text.c:2705
+#: clutter/clutter-text.c:2729
msgid "The cursor position"
msgstr "La position du curseur"
-#: clutter/clutter-text.c:2720
+#: clutter/clutter-text.c:2744
msgid "Selection-bound"
msgstr ""
-#: clutter/clutter-text.c:2721
+#: clutter/clutter-text.c:2745
msgid "The cursor position of the other end of the selection"
msgstr ""
-#: clutter/clutter-text.c:2736 clutter/clutter-text.c:2737
+#: clutter/clutter-text.c:2760 clutter/clutter-text.c:2761
msgid "Selection Color"
msgstr ""
-#: clutter/clutter-text.c:2751
+#: clutter/clutter-text.c:2775
msgid "Selection Color Set"
msgstr ""
-#: clutter/clutter-text.c:2752
+#: clutter/clutter-text.c:2776
msgid "Whether the selection color has been set"
msgstr ""
-#: clutter/clutter-text.c:2767
+#: clutter/clutter-text.c:2791
msgid "Attributes"
msgstr ""
-#: clutter/clutter-text.c:2768
+#: clutter/clutter-text.c:2792
msgid "A list of style attributes to apply to the contents of the actor"
msgstr ""
-#: clutter/clutter-text.c:2790
+#: clutter/clutter-text.c:2814
msgid "Use markup"
msgstr ""
-#: clutter/clutter-text.c:2791
+#: clutter/clutter-text.c:2815
msgid "Whether or not the text includes Pango markup"
msgstr ""
-#: clutter/clutter-text.c:2807
+#: clutter/clutter-text.c:2831
msgid "Line wrap"
msgstr ""
-#: clutter/clutter-text.c:2808
+#: clutter/clutter-text.c:2832
msgid "If set, wrap the lines if the text becomes too wide"
msgstr ""
-#: clutter/clutter-text.c:2823
+#: clutter/clutter-text.c:2847
msgid "Line wrap mode"
msgstr ""
-#: clutter/clutter-text.c:2824
+#: clutter/clutter-text.c:2848
msgid "Control how line-wrapping is done"
msgstr ""
-#: clutter/clutter-text.c:2839
+#: clutter/clutter-text.c:2863
msgid "Ellipsize"
msgstr ""
-#: clutter/clutter-text.c:2840
+#: clutter/clutter-text.c:2864
msgid "The preferred place to ellipsize the string"
msgstr ""
-#: clutter/clutter-text.c:2856
+#: clutter/clutter-text.c:2880
msgid "Line Alignment"
msgstr ""
-#: clutter/clutter-text.c:2857
+#: clutter/clutter-text.c:2881
msgid "The preferred alignment for the string, for multi-line text"
msgstr ""
-#: clutter/clutter-text.c:2873
+#: clutter/clutter-text.c:2897
msgid "Justify"
msgstr ""
-#: clutter/clutter-text.c:2874
+#: clutter/clutter-text.c:2898
msgid "Whether the text should be justified"
msgstr ""
-#: clutter/clutter-text.c:2889
+#: clutter/clutter-text.c:2913
msgid "Password Character"
msgstr ""
-#: clutter/clutter-text.c:2890
+#: clutter/clutter-text.c:2914
msgid "If non-zero, use this character to display the actor's contents"
msgstr ""
-#: clutter/clutter-text.c:2904
+#: clutter/clutter-text.c:2928
msgid "Max Length"
msgstr "Longueur maximale"
-#: clutter/clutter-text.c:2905
+#: clutter/clutter-text.c:2929
msgid "Maximum length of the text inside the actor"
msgstr "Longueur maximale du texte à l'intérieur de l'acteur"
-#: clutter/clutter-text.c:2928
+#: clutter/clutter-text.c:2952
msgid "Single Line Mode"
msgstr "Mode ligne"
-#: clutter/clutter-text.c:2929
+#: clutter/clutter-text.c:2953
msgid "Whether the text should be a single line"
msgstr "Si le texte doit être affiché en une seule ligne ou non"
msgid "Shape actor with alpha channel when picking"
msgstr ""
-#: clutter/glx/clutter-backend-glx.c:128
+#: clutter/glx/clutter-backend-glx.c:131
msgid "VBlank method to be used (none, dri or glx)"
msgstr ""
-#: clutter/x11/clutter-backend-x11.c:364
+#: clutter/x11/clutter-backend-x11.c:473
msgid "X display to use"
msgstr "Affichage X à utiliser"
-#: clutter/x11/clutter-backend-x11.c:370
+#: clutter/x11/clutter-backend-x11.c:479
msgid "X screen to use"
msgstr "Écran X à utiliser"
-#: clutter/x11/clutter-backend-x11.c:375
+#: clutter/x11/clutter-backend-x11.c:484
msgid "Make X calls synchronous"
msgstr "Rendre les appels X synchrones"
-#: clutter/x11/clutter-backend-x11.c:382
+#: clutter/x11/clutter-backend-x11.c:491
msgid "Enable XInput support"
msgstr "Activer le support XInput"
"Project-Id-Version: clutter 1.3.14\n"
"Report-Msgid-Bugs-To: http://bugzilla.clutter-project.org/enter_bug.cgi?"
"product=clutter\n"
-"POT-Creation-Date: 2010-12-17 15:51+0000\n"
+"POT-Creation-Date: 2011-02-07 15:50+0000\n"
"PO-Revision-Date: 2010-10-05 20:42+0700\n"
"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
"Language-Team: GNOME Indonesian Translation Team <gnome@i15n.org>\n"
"X-Poedit-Language: Indonesian\n"
"X-Poedit-Country: Indonesia\n"
-#: clutter/clutter-actor.c:3480
+#: clutter/clutter-actor.c:3478
msgid "X coordinate"
msgstr "Koordinat X"
-#: clutter/clutter-actor.c:3481
+#: clutter/clutter-actor.c:3479
msgid "X coordinate of the actor"
msgstr "Koordinat X dari aktor"
-#: clutter/clutter-actor.c:3496
+#: clutter/clutter-actor.c:3494
msgid "Y coordinate"
msgstr "Koordinat Y"
-#: clutter/clutter-actor.c:3497
+#: clutter/clutter-actor.c:3495
msgid "Y coordinate of the actor"
msgstr "Koordinat Y dari aktor"
-#: clutter/clutter-actor.c:3512 clutter/clutter-behaviour-ellipse.c:475
+#: clutter/clutter-actor.c:3510 clutter/clutter-behaviour-ellipse.c:474
msgid "Width"
msgstr "Lebar"
-#: clutter/clutter-actor.c:3513
+#: clutter/clutter-actor.c:3511
msgid "Width of the actor"
msgstr "Lebar aktor"
-#: clutter/clutter-actor.c:3527 clutter/clutter-behaviour-ellipse.c:491
+#: clutter/clutter-actor.c:3525 clutter/clutter-behaviour-ellipse.c:490
msgid "Height"
msgstr "Tinggi"
-#: clutter/clutter-actor.c:3528
+#: clutter/clutter-actor.c:3526
msgid "Height of the actor"
msgstr "Tinggi aktor"
-#: clutter/clutter-actor.c:3546
+#: clutter/clutter-actor.c:3544
msgid "Fixed X"
msgstr "X Tetap"
-#: clutter/clutter-actor.c:3547
+#: clutter/clutter-actor.c:3545
msgid "Forced X position of the actor"
msgstr "Posisi X aktor yang dipaksakan"
-#: clutter/clutter-actor.c:3565
+#: clutter/clutter-actor.c:3563
msgid "Fixed Y"
msgstr "Y Tetap"
-#: clutter/clutter-actor.c:3566
+#: clutter/clutter-actor.c:3564
msgid "Forced Y position of the actor"
msgstr "Posisi Y aktor yang dipaksakan"
-#: clutter/clutter-actor.c:3582
+#: clutter/clutter-actor.c:3580
msgid "Fixed position set"
msgstr "Posisi yang ditetapkan ditata"
-#: clutter/clutter-actor.c:3583
+#: clutter/clutter-actor.c:3581
msgid "Whether to use fixed positioning for the actor"
msgstr "Apakah memakai penempatan yang ditetapkan bagi aktor"
-#: clutter/clutter-actor.c:3605
+#: clutter/clutter-actor.c:3603
msgid "Min Width"
msgstr "Lebar Min"
-#: clutter/clutter-actor.c:3606
+#: clutter/clutter-actor.c:3604
msgid "Forced minimum width request for the actor"
msgstr "Permintaan lebar minimal yang dipaksakan bagi aktor"
-#: clutter/clutter-actor.c:3625
+#: clutter/clutter-actor.c:3623
msgid "Min Height"
msgstr "Tinggi Min"
-#: clutter/clutter-actor.c:3626
+#: clutter/clutter-actor.c:3624
msgid "Forced minimum height request for the actor"
msgstr "Permintaan tinggi minimal yang dipaksakan bagi aktor"
-#: clutter/clutter-actor.c:3645
+#: clutter/clutter-actor.c:3643
msgid "Natural Width"
msgstr "Lebar Alami"
-#: clutter/clutter-actor.c:3646
+#: clutter/clutter-actor.c:3644
msgid "Forced natural width request for the actor"
msgstr "Permintaan lebar alami yang dipaksakan bagi aktor"
-#: clutter/clutter-actor.c:3665
+#: clutter/clutter-actor.c:3663
msgid "Natural Height"
msgstr "Tinggi Alami"
-#: clutter/clutter-actor.c:3666
+#: clutter/clutter-actor.c:3664
msgid "Forced natural height request for the actor"
msgstr "Permintaan tinggi alami yang dipaksakan bagi aktor"
-#: clutter/clutter-actor.c:3682
+#: clutter/clutter-actor.c:3680
msgid "Minimum width set"
msgstr "Lebar minimal ditata"
-#: clutter/clutter-actor.c:3683
+#: clutter/clutter-actor.c:3681
msgid "Whether to use the min-width property"
msgstr "Apakah memakai properti min-width"
-#: clutter/clutter-actor.c:3698
+#: clutter/clutter-actor.c:3696
msgid "Minimum height set"
msgstr "Tinggi minimal ditata"
-#: clutter/clutter-actor.c:3699
+#: clutter/clutter-actor.c:3697
msgid "Whether to use the min-height property"
msgstr "Apakah memakai properti min-height"
-#: clutter/clutter-actor.c:3714
+#: clutter/clutter-actor.c:3712
msgid "Natural width set"
msgstr "Lebar alami ditata"
-#: clutter/clutter-actor.c:3715
+#: clutter/clutter-actor.c:3713
msgid "Whether to use the natural-width property"
msgstr "Apakah memakai properti natural-width"
-#: clutter/clutter-actor.c:3732
+#: clutter/clutter-actor.c:3730
msgid "Natural height set"
msgstr "Tinggi alami ditata"
-#: clutter/clutter-actor.c:3733
+#: clutter/clutter-actor.c:3731
msgid "Whether to use the natural-height property"
msgstr "Apakah memakai properti natural-height"
-#: clutter/clutter-actor.c:3752
+#: clutter/clutter-actor.c:3750
msgid "Allocation"
msgstr "Alokasi"
-#: clutter/clutter-actor.c:3753
+#: clutter/clutter-actor.c:3751
msgid "The actor's allocation"
msgstr "Alokasi aktor"
-#: clutter/clutter-actor.c:3809
+#: clutter/clutter-actor.c:3807
msgid "Request Mode"
msgstr "Moda Permintaan"
-#: clutter/clutter-actor.c:3810
+#: clutter/clutter-actor.c:3808
msgid "The actor's request mode"
msgstr "Moda permintaan aktor"
-#: clutter/clutter-actor.c:3825
+#: clutter/clutter-actor.c:3823
msgid "Depth"
msgstr "Kedalaman"
-#: clutter/clutter-actor.c:3826
+#: clutter/clutter-actor.c:3824
msgid "Position on the Z axis"
msgstr "Posisi pada sumbu Z"
-#: clutter/clutter-actor.c:3840
+#: clutter/clutter-actor.c:3838
#, fuzzy
msgid "Opacity"
msgstr "Ketransparanan"
-#: clutter/clutter-actor.c:3841
+#: clutter/clutter-actor.c:3839
msgid "Opacity of an actor"
msgstr "Tingkat transparansi aktor"
-#: clutter/clutter-actor.c:3856
+#: clutter/clutter-actor.c:3854
msgid "Visible"
msgstr "Tampak"
-#: clutter/clutter-actor.c:3857
+#: clutter/clutter-actor.c:3855
msgid "Whether the actor is visible or not"
msgstr "Apakah aktor nampak atau tidak"
-#: clutter/clutter-actor.c:3872
+#: clutter/clutter-actor.c:3870
msgid "Mapped"
msgstr "Dipetakan"
-#: clutter/clutter-actor.c:3873
+#: clutter/clutter-actor.c:3871
msgid "Whether the actor will be painted"
msgstr "Apakah aktor akan digambar"
-#: clutter/clutter-actor.c:3887
+#: clutter/clutter-actor.c:3885
msgid "Realized"
msgstr "Direalisasikan"
-#: clutter/clutter-actor.c:3888
+#: clutter/clutter-actor.c:3886
msgid "Whether the actor has been realized"
msgstr "Apakah aktor telah direalisasikan"
-#: clutter/clutter-actor.c:3904
+#: clutter/clutter-actor.c:3902
msgid "Reactive"
msgstr "Reaktif"
-#: clutter/clutter-actor.c:3905
+#: clutter/clutter-actor.c:3903
msgid "Whether the actor is reactive to events"
msgstr "Apakah aktor reaktif terhadap kejadian"
-#: clutter/clutter-actor.c:3917
+#: clutter/clutter-actor.c:3915
msgid "Has Clip"
msgstr "Punya Klip"
-#: clutter/clutter-actor.c:3918
+#: clutter/clutter-actor.c:3916
msgid "Whether the actor has a clip set"
msgstr "Apakah aktor telah ditata punya klip"
-#: clutter/clutter-actor.c:3933
+#: clutter/clutter-actor.c:3931
msgid "Clip"
msgstr "Klip"
-#: clutter/clutter-actor.c:3934
+#: clutter/clutter-actor.c:3932
msgid "The clip region for the actor"
msgstr "Wilayah klip bagi aktor"
-#: clutter/clutter-actor.c:3948 clutter/clutter-actor-meta.c:205
-#: clutter/clutter-binding-pool.c:320 clutter/clutter-input-device.c:151
+#: clutter/clutter-actor.c:3946 clutter/clutter-actor-meta.c:205
+#: clutter/clutter-binding-pool.c:319 clutter/clutter-input-device.c:235
msgid "Name"
msgstr "Nama"
-#: clutter/clutter-actor.c:3949
+#: clutter/clutter-actor.c:3947
msgid "Name of the actor"
msgstr "Nama aktor"
-#: clutter/clutter-actor.c:3963
+#: clutter/clutter-actor.c:3961
msgid "Scale X"
msgstr "Skala X"
-#: clutter/clutter-actor.c:3964
+#: clutter/clutter-actor.c:3962
msgid "Scale factor on the X axis"
msgstr "Faktor skala pada sumbu X"
-#: clutter/clutter-actor.c:3979
+#: clutter/clutter-actor.c:3977
msgid "Scale Y"
msgstr "Skala Y"
-#: clutter/clutter-actor.c:3980
+#: clutter/clutter-actor.c:3978
msgid "Scale factor on the Y axis"
msgstr "Faktor skala pada sumbu Y"
-#: clutter/clutter-actor.c:3995
+#: clutter/clutter-actor.c:3993
msgid "Scale Center X"
msgstr "Pusat Skala X"
-#: clutter/clutter-actor.c:3996
+#: clutter/clutter-actor.c:3994
msgid "Horizontal scale center"
msgstr "Pusat skala horisontal"
-#: clutter/clutter-actor.c:4011
+#: clutter/clutter-actor.c:4009
msgid "Scale Center Y"
msgstr "Pusat Skala Y"
-#: clutter/clutter-actor.c:4012
+#: clutter/clutter-actor.c:4010
msgid "Vertical scale center"
msgstr "Pusat skala vertikal"
-#: clutter/clutter-actor.c:4027
+#: clutter/clutter-actor.c:4025
msgid "Scale Gravity"
msgstr "Gravitasi Skala"
-#: clutter/clutter-actor.c:4028
+#: clutter/clutter-actor.c:4026
msgid "The center of scaling"
msgstr "Pusat penskalaan"
-#: clutter/clutter-actor.c:4045
+#: clutter/clutter-actor.c:4043
msgid "Rotation Angle X"
msgstr "Sudut Rotasi X"
-#: clutter/clutter-actor.c:4046
+#: clutter/clutter-actor.c:4044
msgid "The rotation angle on the X axis"
msgstr "Sudut rotasi dari sumbu X"
-#: clutter/clutter-actor.c:4061
+#: clutter/clutter-actor.c:4059
msgid "Rotation Angle Y"
msgstr "Sudut Rotasi Y"
-#: clutter/clutter-actor.c:4062
+#: clutter/clutter-actor.c:4060
msgid "The rotation angle on the Y axis"
msgstr "Sudut rotasi dari sumbu Y"
-#: clutter/clutter-actor.c:4077
+#: clutter/clutter-actor.c:4075
msgid "Rotation Angle Z"
msgstr "Sudut Rotasi Z"
-#: clutter/clutter-actor.c:4078
+#: clutter/clutter-actor.c:4076
msgid "The rotation angle on the Z axis"
msgstr "Sudut rotasi dari sumbu Z"
-#: clutter/clutter-actor.c:4093
+#: clutter/clutter-actor.c:4091
msgid "Rotation Center X"
msgstr "Pusat Rotasi X"
-#: clutter/clutter-actor.c:4094
+#: clutter/clutter-actor.c:4092
msgid "The rotation center on the X axis"
msgstr "Pusat rotasi pada sumbu X"
-#: clutter/clutter-actor.c:4110
+#: clutter/clutter-actor.c:4108
msgid "Rotation Center Y"
msgstr "Pusat Rotasi Y"
-#: clutter/clutter-actor.c:4111
+#: clutter/clutter-actor.c:4109
msgid "The rotation center on the Y axis"
msgstr "Pusat rotasi pada sumbu Y"
-#: clutter/clutter-actor.c:4127
+#: clutter/clutter-actor.c:4125
msgid "Rotation Center Z"
msgstr "Pusat Rotasi Z"
-#: clutter/clutter-actor.c:4128
+#: clutter/clutter-actor.c:4126
msgid "The rotation center on the Z axis"
msgstr "Pusat rotasi pada sumbu Z"
-#: clutter/clutter-actor.c:4144
+#: clutter/clutter-actor.c:4142
msgid "Rotation Center Z Gravity"
msgstr "Gravitasi Z Pusat Rotasi"
-#: clutter/clutter-actor.c:4145
+#: clutter/clutter-actor.c:4143
msgid "Center point for rotation around the Z axis"
msgstr "Titik pusat rotasi seputar sumbu Z"
-#: clutter/clutter-actor.c:4163
+#: clutter/clutter-actor.c:4161
msgid "Anchor X"
msgstr "Jangkar X"
-#: clutter/clutter-actor.c:4164
+#: clutter/clutter-actor.c:4162
msgid "X coordinate of the anchor point"
msgstr "Koordinat X titik jangkar"
-#: clutter/clutter-actor.c:4180
+#: clutter/clutter-actor.c:4178
msgid "Anchor Y"
msgstr "Jangkar Y"
-#: clutter/clutter-actor.c:4181
+#: clutter/clutter-actor.c:4179
msgid "Y coordinate of the anchor point"
msgstr "Koordinat Y titik jangkar"
-#: clutter/clutter-actor.c:4196
+#: clutter/clutter-actor.c:4194
msgid "Anchor Gravity"
msgstr "Gravitasi Jangkar"
-#: clutter/clutter-actor.c:4197
+#: clutter/clutter-actor.c:4195
msgid "The anchor point as a ClutterGravity"
msgstr ""
-#: clutter/clutter-actor.c:4216
+#: clutter/clutter-actor.c:4214
msgid "Show on set parent"
msgstr ""
-#: clutter/clutter-actor.c:4217
+#: clutter/clutter-actor.c:4215
msgid "Whether the actor is shown when parented"
msgstr ""
-#: clutter/clutter-actor.c:4237
+#: clutter/clutter-actor.c:4235
msgid "Clip to Allocation"
msgstr ""
-#: clutter/clutter-actor.c:4238
+#: clutter/clutter-actor.c:4236
msgid "Sets the clip region to track the actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:4248
+#: clutter/clutter-actor.c:4246
msgid "Text Direction"
msgstr "Arah Teks"
-#: clutter/clutter-actor.c:4249
+#: clutter/clutter-actor.c:4247
msgid "Direction of the text"
msgstr "Arah teks"
-#: clutter/clutter-actor.c:4267
+#: clutter/clutter-actor.c:4265
msgid "Has Pointer"
msgstr "Punya Penunjuk"
-#: clutter/clutter-actor.c:4268
+#: clutter/clutter-actor.c:4266
msgid "Whether the actor contains the pointer of an input device"
msgstr "Apakah aktor memuat penunjuk dari suatu perangkat masukan"
-#: clutter/clutter-actor.c:4285
+#: clutter/clutter-actor.c:4283
msgid "Actions"
msgstr "Aksi"
-#: clutter/clutter-actor.c:4286
+#: clutter/clutter-actor.c:4284
msgid "Adds an action to the actor"
msgstr "Tambahkan aksi ke aktor"
-#: clutter/clutter-actor.c:4300
+#: clutter/clutter-actor.c:4298
msgid "Constraints"
msgstr "Kendala"
-#: clutter/clutter-actor.c:4301
+#: clutter/clutter-actor.c:4299
msgid "Adds a constraint to the actor"
msgstr "Tambahkan kendala ke aktor"
msgid "The name of the meta"
msgstr "Perubah Meta"
-#: clutter/clutter-actor-meta.c:219 clutter/clutter-shader.c:261
+#: clutter/clutter-actor-meta.c:219 clutter/clutter-input-device.c:314
+#: clutter/clutter-shader.c:295
#, fuzzy
msgid "Enabled"
msgstr "Diaktifkan"
msgid "Whether the meta is enabled"
msgstr "Menentukan apkaah aksi diaktifkan"
-#: clutter/clutter-align-constraint.c:231
-#: clutter/clutter-bind-constraint.c:286 clutter/clutter-clone.c:322
+#: clutter/clutter-align-constraint.c:252
+#: clutter/clutter-bind-constraint.c:316 clutter/clutter-clone.c:322
msgid "Source"
msgstr "Sumber"
-#: clutter/clutter-align-constraint.c:232
+#: clutter/clutter-align-constraint.c:253
msgid "The source of the alignment"
msgstr "Sumber perataan"
-#: clutter/clutter-align-constraint.c:245
+#: clutter/clutter-align-constraint.c:266
#, fuzzy
msgid "Align Axis"
msgstr "Rata kanan"
-#: clutter/clutter-align-constraint.c:246
+#: clutter/clutter-align-constraint.c:267
msgid "The axis to align the position to"
msgstr ""
-#: clutter/clutter-align-constraint.c:265
-#: clutter/clutter-desaturate-effect.c:309
+#: clutter/clutter-align-constraint.c:286
+#: clutter/clutter-desaturate-effect.c:307
msgid "Factor"
msgstr "Faktor"
-#: clutter/clutter-align-constraint.c:266
+#: clutter/clutter-align-constraint.c:287
msgid "The alignment factor, between 0.0 and 1.0"
msgstr ""
#: clutter/clutter-alpha.c:339 clutter/clutter-animation.c:523
-#: clutter/clutter-animator.c:1801
+#: clutter/clutter-animator.c:1802
msgid "Timeline"
msgstr ""
msgid "The mode of the animation"
msgstr "Mode animasi gambar"
-#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1785
+#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1786
#: clutter/clutter-media.c:194 clutter/clutter-state.c:1282
msgid "Duration"
msgstr "Durasi"
msgid "The timeline used by the animation"
msgstr ""
-#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:299
+#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:298
msgid "Alpha"
msgstr "Alfa"
msgid "The alpha used by the animation"
msgstr ""
-#: clutter/clutter-animator.c:1786
+#: clutter/clutter-animator.c:1787
#, fuzzy
msgid "The duration of the animation"
msgstr "Durasi animasi"
-#: clutter/clutter-animator.c:1802
+#: clutter/clutter-animator.c:1803
#, fuzzy
msgid "The timeline of the animation"
msgstr "Pilih sebuah animasi"
-#: clutter/clutter-behaviour.c:300
+#: clutter/clutter-behaviour.c:299
msgid "Alpha Object to drive the behaviour"
msgstr ""
-#: clutter/clutter-behaviour-depth.c:175
+#: clutter/clutter-behaviour-depth.c:174
#, fuzzy
msgid "Start Depth"
msgstr "_Kedalaman Warna:"
-#: clutter/clutter-behaviour-depth.c:176
+#: clutter/clutter-behaviour-depth.c:175
msgid "Initial depth to apply"
msgstr ""
-#: clutter/clutter-behaviour-depth.c:191
+#: clutter/clutter-behaviour-depth.c:190
#, fuzzy
msgid "End Depth"
msgstr "_Kedalaman Warna:"
-#: clutter/clutter-behaviour-depth.c:192
+#: clutter/clutter-behaviour-depth.c:191
msgid "Final depth to apply"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-ellipse.c:394
#, fuzzy
msgid "Start Angle"
msgstr "Menu S_udut"
-#: clutter/clutter-behaviour-ellipse.c:396
-#: clutter/clutter-behaviour-rotate.c:277
+#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-rotate.c:276
#, fuzzy
msgid "Initial angle"
msgstr "Menu S_udut"
-#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-ellipse.c:410
#, fuzzy
msgid "End Angle"
msgstr "Menu S_udut"
-#: clutter/clutter-behaviour-ellipse.c:412
-#: clutter/clutter-behaviour-rotate.c:295
+#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-rotate.c:294
#, fuzzy
msgid "Final angle"
msgstr "Menu S_udut"
-#: clutter/clutter-behaviour-ellipse.c:427
+#: clutter/clutter-behaviour-ellipse.c:426
#, fuzzy
msgid "Angle x tilt"
msgstr "Menu S_udut"
-#: clutter/clutter-behaviour-ellipse.c:428
+#: clutter/clutter-behaviour-ellipse.c:427
msgid "Tilt of the ellipse around x axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:443
+#: clutter/clutter-behaviour-ellipse.c:442
#, fuzzy
msgid "Angle y tilt"
msgstr "Menu S_udut"
-#: clutter/clutter-behaviour-ellipse.c:444
+#: clutter/clutter-behaviour-ellipse.c:443
msgid "Tilt of the ellipse around y axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:459
+#: clutter/clutter-behaviour-ellipse.c:458
#, fuzzy
msgid "Angle z tilt"
msgstr "Menu S_udut"
-#: clutter/clutter-behaviour-ellipse.c:460
+#: clutter/clutter-behaviour-ellipse.c:459
msgid "Tilt of the ellipse around z axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:476
+#: clutter/clutter-behaviour-ellipse.c:475
#, fuzzy
msgid "Width of the ellipse"
msgstr "_Lebar tetap:"
-#: clutter/clutter-behaviour-ellipse.c:492
+#: clutter/clutter-behaviour-ellipse.c:491
#, fuzzy
msgid "Height of ellipse"
msgstr "<b>Tinggi:</b> %d piksel\n"
-#: clutter/clutter-behaviour-ellipse.c:507
+#: clutter/clutter-behaviour-ellipse.c:506
#, fuzzy
msgid "Center"
msgstr "Tengah"
-#: clutter/clutter-behaviour-ellipse.c:508
+#: clutter/clutter-behaviour-ellipse.c:507
#, fuzzy
msgid "Center of ellipse"
msgstr "Pusat Pengaturan"
-#: clutter/clutter-behaviour-ellipse.c:522
-#: clutter/clutter-behaviour-rotate.c:330
+#: clutter/clutter-behaviour-ellipse.c:521
+#: clutter/clutter-behaviour-rotate.c:329
msgid "Direction"
msgstr "Arah"
-#: clutter/clutter-behaviour-ellipse.c:523
-#: clutter/clutter-behaviour-rotate.c:331
+#: clutter/clutter-behaviour-ellipse.c:522
+#: clutter/clutter-behaviour-rotate.c:330
#, fuzzy
msgid "Direction of rotation"
msgstr "Putaran Jarum Jam"
-#: clutter/clutter-behaviour-opacity.c:178
+#: clutter/clutter-behaviour-opacity.c:177
#, fuzzy
msgid "Opacity Start"
msgstr "Jalankan program"
-#: clutter/clutter-behaviour-opacity.c:179
+#: clutter/clutter-behaviour-opacity.c:178
msgid "Initial opacity level"
msgstr ""
-#: clutter/clutter-behaviour-opacity.c:196
+#: clutter/clutter-behaviour-opacity.c:195
#, fuzzy
msgid "Opacity End"
msgstr "KP_End"
-#: clutter/clutter-behaviour-opacity.c:197
+#: clutter/clutter-behaviour-opacity.c:196
msgid "Final opacity level"
msgstr ""
-#: clutter/clutter-behaviour-path.c:220
+#: clutter/clutter-behaviour-path.c:219
msgid "Path"
msgstr "Path"
-#: clutter/clutter-behaviour-path.c:221
+#: clutter/clutter-behaviour-path.c:220
msgid "The ClutterPath object representing the path to animate along"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:276
+#: clutter/clutter-behaviour-rotate.c:275
#, fuzzy
msgid "Angle Begin"
msgstr "KP_Begin"
-#: clutter/clutter-behaviour-rotate.c:294
+#: clutter/clutter-behaviour-rotate.c:293
#, fuzzy
msgid "Angle End"
msgstr "KP_End"
-#: clutter/clutter-behaviour-rotate.c:312
+#: clutter/clutter-behaviour-rotate.c:311
#, fuzzy
msgid "Axis"
msgstr "Sumbu"
-#: clutter/clutter-behaviour-rotate.c:313
+#: clutter/clutter-behaviour-rotate.c:312
#, fuzzy
msgid "Axis of rotation"
msgstr "Putaran Jarum Jam"
-#: clutter/clutter-behaviour-rotate.c:348
+#: clutter/clutter-behaviour-rotate.c:347
msgid "Center X"
msgstr "Pusat X"
-#: clutter/clutter-behaviour-rotate.c:349
+#: clutter/clutter-behaviour-rotate.c:348
msgid "X coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:366
+#: clutter/clutter-behaviour-rotate.c:365
msgid "Center Y"
msgstr "Pusat Y"
-#: clutter/clutter-behaviour-rotate.c:367
+#: clutter/clutter-behaviour-rotate.c:366
msgid "Y coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:384
+#: clutter/clutter-behaviour-rotate.c:383
msgid "Center Z"
msgstr "Pusat Z"
-#: clutter/clutter-behaviour-rotate.c:385
+#: clutter/clutter-behaviour-rotate.c:384
msgid "Z coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:219
+#: clutter/clutter-behaviour-scale.c:218
#, fuzzy
msgid "X Start Scale"
msgstr "Skala Beaufort"
-#: clutter/clutter-behaviour-scale.c:220
+#: clutter/clutter-behaviour-scale.c:219
msgid "Initial scale on the X axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:238
+#: clutter/clutter-behaviour-scale.c:237
#, fuzzy
msgid "X End Scale"
msgstr "Skala Beaufort"
-#: clutter/clutter-behaviour-scale.c:239
+#: clutter/clutter-behaviour-scale.c:238
msgid "Final scale on the X axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:257
+#: clutter/clutter-behaviour-scale.c:256
#, fuzzy
msgid "Y Start Scale"
msgstr "Skala Beaufort"
-#: clutter/clutter-behaviour-scale.c:258
+#: clutter/clutter-behaviour-scale.c:257
msgid "Initial scale on the Y axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:276
+#: clutter/clutter-behaviour-scale.c:275
#, fuzzy
msgid "Y End Scale"
msgstr "Skala Beaufort"
-#: clutter/clutter-behaviour-scale.c:277
+#: clutter/clutter-behaviour-scale.c:276
msgid "Final scale on the Y axis"
msgstr ""
-#: clutter/clutter-bind-constraint.c:287
+#: clutter/clutter-bind-constraint.c:317
#, fuzzy
msgid "The source of the binding"
msgstr "Asal IP"
-#: clutter/clutter-bind-constraint.c:300
+#: clutter/clutter-bind-constraint.c:330
#, fuzzy
msgid "Coordinate"
msgstr "Koordinat X"
-#: clutter/clutter-bind-constraint.c:301
+#: clutter/clutter-bind-constraint.c:331
#, fuzzy
msgid "The coordinate to bind"
msgstr "Koordinat X dari kotak untuk merekam"
-#: clutter/clutter-bind-constraint.c:315
+#: clutter/clutter-bind-constraint.c:345
msgid "Offset"
msgstr "Ofset"
-#: clutter/clutter-bind-constraint.c:316
+#: clutter/clutter-bind-constraint.c:346
msgid "The offset in pixels to apply to the binding"
msgstr ""
msgid "Default vertical alignment for the actors inside the layout manager"
msgstr ""
-#: clutter/clutter-binding-pool.c:321
+#: clutter/clutter-binding-pool.c:320
msgid "The unique name of the binding pool"
msgstr ""
msgstr ""
#: clutter/clutter-box.c:514 clutter/clutter-rectangle.c:258
-#: clutter/clutter-stage.c:1307
+#: clutter/clutter-stage.c:1317
msgid "Color"
msgstr "Warna"
msgid "The actor wrapped by this data"
msgstr ""
-#: clutter/clutter-click-action.c:283
+#: clutter/clutter-click-action.c:302
#, fuzzy
msgid "Pressed"
msgstr "ditekan"
-#: clutter/clutter-click-action.c:284
+#: clutter/clutter-click-action.c:303
msgid "Whether the clickable should be in pressed state"
msgstr ""
-#: clutter/clutter-click-action.c:297
+#: clutter/clutter-click-action.c:316
msgid "Held"
msgstr ""
-#: clutter/clutter-click-action.c:298
+#: clutter/clutter-click-action.c:317
msgid "Whether the clickable has a grab"
msgstr ""
msgid "Specifies the actor to be cloned"
msgstr ""
-#: clutter/clutter-colorize-effect.c:309
+#: clutter/clutter-colorize-effect.c:307
msgid "Tint"
msgstr ""
-#: clutter/clutter-colorize-effect.c:310
+#: clutter/clutter-colorize-effect.c:308
#, fuzzy
msgid "The tint to apply"
msgstr "Stash yang akan Diterapkan"
msgid "The material to be used when painting the back of the actor"
msgstr ""
-#: clutter/clutter-desaturate-effect.c:310
+#: clutter/clutter-desaturate-effect.c:308
#, fuzzy
msgid "The desaturation factor"
msgstr "Faktor koreksi"
-#: clutter/clutter-device-manager.c:130
+#: clutter/clutter-device-manager.c:130 clutter/clutter-input-device.c:343
#, fuzzy
msgid "Backend"
msgstr "Backend"
msgid "The ClutterBackend of the device manager"
msgstr "Peran perangkat di dalam manajer"
-#: clutter/clutter-drag-action.c:490
+#: clutter/clutter-drag-action.c:491
msgid "Horizontal Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:491
+#: clutter/clutter-drag-action.c:492
msgid "The horizontal amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:510
+#: clutter/clutter-drag-action.c:511
msgid "Vertical Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:511
+#: clutter/clutter-drag-action.c:512
msgid "The vertical amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:532
+#: clutter/clutter-drag-action.c:533
#, fuzzy
msgid "Drag Handle"
msgstr "Tampilkan handle"
-#: clutter/clutter-drag-action.c:533
+#: clutter/clutter-drag-action.c:534
msgid "The actor that is being dragged"
msgstr ""
-#: clutter/clutter-drag-action.c:546
+#: clutter/clutter-drag-action.c:547
#, fuzzy
msgid "Drag Axis"
msgstr " _Drag"
-#: clutter/clutter-drag-action.c:547
+#: clutter/clutter-drag-action.c:548
msgid "Constraints the dragging to an axis"
msgstr ""
msgid "Maximum height for each row"
msgstr ""
-#: clutter/clutter-input-device.c:134
+#: clutter/clutter-input-device.c:219
msgid "Id"
msgstr "Id"
-#: clutter/clutter-input-device.c:135
+#: clutter/clutter-input-device.c:220
msgid "Unique identifier of the device"
msgstr ""
-#: clutter/clutter-input-device.c:152
+#: clutter/clutter-input-device.c:236
#, fuzzy
msgid "The name of the device"
msgstr "Nama perangkat"
-#: clutter/clutter-input-device.c:167
+#: clutter/clutter-input-device.c:250
#, fuzzy
msgid "Device Type"
msgstr "_Tipe perangkat:"
-#: clutter/clutter-input-device.c:168
+#: clutter/clutter-input-device.c:251
#, fuzzy
msgid "The type of the device"
msgstr "_Tipe perangkat:"
+#: clutter/clutter-input-device.c:266
+#, fuzzy
+msgid "Device Manager"
+msgstr "Manajer"
+
+#: clutter/clutter-input-device.c:267
+msgid "The device manager instance"
+msgstr ""
+
+#: clutter/clutter-input-device.c:280
+#, fuzzy
+msgid "Device Mode"
+msgstr "_Tipe perangkat:"
+
+#: clutter/clutter-input-device.c:281
+#, fuzzy
+msgid "The mode of the device"
+msgstr "Nama perangkat"
+
+#: clutter/clutter-input-device.c:295
+#, fuzzy
+msgid "Has Cursor"
+msgstr "Bingkai Jendela"
+
+#: clutter/clutter-input-device.c:296
+#, fuzzy
+msgid "Whether the device has a cursor"
+msgstr "Apakah aktor telah ditata punya klip"
+
+#: clutter/clutter-input-device.c:315
+#, fuzzy
+msgid "Whether the device is enabled"
+msgstr "Menentukan apkaah aksi diaktifkan"
+
+#: clutter/clutter-input-device.c:328
+msgid "Number of Axes"
+msgstr ""
+
+#: clutter/clutter-input-device.c:329
+#, fuzzy
+msgid "The number of axes on the device"
+msgstr "Nama perangkat"
+
+#: clutter/clutter-input-device.c:344
+msgid "The backend instance"
+msgstr ""
+
#: clutter/clutter-interval.c:397
#, fuzzy
msgid "Value Type"
msgid "The manager that created this data"
msgstr ""
-#: clutter/clutter-main.c:756
+#: clutter/clutter-main.c:753
#, fuzzy
msgid "default:LTR"
msgstr "default:LTR"
-#: clutter/clutter-main.c:1560
+#: clutter/clutter-main.c:1557
msgid "Show frames per second"
msgstr ""
-#: clutter/clutter-main.c:1562
+#: clutter/clutter-main.c:1559
msgid "Default frame rate"
msgstr ""
-#: clutter/clutter-main.c:1564
+#: clutter/clutter-main.c:1561
#, fuzzy
msgid "Make all warnings fatal"
msgstr "Buat semua peringatan menjadi pesan fatal"
-#: clutter/clutter-main.c:1567
+#: clutter/clutter-main.c:1564
#, fuzzy
msgid "Direction for the text"
msgstr "Fonta untuk teks"
-#: clutter/clutter-main.c:1570
+#: clutter/clutter-main.c:1567
msgid "Disable mipmapping on text"
msgstr ""
-#: clutter/clutter-main.c:1573
+#: clutter/clutter-main.c:1570
msgid "Use 'fuzzy' picking"
msgstr ""
-#: clutter/clutter-main.c:1576
+#: clutter/clutter-main.c:1573
#, fuzzy
msgid "Clutter debugging flags to set"
msgstr "Bendera debug Gdk yang hendak dipasang"
-#: clutter/clutter-main.c:1578
+#: clutter/clutter-main.c:1575
#, fuzzy
msgid "Clutter debugging flags to unset"
msgstr "Bendera debug Gdk yang hendak dilepas"
-#: clutter/clutter-main.c:1582
+#: clutter/clutter-main.c:1579
msgid "Clutter profiling flags to set"
msgstr ""
-#: clutter/clutter-main.c:1584
+#: clutter/clutter-main.c:1581
msgid "Clutter profiling flags to unset"
msgstr ""
-#: clutter/clutter-main.c:1587
+#: clutter/clutter-main.c:1584
#, fuzzy
msgid "Enable accessibility"
msgstr "Aktifkan Aksesibilitas"
-#: clutter/clutter-main.c:1774
+#: clutter/clutter-main.c:1771
#, fuzzy
msgid "Clutter Options"
msgstr "Pilihan GTK+"
-#: clutter/clutter-main.c:1775
+#: clutter/clutter-main.c:1772
#, fuzzy
msgid "Show Clutter Options"
msgstr "Tampilkan opsi pengawa-kutuan"
msgid "The path of the currently parsed file"
msgstr ""
-#: clutter/clutter-shader.c:215
+#: clutter/clutter-shader.c:249
#, fuzzy
msgid "Vertex Source"
msgstr "Asal IP"
-#: clutter/clutter-shader.c:216
+#: clutter/clutter-shader.c:250
msgid "Source of vertex shader"
msgstr ""
-#: clutter/clutter-shader.c:230
+#: clutter/clutter-shader.c:264
#, fuzzy
msgid "Fragment Source"
msgstr "Asal IP"
-#: clutter/clutter-shader.c:231
+#: clutter/clutter-shader.c:265
msgid "Source of fragment shader"
msgstr ""
-#: clutter/clutter-shader.c:246
+#: clutter/clutter-shader.c:280
msgid "Compiled"
msgstr ""
-#: clutter/clutter-shader.c:247
+#: clutter/clutter-shader.c:281
msgid "Whether the shader is compiled and linked"
msgstr ""
-#: clutter/clutter-shader.c:262
+#: clutter/clutter-shader.c:296
#, fuzzy
msgid "Whether the shader is enabled"
msgstr "Menentukan apkaah aksi diaktifkan"
-#: clutter/clutter-shader.c:467
+#: clutter/clutter-shader.c:501
#, fuzzy, c-format
msgid "%s compilation failed: %s"
msgstr "Pemasangan Gagal"
-#: clutter/clutter-shader.c:468
+#: clutter/clutter-shader.c:502
#, fuzzy
msgid "Vertex shader"
msgstr "Bahasa CG Shader"
-#: clutter/clutter-shader.c:469
+#: clutter/clutter-shader.c:503
#, fuzzy
msgid "Fragment shader"
msgstr "Bahasa CG Shader"
msgid "The type of shader used"
msgstr "Jenis arsip terakhir yang digunakan"
-#: clutter/clutter-stage.c:1249
+#: clutter/clutter-stage.c:1259
#, fuzzy
msgid "Fullscreen Set"
msgstr "<small>Tata...</small>"
-#: clutter/clutter-stage.c:1250
+#: clutter/clutter-stage.c:1260
msgid "Whether the main stage is fullscreen"
msgstr ""
-#: clutter/clutter-stage.c:1266
+#: clutter/clutter-stage.c:1276
msgid "Offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1267
+#: clutter/clutter-stage.c:1277
msgid "Whether the main stage should be rendered offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1279 clutter/clutter-text.c:2643
+#: clutter/clutter-stage.c:1289 clutter/clutter-text.c:2667
#, fuzzy
msgid "Cursor Visible"
msgstr "Kursor Nampak"
-#: clutter/clutter-stage.c:1280
+#: clutter/clutter-stage.c:1290
msgid "Whether the mouse pointer is visible on the main stage"
msgstr ""
-#: clutter/clutter-stage.c:1294
+#: clutter/clutter-stage.c:1304
#, fuzzy
msgid "User Resizable"
msgstr "_Ganti Pengguna"
-#: clutter/clutter-stage.c:1295
+#: clutter/clutter-stage.c:1305
msgid "Whether the stage is able to be resized via user interaction"
msgstr ""
-#: clutter/clutter-stage.c:1308
+#: clutter/clutter-stage.c:1318
#, fuzzy
msgid "The color of the stage"
msgstr "Pilih warna"
-#: clutter/clutter-stage.c:1322
+#: clutter/clutter-stage.c:1332
msgid "Perspective"
msgstr ""
-#: clutter/clutter-stage.c:1323
+#: clutter/clutter-stage.c:1333
msgid "Perspective projection parameters"
msgstr ""
-#: clutter/clutter-stage.c:1338
+#: clutter/clutter-stage.c:1348
msgid "Title"
msgstr "Judul"
-#: clutter/clutter-stage.c:1339
+#: clutter/clutter-stage.c:1349
#, fuzzy
msgid "Stage Title"
msgstr "Jabatan"
-#: clutter/clutter-stage.c:1354
+#: clutter/clutter-stage.c:1364
msgid "Use Fog"
msgstr "Gunakan Kabut"
-#: clutter/clutter-stage.c:1355
+#: clutter/clutter-stage.c:1365
msgid "Whether to enable depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1369
+#: clutter/clutter-stage.c:1379
msgid "Fog"
msgstr "Kabut"
-#: clutter/clutter-stage.c:1370
+#: clutter/clutter-stage.c:1380
msgid "Settings for the depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1386
+#: clutter/clutter-stage.c:1396
msgid "Use Alpha"
msgstr "Gunakan Alfa"
-#: clutter/clutter-stage.c:1387
+#: clutter/clutter-stage.c:1397
msgid "Whether to honour the alpha component of the stage color"
msgstr ""
-#: clutter/clutter-stage.c:1403
+#: clutter/clutter-stage.c:1413
#, fuzzy
msgid "Key Focus"
msgstr "Ambil Fokus"
-#: clutter/clutter-stage.c:1404
+#: clutter/clutter-stage.c:1414
msgid "The currently key focused actor"
msgstr ""
-#: clutter/clutter-stage.c:1420
+#: clutter/clutter-stage.c:1430
msgid "No Clear Hint"
msgstr ""
-#: clutter/clutter-stage.c:1421
+#: clutter/clutter-stage.c:1431
msgid "Whether the stage should clear its contents"
msgstr ""
+#: clutter/clutter-stage.c:1444
+#, fuzzy
+msgid "Accept Focus"
+msgstr "Ambil Fokus"
+
+#: clutter/clutter-stage.c:1445
+msgid "Whether the stage should accept focus on show"
+msgstr ""
+
#: clutter/clutter-state.c:1268
#, fuzzy
msgid "State"
msgid "Default transition duration"
msgstr ""
-#: clutter/clutter-text.c:2530
+#: clutter/clutter-text.c:2554
msgid "Font Name"
msgstr "Nama Fonta"
-#: clutter/clutter-text.c:2531
+#: clutter/clutter-text.c:2555
msgid "The font to be used by the text"
msgstr ""
-#: clutter/clutter-text.c:2548
+#: clutter/clutter-text.c:2572
#, fuzzy
msgid "Font Description"
msgstr "Deskripsi fonta"
-#: clutter/clutter-text.c:2549
+#: clutter/clutter-text.c:2573
#, fuzzy
msgid "The font description to be used"
msgstr "Jenis huruf yang digunakan ketika mencetak"
-#: clutter/clutter-text.c:2565
+#: clutter/clutter-text.c:2589
msgid "Text"
msgstr "Teks"
-#: clutter/clutter-text.c:2566
+#: clutter/clutter-text.c:2590
#, fuzzy
msgid "The text to render"
msgstr "Teks yang hendak ditulis"
-#: clutter/clutter-text.c:2580
+#: clutter/clutter-text.c:2604
msgid "Font Color"
msgstr "Warna Fonta"
-#: clutter/clutter-text.c:2581
+#: clutter/clutter-text.c:2605
msgid "Color of the font used by the text"
msgstr ""
-#: clutter/clutter-text.c:2595
+#: clutter/clutter-text.c:2619
#, fuzzy
msgid "Editable"
msgstr "Dapat diedit"
-#: clutter/clutter-text.c:2596
+#: clutter/clutter-text.c:2620
#, fuzzy
msgid "Whether the text is editable"
msgstr "Apakah entri ini dapat diterjemahkan"
-#: clutter/clutter-text.c:2611
+#: clutter/clutter-text.c:2635
#, fuzzy
msgid "Selectable"
msgstr "Dapat dipilih"
-#: clutter/clutter-text.c:2612
+#: clutter/clutter-text.c:2636
#, fuzzy
msgid "Whether the text is selectable"
msgstr "Menentukan apakah teks ini disembunyikan"
-#: clutter/clutter-text.c:2626
+#: clutter/clutter-text.c:2650
#, fuzzy
msgid "Activatable"
msgstr "Dapat diaktifkan"
-#: clutter/clutter-text.c:2627
+#: clutter/clutter-text.c:2651
msgid "Whether pressing return causes the activate signal to be emitted"
msgstr ""
-#: clutter/clutter-text.c:2644
+#: clutter/clutter-text.c:2668
msgid "Whether the input cursor is visible"
msgstr ""
-#: clutter/clutter-text.c:2658 clutter/clutter-text.c:2659
+#: clutter/clutter-text.c:2682 clutter/clutter-text.c:2683
msgid "Cursor Color"
msgstr "Warna Kursor"
-#: clutter/clutter-text.c:2673
+#: clutter/clutter-text.c:2697
#, fuzzy
msgid "Cursor Color Set"
msgstr "Warna latar belakang sudah diset"
-#: clutter/clutter-text.c:2674
+#: clutter/clutter-text.c:2698
msgid "Whether the cursor color has been set"
msgstr ""
-#: clutter/clutter-text.c:2689
+#: clutter/clutter-text.c:2713
msgid "Cursor Size"
msgstr "Ukuran Kursor"
-#: clutter/clutter-text.c:2690
+#: clutter/clutter-text.c:2714
#, fuzzy
msgid "The width of the cursor, in pixels"
msgstr "Lebar cuplikan layar (dalam piksel):"
-#: clutter/clutter-text.c:2704
+#: clutter/clutter-text.c:2728
#, fuzzy
msgid "Cursor Position"
msgstr "Posisi Kursor"
-#: clutter/clutter-text.c:2705
+#: clutter/clutter-text.c:2729
#, fuzzy
msgid "The cursor position"
msgstr "Posisi Kursor"
-#: clutter/clutter-text.c:2720
+#: clutter/clutter-text.c:2744
#, fuzzy
msgid "Selection-bound"
msgstr "Batas Seleksi"
-#: clutter/clutter-text.c:2721
+#: clutter/clutter-text.c:2745
msgid "The cursor position of the other end of the selection"
msgstr ""
-#: clutter/clutter-text.c:2736 clutter/clutter-text.c:2737
+#: clutter/clutter-text.c:2760 clutter/clutter-text.c:2761
msgid "Selection Color"
msgstr "Warna Pilihan"
-#: clutter/clutter-text.c:2751
+#: clutter/clutter-text.c:2775
msgid "Selection Color Set"
msgstr "Warna Pilihan Ditata"
-#: clutter/clutter-text.c:2752
+#: clutter/clutter-text.c:2776
msgid "Whether the selection color has been set"
msgstr "Apakah warna pilihan telah ditata"
-#: clutter/clutter-text.c:2767
+#: clutter/clutter-text.c:2791
msgid "Attributes"
msgstr "Atribut"
-#: clutter/clutter-text.c:2768
+#: clutter/clutter-text.c:2792
msgid "A list of style attributes to apply to the contents of the actor"
msgstr ""
-#: clutter/clutter-text.c:2790
+#: clutter/clutter-text.c:2814
#, fuzzy
msgid "Use markup"
msgstr "Gunakan markup"
-#: clutter/clutter-text.c:2791
+#: clutter/clutter-text.c:2815
msgid "Whether or not the text includes Pango markup"
msgstr ""
-#: clutter/clutter-text.c:2807
+#: clutter/clutter-text.c:2831
#, fuzzy
msgid "Line wrap"
msgstr "Potong baris"
-#: clutter/clutter-text.c:2808
+#: clutter/clutter-text.c:2832
#, fuzzy
msgid "If set, wrap the lines if the text becomes too wide"
msgstr "Jika ini diset, baris akan dipotong bila terlalu lebar."
-#: clutter/clutter-text.c:2823
+#: clutter/clutter-text.c:2847
#, fuzzy
msgid "Line wrap mode"
msgstr "Mode pelipatan baris"
-#: clutter/clutter-text.c:2824
+#: clutter/clutter-text.c:2848
msgid "Control how line-wrapping is done"
msgstr ""
-#: clutter/clutter-text.c:2839
+#: clutter/clutter-text.c:2863
#, fuzzy
msgid "Ellipsize"
msgstr "Elipsis"
-#: clutter/clutter-text.c:2840
+#: clutter/clutter-text.c:2864
msgid "The preferred place to ellipsize the string"
msgstr ""
-#: clutter/clutter-text.c:2856
+#: clutter/clutter-text.c:2880
msgid "Line Alignment"
msgstr "Perataan Baris"
-#: clutter/clutter-text.c:2857
+#: clutter/clutter-text.c:2881
msgid "The preferred alignment for the string, for multi-line text"
msgstr ""
-#: clutter/clutter-text.c:2873
+#: clutter/clutter-text.c:2897
msgid "Justify"
msgstr "Diratakan"
-#: clutter/clutter-text.c:2874
+#: clutter/clutter-text.c:2898
msgid "Whether the text should be justified"
msgstr ""
-#: clutter/clutter-text.c:2889
+#: clutter/clutter-text.c:2913
msgid "Password Character"
msgstr "Karakter Sandi"
-#: clutter/clutter-text.c:2890
+#: clutter/clutter-text.c:2914
msgid "If non-zero, use this character to display the actor's contents"
msgstr ""
-#: clutter/clutter-text.c:2904
+#: clutter/clutter-text.c:2928
msgid "Max Length"
msgstr "Panjang Maks"
-#: clutter/clutter-text.c:2905
+#: clutter/clutter-text.c:2929
msgid "Maximum length of the text inside the actor"
msgstr ""
-#: clutter/clutter-text.c:2928
+#: clutter/clutter-text.c:2952
#, fuzzy
msgid "Single Line Mode"
msgstr "Moda Satu Baris"
-#: clutter/clutter-text.c:2929
+#: clutter/clutter-text.c:2953
msgid "Whether the text should be a single line"
msgstr ""
msgid "Shape actor with alpha channel when picking"
msgstr ""
-#: clutter/glx/clutter-backend-glx.c:128
+#: clutter/glx/clutter-backend-glx.c:131
msgid "VBlank method to be used (none, dri or glx)"
msgstr ""
-#: clutter/x11/clutter-backend-x11.c:364
+#: clutter/x11/clutter-backend-x11.c:473
#, fuzzy
msgid "X display to use"
msgstr "Tampilan X yang digunakan"
-#: clutter/x11/clutter-backend-x11.c:370
+#: clutter/x11/clutter-backend-x11.c:479
#, fuzzy
msgid "X screen to use"
msgstr "Layar X yang digunakan"
-#: clutter/x11/clutter-backend-x11.c:375
+#: clutter/x11/clutter-backend-x11.c:484
#, fuzzy
msgid "Make X calls synchronous"
msgstr "Buat panggilan X sinkronus"
-#: clutter/x11/clutter-backend-x11.c:382
+#: clutter/x11/clutter-backend-x11.c:491
#, fuzzy
msgid "Enable XInput support"
msgstr "Aktifkan dukungan IPv4"
"Project-Id-Version: clutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.clutter-project.org/enter_bug.cgi?"
"product=clutter\n"
-"POT-Creation-Date: 2010-12-17 15:51+0000\n"
+"POT-Creation-Date: 2011-02-07 15:50+0000\n"
"PO-Revision-Date: 2010-08-20 16:59+0200\n"
"Last-Translator: Luca Ferretti\n"
"Language-Team: Italian <tp@lists.linux.it>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: clutter/clutter-actor.c:3480
+#: clutter/clutter-actor.c:3478
msgid "X coordinate"
msgstr "Coordinata X"
-#: clutter/clutter-actor.c:3481
+#: clutter/clutter-actor.c:3479
msgid "X coordinate of the actor"
msgstr "Coordinata X dell'attore"
-#: clutter/clutter-actor.c:3496
+#: clutter/clutter-actor.c:3494
msgid "Y coordinate"
msgstr "Coordinata Y"
-#: clutter/clutter-actor.c:3497
+#: clutter/clutter-actor.c:3495
msgid "Y coordinate of the actor"
msgstr "Coordinata Y dell'attore"
-#: clutter/clutter-actor.c:3512 clutter/clutter-behaviour-ellipse.c:475
+#: clutter/clutter-actor.c:3510 clutter/clutter-behaviour-ellipse.c:474
msgid "Width"
msgstr "Larghezza"
-#: clutter/clutter-actor.c:3513
+#: clutter/clutter-actor.c:3511
msgid "Width of the actor"
msgstr "Larghezza dell'attore"
-#: clutter/clutter-actor.c:3527 clutter/clutter-behaviour-ellipse.c:491
+#: clutter/clutter-actor.c:3525 clutter/clutter-behaviour-ellipse.c:490
msgid "Height"
msgstr "Altezza"
-#: clutter/clutter-actor.c:3528
+#: clutter/clutter-actor.c:3526
msgid "Height of the actor"
msgstr "Altezza dell'attore"
-#: clutter/clutter-actor.c:3546
+#: clutter/clutter-actor.c:3544
msgid "Fixed X"
msgstr "Fissata X"
-#: clutter/clutter-actor.c:3547
+#: clutter/clutter-actor.c:3545
msgid "Forced X position of the actor"
msgstr "Posizione X forzata dell'attore"
-#: clutter/clutter-actor.c:3565
+#: clutter/clutter-actor.c:3563
msgid "Fixed Y"
msgstr "Fissata Y"
-#: clutter/clutter-actor.c:3566
+#: clutter/clutter-actor.c:3564
msgid "Forced Y position of the actor"
msgstr "Posizione Y forzata dell'attore"
-#: clutter/clutter-actor.c:3582
+#: clutter/clutter-actor.c:3580
msgid "Fixed position set"
msgstr "Imposta posizione fissa"
-#: clutter/clutter-actor.c:3583
+#: clutter/clutter-actor.c:3581
msgid "Whether to use fixed positioning for the actor"
msgstr "Se usare il posizionamento fisso per l'attore"
-#: clutter/clutter-actor.c:3605
+#: clutter/clutter-actor.c:3603
msgid "Min Width"
msgstr "Larghezza minima"
-#: clutter/clutter-actor.c:3606
+#: clutter/clutter-actor.c:3604
msgid "Forced minimum width request for the actor"
msgstr "Larghezza minima forzata richiesta per l'attore"
-#: clutter/clutter-actor.c:3625
+#: clutter/clutter-actor.c:3623
msgid "Min Height"
msgstr "Altezza minima"
-#: clutter/clutter-actor.c:3626
+#: clutter/clutter-actor.c:3624
msgid "Forced minimum height request for the actor"
msgstr "Altezza minima forzata richiesta per l'attore"
-#: clutter/clutter-actor.c:3645
+#: clutter/clutter-actor.c:3643
msgid "Natural Width"
msgstr "Larghezza naturale"
-#: clutter/clutter-actor.c:3646
+#: clutter/clutter-actor.c:3644
msgid "Forced natural width request for the actor"
msgstr "Larghezza naturale forzata richiesta per l'attore"
-#: clutter/clutter-actor.c:3665
+#: clutter/clutter-actor.c:3663
msgid "Natural Height"
msgstr "Altezza naturale"
-#: clutter/clutter-actor.c:3666
+#: clutter/clutter-actor.c:3664
msgid "Forced natural height request for the actor"
msgstr "Altezza naturale forzata richiesta per l'attore"
-#: clutter/clutter-actor.c:3682
+#: clutter/clutter-actor.c:3680
msgid "Minimum width set"
msgstr "Imposta larghezza minima"
-#: clutter/clutter-actor.c:3683
+#: clutter/clutter-actor.c:3681
msgid "Whether to use the min-width property"
msgstr "Se utilizzare la proprietà larghezza minima"
-#: clutter/clutter-actor.c:3698
+#: clutter/clutter-actor.c:3696
msgid "Minimum height set"
msgstr "Imposta altezza minima"
-#: clutter/clutter-actor.c:3699
+#: clutter/clutter-actor.c:3697
msgid "Whether to use the min-height property"
msgstr "Se usare la proprietà altezza minima"
-#: clutter/clutter-actor.c:3714
+#: clutter/clutter-actor.c:3712
msgid "Natural width set"
msgstr "Imposta larghezza naturale"
-#: clutter/clutter-actor.c:3715
+#: clutter/clutter-actor.c:3713
msgid "Whether to use the natural-width property"
msgstr "Se usare la proprietà larghezza naturale"
-#: clutter/clutter-actor.c:3732
+#: clutter/clutter-actor.c:3730
msgid "Natural height set"
msgstr "Imposta altezza naturale"
-#: clutter/clutter-actor.c:3733
+#: clutter/clutter-actor.c:3731
msgid "Whether to use the natural-height property"
msgstr "Se usare la proprietà altezza naturale"
-#: clutter/clutter-actor.c:3752
+#: clutter/clutter-actor.c:3750
msgid "Allocation"
msgstr "Allocazione"
-#: clutter/clutter-actor.c:3753
+#: clutter/clutter-actor.c:3751
msgid "The actor's allocation"
msgstr "Assegnazione dell'attore"
-#: clutter/clutter-actor.c:3809
+#: clutter/clutter-actor.c:3807
msgid "Request Mode"
msgstr "Modalità richiesta"
-#: clutter/clutter-actor.c:3810
+#: clutter/clutter-actor.c:3808
msgid "The actor's request mode"
msgstr "La modalità richiesta dell'attore"
-#: clutter/clutter-actor.c:3825
+#: clutter/clutter-actor.c:3823
msgid "Depth"
msgstr "Profondità"
-#: clutter/clutter-actor.c:3826
+#: clutter/clutter-actor.c:3824
msgid "Position on the Z axis"
msgstr "Posizione sull'asse Z"
-#: clutter/clutter-actor.c:3840
+#: clutter/clutter-actor.c:3838
msgid "Opacity"
msgstr "Opacità"
-#: clutter/clutter-actor.c:3841
+#: clutter/clutter-actor.c:3839
msgid "Opacity of an actor"
msgstr "Opacità di un attore"
-#: clutter/clutter-actor.c:3856
+#: clutter/clutter-actor.c:3854
msgid "Visible"
msgstr "Visibile"
-#: clutter/clutter-actor.c:3857
+#: clutter/clutter-actor.c:3855
msgid "Whether the actor is visible or not"
msgstr "Se l'attore è visibile o meno"
-#: clutter/clutter-actor.c:3872
+#: clutter/clutter-actor.c:3870
msgid "Mapped"
msgstr "Mappato"
-#: clutter/clutter-actor.c:3873
+#: clutter/clutter-actor.c:3871
msgid "Whether the actor will be painted"
msgstr "Se l'attore sarà disegnato"
-#: clutter/clutter-actor.c:3887
+#: clutter/clutter-actor.c:3885
msgid "Realized"
msgstr "Realizzato"
-#: clutter/clutter-actor.c:3888
+#: clutter/clutter-actor.c:3886
msgid "Whether the actor has been realized"
msgstr "Se l'attore è stato realizzato"
-#: clutter/clutter-actor.c:3904
+#: clutter/clutter-actor.c:3902
msgid "Reactive"
msgstr "Reattivo"
-#: clutter/clutter-actor.c:3905
+#: clutter/clutter-actor.c:3903
msgid "Whether the actor is reactive to events"
msgstr "Se l'attore è reattivo agli eventi"
-#: clutter/clutter-actor.c:3917
+#: clutter/clutter-actor.c:3915
msgid "Has Clip"
msgstr ""
-#: clutter/clutter-actor.c:3918
+#: clutter/clutter-actor.c:3916
msgid "Whether the actor has a clip set"
msgstr ""
-#: clutter/clutter-actor.c:3933
+#: clutter/clutter-actor.c:3931
msgid "Clip"
msgstr ""
-#: clutter/clutter-actor.c:3934
+#: clutter/clutter-actor.c:3932
msgid "The clip region for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3948 clutter/clutter-actor-meta.c:205
-#: clutter/clutter-binding-pool.c:320 clutter/clutter-input-device.c:151
+#: clutter/clutter-actor.c:3946 clutter/clutter-actor-meta.c:205
+#: clutter/clutter-binding-pool.c:319 clutter/clutter-input-device.c:235
msgid "Name"
msgstr "Nome"
-#: clutter/clutter-actor.c:3949
+#: clutter/clutter-actor.c:3947
msgid "Name of the actor"
msgstr "Nome dell'attore"
-#: clutter/clutter-actor.c:3963
+#: clutter/clutter-actor.c:3961
msgid "Scale X"
msgstr "Scala X"
-#: clutter/clutter-actor.c:3964
+#: clutter/clutter-actor.c:3962
msgid "Scale factor on the X axis"
msgstr "Fattore di scala sull'asse X"
-#: clutter/clutter-actor.c:3979
+#: clutter/clutter-actor.c:3977
msgid "Scale Y"
msgstr "Scala Y"
-#: clutter/clutter-actor.c:3980
+#: clutter/clutter-actor.c:3978
msgid "Scale factor on the Y axis"
msgstr "Fattore di scala sull'asse Y"
-#: clutter/clutter-actor.c:3995
+#: clutter/clutter-actor.c:3993
msgid "Scale Center X"
msgstr "Scala centrale X"
-#: clutter/clutter-actor.c:3996
+#: clutter/clutter-actor.c:3994
msgid "Horizontal scale center"
msgstr "Scala centrale orizzontale"
-#: clutter/clutter-actor.c:4011
+#: clutter/clutter-actor.c:4009
msgid "Scale Center Y"
msgstr "Scala centrale Y"
-#: clutter/clutter-actor.c:4012
+#: clutter/clutter-actor.c:4010
msgid "Vertical scale center"
msgstr "Scala centrale verticale"
-#: clutter/clutter-actor.c:4027
+#: clutter/clutter-actor.c:4025
msgid "Scale Gravity"
msgstr "Scala di gravità"
-#: clutter/clutter-actor.c:4028
+#: clutter/clutter-actor.c:4026
msgid "The center of scaling"
msgstr "Il centro della scala"
-#: clutter/clutter-actor.c:4045
+#: clutter/clutter-actor.c:4043
msgid "Rotation Angle X"
msgstr "Angolo di rotazione X"
-#: clutter/clutter-actor.c:4046
+#: clutter/clutter-actor.c:4044
msgid "The rotation angle on the X axis"
msgstr "L'angolo di rotazione sull'asse X"
-#: clutter/clutter-actor.c:4061
+#: clutter/clutter-actor.c:4059
msgid "Rotation Angle Y"
msgstr "Angolo di rotazione Y"
-#: clutter/clutter-actor.c:4062
+#: clutter/clutter-actor.c:4060
msgid "The rotation angle on the Y axis"
msgstr "L'angolo di rotazione sull'asse Y"
-#: clutter/clutter-actor.c:4077
+#: clutter/clutter-actor.c:4075
msgid "Rotation Angle Z"
msgstr "Angolo di rotazione Z"
-#: clutter/clutter-actor.c:4078
+#: clutter/clutter-actor.c:4076
msgid "The rotation angle on the Z axis"
msgstr "L'angolo di rotazione sull'asse Z"
-#: clutter/clutter-actor.c:4093
+#: clutter/clutter-actor.c:4091
msgid "Rotation Center X"
msgstr "Rotazione centrale X"
-#: clutter/clutter-actor.c:4094
+#: clutter/clutter-actor.c:4092
msgid "The rotation center on the X axis"
msgstr "La rotazione centrale sull'asse X"
-#: clutter/clutter-actor.c:4110
+#: clutter/clutter-actor.c:4108
msgid "Rotation Center Y"
msgstr "Rotazione centrale Y"
-#: clutter/clutter-actor.c:4111
+#: clutter/clutter-actor.c:4109
msgid "The rotation center on the Y axis"
msgstr "La rotazione centrale sull'asse Y"
-#: clutter/clutter-actor.c:4127
+#: clutter/clutter-actor.c:4125
msgid "Rotation Center Z"
msgstr "Rotazione centrale Z"
-#: clutter/clutter-actor.c:4128
+#: clutter/clutter-actor.c:4126
msgid "The rotation center on the Z axis"
msgstr "La rotazione centrale sull'asse Z"
-#: clutter/clutter-actor.c:4144
+#: clutter/clutter-actor.c:4142
msgid "Rotation Center Z Gravity"
msgstr "Gravità della rotazione centrale Z"
-#: clutter/clutter-actor.c:4145
+#: clutter/clutter-actor.c:4143
msgid "Center point for rotation around the Z axis"
msgstr "Punto centrale per la rotazione sull'asse Z"
-#: clutter/clutter-actor.c:4163
+#: clutter/clutter-actor.c:4161
msgid "Anchor X"
msgstr "Ancoraggio X"
-#: clutter/clutter-actor.c:4164
+#: clutter/clutter-actor.c:4162
msgid "X coordinate of the anchor point"
msgstr "Coordinata X del punto di ancoraggio"
-#: clutter/clutter-actor.c:4180
+#: clutter/clutter-actor.c:4178
msgid "Anchor Y"
msgstr "Ancoraggio Y"
-#: clutter/clutter-actor.c:4181
+#: clutter/clutter-actor.c:4179
msgid "Y coordinate of the anchor point"
msgstr "Coordinata Y del punto di ancoraggio"
-#: clutter/clutter-actor.c:4196
+#: clutter/clutter-actor.c:4194
msgid "Anchor Gravity"
msgstr "Gravità di ancoraggio"
-#: clutter/clutter-actor.c:4197
+#: clutter/clutter-actor.c:4195
#, fuzzy
msgid "The anchor point as a ClutterGravity"
msgstr "Il punto di ancoraggio come ClutterGravity"
-#: clutter/clutter-actor.c:4216
+#: clutter/clutter-actor.c:4214
msgid "Show on set parent"
msgstr "Mostra su imposta genitore"
-#: clutter/clutter-actor.c:4217
+#: clutter/clutter-actor.c:4215
msgid "Whether the actor is shown when parented"
msgstr "Se l'attore è mostrato quando genitore"
-#: clutter/clutter-actor.c:4237
+#: clutter/clutter-actor.c:4235
msgid "Clip to Allocation"
msgstr ""
-#: clutter/clutter-actor.c:4238
+#: clutter/clutter-actor.c:4236
msgid "Sets the clip region to track the actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:4248
+#: clutter/clutter-actor.c:4246
msgid "Text Direction"
msgstr "Direzione del testo"
-#: clutter/clutter-actor.c:4249
+#: clutter/clutter-actor.c:4247
msgid "Direction of the text"
msgstr "Direzione del testo"
-#: clutter/clutter-actor.c:4267
+#: clutter/clutter-actor.c:4265
msgid "Has Pointer"
msgstr "Ha il puntatore"
-#: clutter/clutter-actor.c:4268
+#: clutter/clutter-actor.c:4266
msgid "Whether the actor contains the pointer of an input device"
msgstr "Se l'attore contiene il puntatore di un dispositivo di input"
-#: clutter/clutter-actor.c:4285
+#: clutter/clutter-actor.c:4283
msgid "Actions"
msgstr "Azioni"
-#: clutter/clutter-actor.c:4286
+#: clutter/clutter-actor.c:4284
msgid "Adds an action to the actor"
msgstr "Aggiunge un'azione per l'attore"
-#: clutter/clutter-actor.c:4300
+#: clutter/clutter-actor.c:4298
msgid "Constraints"
msgstr "Vincoli"
-#: clutter/clutter-actor.c:4301
+#: clutter/clutter-actor.c:4299
msgid "Adds a constraint to the actor"
msgstr "Aggiunge un vincolo per l'attore"
msgid "The name of the meta"
msgstr "Il nome del meta"
-#: clutter/clutter-actor-meta.c:219 clutter/clutter-shader.c:261
+#: clutter/clutter-actor-meta.c:219 clutter/clutter-input-device.c:314
+#: clutter/clutter-shader.c:295
msgid "Enabled"
msgstr "Attivato"
msgid "Whether the meta is enabled"
msgstr "Se il meta è attivato"
-#: clutter/clutter-align-constraint.c:231
-#: clutter/clutter-bind-constraint.c:286 clutter/clutter-clone.c:322
+#: clutter/clutter-align-constraint.c:252
+#: clutter/clutter-bind-constraint.c:316 clutter/clutter-clone.c:322
msgid "Source"
msgstr "Origine"
-#: clutter/clutter-align-constraint.c:232
+#: clutter/clutter-align-constraint.c:253
msgid "The source of the alignment"
msgstr "L'origine dell'allineamento"
-#: clutter/clutter-align-constraint.c:245
+#: clutter/clutter-align-constraint.c:266
msgid "Align Axis"
msgstr "Allinea le assi"
-#: clutter/clutter-align-constraint.c:246
+#: clutter/clutter-align-constraint.c:267
msgid "The axis to align the position to"
msgstr "Le assi alle quali allineare la posizione"
-#: clutter/clutter-align-constraint.c:265
-#: clutter/clutter-desaturate-effect.c:309
+#: clutter/clutter-align-constraint.c:286
+#: clutter/clutter-desaturate-effect.c:307
msgid "Factor"
msgstr "Fattore"
-#: clutter/clutter-align-constraint.c:266
+#: clutter/clutter-align-constraint.c:287
msgid "The alignment factor, between 0.0 and 1.0"
msgstr "Il fattore di allineamento, tra 0.0 e 1.0"
#: clutter/clutter-alpha.c:339 clutter/clutter-animation.c:523
-#: clutter/clutter-animator.c:1801
+#: clutter/clutter-animator.c:1802
msgid "Timeline"
msgstr ""
msgid "The mode of the animation"
msgstr "La modalità di animazione"
-#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1785
+#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1786
#: clutter/clutter-media.c:194 clutter/clutter-state.c:1282
msgid "Duration"
msgstr "Durata"
msgid "The timeline used by the animation"
msgstr ""
-#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:299
+#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:298
msgid "Alpha"
msgstr "Alpha"
msgid "The alpha used by the animation"
msgstr "L'alpha usato dall'animazione"
-#: clutter/clutter-animator.c:1786
+#: clutter/clutter-animator.c:1787
msgid "The duration of the animation"
msgstr "La durata dell'animazione"
-#: clutter/clutter-animator.c:1802
+#: clutter/clutter-animator.c:1803
#, fuzzy
msgid "The timeline of the animation"
msgstr "La timeline di animazione"
-#: clutter/clutter-behaviour.c:300
+#: clutter/clutter-behaviour.c:299
msgid "Alpha Object to drive the behaviour"
msgstr "Oggetto alpha per guidare il comportamento"
-#: clutter/clutter-behaviour-depth.c:175
+#: clutter/clutter-behaviour-depth.c:174
msgid "Start Depth"
msgstr "Profondità iniziale"
-#: clutter/clutter-behaviour-depth.c:176
+#: clutter/clutter-behaviour-depth.c:175
msgid "Initial depth to apply"
msgstr "Profondità iniziale da applicare"
-#: clutter/clutter-behaviour-depth.c:191
+#: clutter/clutter-behaviour-depth.c:190
msgid "End Depth"
msgstr "Profondità finale"
-#: clutter/clutter-behaviour-depth.c:192
+#: clutter/clutter-behaviour-depth.c:191
msgid "Final depth to apply"
msgstr "Profondità finale da applicare"
-#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-ellipse.c:394
msgid "Start Angle"
msgstr "Angolo iniziale"
-#: clutter/clutter-behaviour-ellipse.c:396
-#: clutter/clutter-behaviour-rotate.c:277
+#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-rotate.c:276
msgid "Initial angle"
msgstr "Angolo iniziale"
-#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-ellipse.c:410
msgid "End Angle"
msgstr "Angolo finale"
-#: clutter/clutter-behaviour-ellipse.c:412
-#: clutter/clutter-behaviour-rotate.c:295
+#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-rotate.c:294
msgid "Final angle"
msgstr "Angolo finale"
-#: clutter/clutter-behaviour-ellipse.c:427
+#: clutter/clutter-behaviour-ellipse.c:426
msgid "Angle x tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:428
+#: clutter/clutter-behaviour-ellipse.c:427
msgid "Tilt of the ellipse around x axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:443
+#: clutter/clutter-behaviour-ellipse.c:442
msgid "Angle y tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:444
+#: clutter/clutter-behaviour-ellipse.c:443
msgid "Tilt of the ellipse around y axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:459
+#: clutter/clutter-behaviour-ellipse.c:458
msgid "Angle z tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:460
+#: clutter/clutter-behaviour-ellipse.c:459
msgid "Tilt of the ellipse around z axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:476
+#: clutter/clutter-behaviour-ellipse.c:475
msgid "Width of the ellipse"
msgstr "Larghezza dell'ellisse"
-#: clutter/clutter-behaviour-ellipse.c:492
+#: clutter/clutter-behaviour-ellipse.c:491
msgid "Height of ellipse"
msgstr "Altezza dell'ellisse"
-#: clutter/clutter-behaviour-ellipse.c:507
+#: clutter/clutter-behaviour-ellipse.c:506
msgid "Center"
msgstr "Centro"
-#: clutter/clutter-behaviour-ellipse.c:508
+#: clutter/clutter-behaviour-ellipse.c:507
msgid "Center of ellipse"
msgstr "Centro dell'ellisse"
-#: clutter/clutter-behaviour-ellipse.c:522
-#: clutter/clutter-behaviour-rotate.c:330
+#: clutter/clutter-behaviour-ellipse.c:521
+#: clutter/clutter-behaviour-rotate.c:329
msgid "Direction"
msgstr "Direzione"
-#: clutter/clutter-behaviour-ellipse.c:523
-#: clutter/clutter-behaviour-rotate.c:331
+#: clutter/clutter-behaviour-ellipse.c:522
+#: clutter/clutter-behaviour-rotate.c:330
msgid "Direction of rotation"
msgstr "Direzione della rotazione"
-#: clutter/clutter-behaviour-opacity.c:178
+#: clutter/clutter-behaviour-opacity.c:177
msgid "Opacity Start"
msgstr "Opacità iniziale"
-#: clutter/clutter-behaviour-opacity.c:179
+#: clutter/clutter-behaviour-opacity.c:178
msgid "Initial opacity level"
msgstr "Livello di opacità iniziale"
-#: clutter/clutter-behaviour-opacity.c:196
+#: clutter/clutter-behaviour-opacity.c:195
msgid "Opacity End"
msgstr "Opacità finale"
-#: clutter/clutter-behaviour-opacity.c:197
+#: clutter/clutter-behaviour-opacity.c:196
msgid "Final opacity level"
msgstr "Livello di opacità finale"
-#: clutter/clutter-behaviour-path.c:220
+#: clutter/clutter-behaviour-path.c:219
msgid "Path"
msgstr "Percorso"
-#: clutter/clutter-behaviour-path.c:221
+#: clutter/clutter-behaviour-path.c:220
msgid "The ClutterPath object representing the path to animate along"
msgstr "L'oggetto ClutterPath che rappresenta il percorso dell'animazione"
-#: clutter/clutter-behaviour-rotate.c:276
+#: clutter/clutter-behaviour-rotate.c:275
msgid "Angle Begin"
msgstr "Angolo iniziale"
-#: clutter/clutter-behaviour-rotate.c:294
+#: clutter/clutter-behaviour-rotate.c:293
msgid "Angle End"
msgstr "Angolo finale"
-#: clutter/clutter-behaviour-rotate.c:312
+#: clutter/clutter-behaviour-rotate.c:311
msgid "Axis"
msgstr "Assi"
-#: clutter/clutter-behaviour-rotate.c:313
+#: clutter/clutter-behaviour-rotate.c:312
msgid "Axis of rotation"
msgstr "Assi di rotazione"
-#: clutter/clutter-behaviour-rotate.c:348
+#: clutter/clutter-behaviour-rotate.c:347
msgid "Center X"
msgstr "Centro X"
-#: clutter/clutter-behaviour-rotate.c:349
+#: clutter/clutter-behaviour-rotate.c:348
msgid "X coordinate of the center of rotation"
msgstr "Coordinata X del centro di rotazione"
-#: clutter/clutter-behaviour-rotate.c:366
+#: clutter/clutter-behaviour-rotate.c:365
msgid "Center Y"
msgstr "Centro Y"
-#: clutter/clutter-behaviour-rotate.c:367
+#: clutter/clutter-behaviour-rotate.c:366
msgid "Y coordinate of the center of rotation"
msgstr "Coordinata Y del centro di rotazione"
-#: clutter/clutter-behaviour-rotate.c:384
+#: clutter/clutter-behaviour-rotate.c:383
msgid "Center Z"
msgstr "Centro"
-#: clutter/clutter-behaviour-rotate.c:385
+#: clutter/clutter-behaviour-rotate.c:384
msgid "Z coordinate of the center of rotation"
msgstr "Coordinata Z del centro di rotazione"
-#: clutter/clutter-behaviour-scale.c:219
+#: clutter/clutter-behaviour-scale.c:218
msgid "X Start Scale"
msgstr "Scala iniziale X"
-#: clutter/clutter-behaviour-scale.c:220
+#: clutter/clutter-behaviour-scale.c:219
msgid "Initial scale on the X axis"
msgstr "Scala iniziale sull'asse X"
-#: clutter/clutter-behaviour-scale.c:238
+#: clutter/clutter-behaviour-scale.c:237
msgid "X End Scale"
msgstr "Scala finale X"
-#: clutter/clutter-behaviour-scale.c:239
+#: clutter/clutter-behaviour-scale.c:238
msgid "Final scale on the X axis"
msgstr "Scala finale sull'asse X"
-#: clutter/clutter-behaviour-scale.c:257
+#: clutter/clutter-behaviour-scale.c:256
msgid "Y Start Scale"
msgstr "Scala iniziale Y"
-#: clutter/clutter-behaviour-scale.c:258
+#: clutter/clutter-behaviour-scale.c:257
msgid "Initial scale on the Y axis"
msgstr "Scala iniziale sull'asse U"
-#: clutter/clutter-behaviour-scale.c:276
+#: clutter/clutter-behaviour-scale.c:275
msgid "Y End Scale"
msgstr "Scala finale Y"
-#: clutter/clutter-behaviour-scale.c:277
+#: clutter/clutter-behaviour-scale.c:276
msgid "Final scale on the Y axis"
msgstr "Scala finale sull'asse Y"
-#: clutter/clutter-bind-constraint.c:287
+#: clutter/clutter-bind-constraint.c:317
msgid "The source of the binding"
msgstr "L'origine dell'associazione"
-#: clutter/clutter-bind-constraint.c:300
+#: clutter/clutter-bind-constraint.c:330
msgid "Coordinate"
msgstr "Coordinata"
-#: clutter/clutter-bind-constraint.c:301
+#: clutter/clutter-bind-constraint.c:331
msgid "The coordinate to bind"
msgstr "La coordinata da associare"
-#: clutter/clutter-bind-constraint.c:315
+#: clutter/clutter-bind-constraint.c:345
msgid "Offset"
msgstr "Spostamento"
-#: clutter/clutter-bind-constraint.c:316
+#: clutter/clutter-bind-constraint.c:346
msgid "The offset in pixels to apply to the binding"
msgstr "Lo spostamento in pixel da applicare all'associazione"
msgstr ""
"Allineamento verticale predefinito per l'attore dentro il gestore di layout"
-#: clutter/clutter-binding-pool.c:321
+#: clutter/clutter-binding-pool.c:320
msgid "The unique name of the binding pool"
msgstr "Il nome unico dell'insieme di associazione"
msgstr "Il gestore di layout usato dal box"
#: clutter/clutter-box.c:514 clutter/clutter-rectangle.c:258
-#: clutter/clutter-stage.c:1307
+#: clutter/clutter-stage.c:1317
msgid "Color"
msgstr "Colore"
msgid "The actor wrapped by this data"
msgstr ""
-#: clutter/clutter-click-action.c:283
+#: clutter/clutter-click-action.c:302
msgid "Pressed"
msgstr "Premuto"
-#: clutter/clutter-click-action.c:284
+#: clutter/clutter-click-action.c:303
msgid "Whether the clickable should be in pressed state"
msgstr "Se il cliccabile dovrebbe essere in stato premuto"
-#: clutter/clutter-click-action.c:297
+#: clutter/clutter-click-action.c:316
msgid "Held"
msgstr "Mantenuto"
-#: clutter/clutter-click-action.c:298
+#: clutter/clutter-click-action.c:317
msgid "Whether the clickable has a grab"
msgstr "Se il cliccabile ha la maniglia"
msgid "Specifies the actor to be cloned"
msgstr "Specifica l'attore da clonare"
-#: clutter/clutter-colorize-effect.c:309
+#: clutter/clutter-colorize-effect.c:307
msgid "Tint"
msgstr "Tinta"
-#: clutter/clutter-colorize-effect.c:310
+#: clutter/clutter-colorize-effect.c:308
msgid "The tint to apply"
msgstr "La tinta da applicare"
msgid "The material to be used when painting the back of the actor"
msgstr "Il materiale da usare nel disegno del posteriore dell'attore"
-#: clutter/clutter-desaturate-effect.c:310
+#: clutter/clutter-desaturate-effect.c:308
msgid "The desaturation factor"
msgstr "Il fattore desaturazione"
-#: clutter/clutter-device-manager.c:130
+#: clutter/clutter-device-manager.c:130 clutter/clutter-input-device.c:343
msgid "Backend"
msgstr ""
msgid "The ClutterBackend of the device manager"
msgstr "Il ClutterBackend del gestore di dispositivo"
-#: clutter/clutter-drag-action.c:490
+#: clutter/clutter-drag-action.c:491
msgid "Horizontal Drag Threshold"
msgstr "Soglia di trascinamento orizzontale"
-#: clutter/clutter-drag-action.c:491
+#: clutter/clutter-drag-action.c:492
msgid "The horizontal amount of pixels required to start dragging"
msgstr "Il numero di pixel orizzontali richiesto per iniziare il trascinamento"
-#: clutter/clutter-drag-action.c:510
+#: clutter/clutter-drag-action.c:511
msgid "Vertical Drag Threshold"
msgstr "Soglia di trascinamento verticale"
-#: clutter/clutter-drag-action.c:511
+#: clutter/clutter-drag-action.c:512
msgid "The vertical amount of pixels required to start dragging"
msgstr "Il numero di pixel verticali richiesto per iniziare il trascinamento"
-#: clutter/clutter-drag-action.c:532
+#: clutter/clutter-drag-action.c:533
msgid "Drag Handle"
msgstr "Maniglia di trascinamento"
-#: clutter/clutter-drag-action.c:533
+#: clutter/clutter-drag-action.c:534
msgid "The actor that is being dragged"
msgstr "L'attore che si sta trascinando"
-#: clutter/clutter-drag-action.c:546
+#: clutter/clutter-drag-action.c:547
msgid "Drag Axis"
msgstr "Asse di trascinamento"
-#: clutter/clutter-drag-action.c:547
+#: clutter/clutter-drag-action.c:548
msgid "Constraints the dragging to an axis"
msgstr "Vincoli di trascinamento di un asse"
msgid "Maximum height for each row"
msgstr "Altezza massima di ogni riga"
-#: clutter/clutter-input-device.c:134
+#: clutter/clutter-input-device.c:219
msgid "Id"
msgstr "Id"
-#: clutter/clutter-input-device.c:135
+#: clutter/clutter-input-device.c:220
msgid "Unique identifier of the device"
msgstr "Identificativo unico del dispositivo"
-#: clutter/clutter-input-device.c:152
+#: clutter/clutter-input-device.c:236
msgid "The name of the device"
msgstr "Il nome del dispositivo"
-#: clutter/clutter-input-device.c:167
+#: clutter/clutter-input-device.c:250
msgid "Device Type"
msgstr "Tipo di dispositivo"
-#: clutter/clutter-input-device.c:168
+#: clutter/clutter-input-device.c:251
msgid "The type of the device"
msgstr "Il tipo di dispositivo"
+#: clutter/clutter-input-device.c:266
+#, fuzzy
+msgid "Device Manager"
+msgstr "Gestore"
+
+#: clutter/clutter-input-device.c:267
+msgid "The device manager instance"
+msgstr ""
+
+#: clutter/clutter-input-device.c:280
+#, fuzzy
+msgid "Device Mode"
+msgstr "Tipo di dispositivo"
+
+#: clutter/clutter-input-device.c:281
+#, fuzzy
+msgid "The mode of the device"
+msgstr "Il nome del dispositivo"
+
+#: clutter/clutter-input-device.c:295
+#, fuzzy
+msgid "Has Cursor"
+msgstr "Ha bordo"
+
+#: clutter/clutter-input-device.c:296
+#, fuzzy
+msgid "Whether the device has a cursor"
+msgstr "Se il cliccabile ha la maniglia"
+
+#: clutter/clutter-input-device.c:315
+#, fuzzy
+msgid "Whether the device is enabled"
+msgstr "Se l'ombreggiatore è abilitato"
+
+#: clutter/clutter-input-device.c:328
+msgid "Number of Axes"
+msgstr ""
+
+#: clutter/clutter-input-device.c:329
+#, fuzzy
+msgid "The number of axes on the device"
+msgstr "Il nome del dispositivo"
+
+#: clutter/clutter-input-device.c:344
+msgid "The backend instance"
+msgstr ""
+
#: clutter/clutter-interval.c:397
msgid "Value Type"
msgstr "Tipo di valore"
msgid "The manager that created this data"
msgstr "Il gestore che ha creato questo dato"
-#: clutter/clutter-main.c:756
+#: clutter/clutter-main.c:753
msgid "default:LTR"
msgstr "default:LTR"
-#: clutter/clutter-main.c:1560
+#: clutter/clutter-main.c:1557
msgid "Show frames per second"
msgstr "Mostra i fotogrammi per secondo"
-#: clutter/clutter-main.c:1562
+#: clutter/clutter-main.c:1559
msgid "Default frame rate"
msgstr "Framerate predefinito"
-#: clutter/clutter-main.c:1564
+#: clutter/clutter-main.c:1561
msgid "Make all warnings fatal"
msgstr "Rende tutti i warning critici"
-#: clutter/clutter-main.c:1567
+#: clutter/clutter-main.c:1564
msgid "Direction for the text"
msgstr "Direzione del testo"
-#: clutter/clutter-main.c:1570
+#: clutter/clutter-main.c:1567
msgid "Disable mipmapping on text"
msgstr "Disabilita il mipmapping sul testo"
-#: clutter/clutter-main.c:1573
+#: clutter/clutter-main.c:1570
msgid "Use 'fuzzy' picking"
msgstr "Usa il picking \"fuzzy\""
-#: clutter/clutter-main.c:1576
+#: clutter/clutter-main.c:1573
msgid "Clutter debugging flags to set"
msgstr "Flag per il debug di Clutter da attivare"
-#: clutter/clutter-main.c:1578
+#: clutter/clutter-main.c:1575
msgid "Clutter debugging flags to unset"
msgstr "Flag per il debug di Clutter da disattivare"
-#: clutter/clutter-main.c:1582
+#: clutter/clutter-main.c:1579
msgid "Clutter profiling flags to set"
msgstr "Flag per il profiling di Clutter da attivare"
-#: clutter/clutter-main.c:1584
+#: clutter/clutter-main.c:1581
msgid "Clutter profiling flags to unset"
msgstr "Flag per il profiling di Clutter da disattivare"
-#: clutter/clutter-main.c:1587
+#: clutter/clutter-main.c:1584
msgid "Enable accessibility"
msgstr "Attiva l'accessibilità"
-#: clutter/clutter-main.c:1774
+#: clutter/clutter-main.c:1771
msgid "Clutter Options"
msgstr "Opzioni di Clutter"
-#: clutter/clutter-main.c:1775
+#: clutter/clutter-main.c:1772
msgid "Show Clutter Options"
msgstr "Mostra le opzioni di Clutter"
msgid "The path of the currently parsed file"
msgstr "Il percorso del file attuale analizzato"
-#: clutter/clutter-shader.c:215
+#: clutter/clutter-shader.c:249
msgid "Vertex Source"
msgstr "Origine vertice"
-#: clutter/clutter-shader.c:216
+#: clutter/clutter-shader.c:250
#, fuzzy
msgid "Source of vertex shader"
msgstr "Origine dell'ombreggiatore di vertice"
-#: clutter/clutter-shader.c:230
+#: clutter/clutter-shader.c:264
msgid "Fragment Source"
msgstr "Origine frammento"
-#: clutter/clutter-shader.c:231
+#: clutter/clutter-shader.c:265
#, fuzzy
msgid "Source of fragment shader"
msgstr "Origine dell'ombreggiatore di frammento"
-#: clutter/clutter-shader.c:246
+#: clutter/clutter-shader.c:280
msgid "Compiled"
msgstr "Compilato"
-#: clutter/clutter-shader.c:247
+#: clutter/clutter-shader.c:281
#, fuzzy
msgid "Whether the shader is compiled and linked"
msgstr "Se l'ombreggiatore è compilato e collegato"
-#: clutter/clutter-shader.c:262
+#: clutter/clutter-shader.c:296
#, fuzzy
msgid "Whether the shader is enabled"
msgstr "Se l'ombreggiatore è abilitato"
-#: clutter/clutter-shader.c:467
+#: clutter/clutter-shader.c:501
#, c-format
msgid "%s compilation failed: %s"
msgstr "Compilazione di %s non riuscita: %s"
-#: clutter/clutter-shader.c:468
+#: clutter/clutter-shader.c:502
msgid "Vertex shader"
msgstr "Vertex shader"
-#: clutter/clutter-shader.c:469
+#: clutter/clutter-shader.c:503
msgid "Fragment shader"
msgstr "Fragment shader"
msgid "The type of shader used"
msgstr "Il tipo di ombreggiatore usato"
-#: clutter/clutter-stage.c:1249
+#: clutter/clutter-stage.c:1259
msgid "Fullscreen Set"
msgstr "Imposta a schermo intero"
-#: clutter/clutter-stage.c:1250
+#: clutter/clutter-stage.c:1260
msgid "Whether the main stage is fullscreen"
msgstr "Se il livello principale è a schermo intero"
-#: clutter/clutter-stage.c:1266
+#: clutter/clutter-stage.c:1276
msgid "Offscreen"
msgstr "Fuorischermo"
-#: clutter/clutter-stage.c:1267
+#: clutter/clutter-stage.c:1277
msgid "Whether the main stage should be rendered offscreen"
msgstr "Se il livello principale dovrebbe essere renderizzato fuori schermo"
-#: clutter/clutter-stage.c:1279 clutter/clutter-text.c:2643
+#: clutter/clutter-stage.c:1289 clutter/clutter-text.c:2667
msgid "Cursor Visible"
msgstr "Cursore visibile"
-#: clutter/clutter-stage.c:1280
+#: clutter/clutter-stage.c:1290
msgid "Whether the mouse pointer is visible on the main stage"
msgstr "Se il puntatore del mouse è visibile sul livello principale"
-#: clutter/clutter-stage.c:1294
+#: clutter/clutter-stage.c:1304
msgid "User Resizable"
msgstr "Ridimensionabile dall'utente"
-#: clutter/clutter-stage.c:1295
+#: clutter/clutter-stage.c:1305
msgid "Whether the stage is able to be resized via user interaction"
msgstr ""
"Se il livello può essere ridimensionato attraverso l'interazione dell'utente"
-#: clutter/clutter-stage.c:1308
+#: clutter/clutter-stage.c:1318
msgid "The color of the stage"
msgstr "Il colore del livello"
-#: clutter/clutter-stage.c:1322
+#: clutter/clutter-stage.c:1332
msgid "Perspective"
msgstr "Prospettiva"
-#: clutter/clutter-stage.c:1323
+#: clutter/clutter-stage.c:1333
msgid "Perspective projection parameters"
msgstr "Parametri di proiezione prospettica"
-#: clutter/clutter-stage.c:1338
+#: clutter/clutter-stage.c:1348
msgid "Title"
msgstr "Titolo"
-#: clutter/clutter-stage.c:1339
+#: clutter/clutter-stage.c:1349
msgid "Stage Title"
msgstr "Titolo del livello"
-#: clutter/clutter-stage.c:1354
+#: clutter/clutter-stage.c:1364
msgid "Use Fog"
msgstr "Usa nebbia"
-#: clutter/clutter-stage.c:1355
+#: clutter/clutter-stage.c:1365
msgid "Whether to enable depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1369
+#: clutter/clutter-stage.c:1379
msgid "Fog"
msgstr "Nebbia"
-#: clutter/clutter-stage.c:1370
+#: clutter/clutter-stage.c:1380
msgid "Settings for the depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1386
+#: clutter/clutter-stage.c:1396
msgid "Use Alpha"
msgstr "Usa Alpha"
-#: clutter/clutter-stage.c:1387
+#: clutter/clutter-stage.c:1397
msgid "Whether to honour the alpha component of the stage color"
msgstr "Se rispettare il componente alpha del colore del livello"
-#: clutter/clutter-stage.c:1403
+#: clutter/clutter-stage.c:1413
msgid "Key Focus"
msgstr "Fuoco chiave"
-#: clutter/clutter-stage.c:1404
+#: clutter/clutter-stage.c:1414
msgid "The currently key focused actor"
msgstr "L'attore chiave attuale con fuoco"
-#: clutter/clutter-stage.c:1420
+#: clutter/clutter-stage.c:1430
msgid "No Clear Hint"
msgstr ""
-#: clutter/clutter-stage.c:1421
+#: clutter/clutter-stage.c:1431
msgid "Whether the stage should clear its contents"
msgstr "Se il livello dovrebbe cancellare il suo contenuto"
+#: clutter/clutter-stage.c:1444
+#, fuzzy
+msgid "Accept Focus"
+msgstr "Fuoco chiave"
+
+#: clutter/clutter-stage.c:1445
+#, fuzzy
+msgid "Whether the stage should accept focus on show"
+msgstr "Se il livello dovrebbe cancellare il suo contenuto"
+
#: clutter/clutter-state.c:1268
msgid "State"
msgstr "Stato"
msgid "Default transition duration"
msgstr ""
-#: clutter/clutter-text.c:2530
+#: clutter/clutter-text.c:2554
msgid "Font Name"
msgstr "Nome carattere"
-#: clutter/clutter-text.c:2531
+#: clutter/clutter-text.c:2555
msgid "The font to be used by the text"
msgstr "Il carattere utilizzato dal testo"
-#: clutter/clutter-text.c:2548
+#: clutter/clutter-text.c:2572
msgid "Font Description"
msgstr "Descrizione carattere"
-#: clutter/clutter-text.c:2549
+#: clutter/clutter-text.c:2573
msgid "The font description to be used"
msgstr "La descrizione del carattere da usare"
-#: clutter/clutter-text.c:2565
+#: clutter/clutter-text.c:2589
msgid "Text"
msgstr "Testo"
-#: clutter/clutter-text.c:2566
+#: clutter/clutter-text.c:2590
msgid "The text to render"
msgstr "Il testo da riprodurre"
-#: clutter/clutter-text.c:2580
+#: clutter/clutter-text.c:2604
msgid "Font Color"
msgstr "Colore carattere"
-#: clutter/clutter-text.c:2581
+#: clutter/clutter-text.c:2605
msgid "Color of the font used by the text"
msgstr "Il colore del carattere usato dal testo"
-#: clutter/clutter-text.c:2595
+#: clutter/clutter-text.c:2619
msgid "Editable"
msgstr "Modificabile"
-#: clutter/clutter-text.c:2596
+#: clutter/clutter-text.c:2620
msgid "Whether the text is editable"
msgstr "Se il testo è modificabile"
-#: clutter/clutter-text.c:2611
+#: clutter/clutter-text.c:2635
msgid "Selectable"
msgstr "Selezionabile"
-#: clutter/clutter-text.c:2612
+#: clutter/clutter-text.c:2636
msgid "Whether the text is selectable"
msgstr "Se il testo è selezionabile"
-#: clutter/clutter-text.c:2626
+#: clutter/clutter-text.c:2650
msgid "Activatable"
msgstr "Attivabile"
-#: clutter/clutter-text.c:2627
+#: clutter/clutter-text.c:2651
msgid "Whether pressing return causes the activate signal to be emitted"
msgstr "Se la pressione di invio causa l'emissione del segnale activate"
-#: clutter/clutter-text.c:2644
+#: clutter/clutter-text.c:2668
msgid "Whether the input cursor is visible"
msgstr "Se il cursore di input è visibile"
-#: clutter/clutter-text.c:2658 clutter/clutter-text.c:2659
+#: clutter/clutter-text.c:2682 clutter/clutter-text.c:2683
msgid "Cursor Color"
msgstr "Colore del cursore"
-#: clutter/clutter-text.c:2673
+#: clutter/clutter-text.c:2697
msgid "Cursor Color Set"
msgstr "Imposta colore cursore"
-#: clutter/clutter-text.c:2674
+#: clutter/clutter-text.c:2698
msgid "Whether the cursor color has been set"
msgstr "Se il colore del cursore è stato impostato"
-#: clutter/clutter-text.c:2689
+#: clutter/clutter-text.c:2713
msgid "Cursor Size"
msgstr "Dimensione cursore"
-#: clutter/clutter-text.c:2690
+#: clutter/clutter-text.c:2714
msgid "The width of the cursor, in pixels"
msgstr "La larghezza del cursore, in pixel"
-#: clutter/clutter-text.c:2704
+#: clutter/clutter-text.c:2728
msgid "Cursor Position"
msgstr "Posizione cursore"
-#: clutter/clutter-text.c:2705
+#: clutter/clutter-text.c:2729
msgid "The cursor position"
msgstr "La posizione del cursore"
-#: clutter/clutter-text.c:2720
+#: clutter/clutter-text.c:2744
msgid "Selection-bound"
msgstr "Rettangolo di selezione"
-#: clutter/clutter-text.c:2721
+#: clutter/clutter-text.c:2745
msgid "The cursor position of the other end of the selection"
msgstr "La posizione del cursore dell'altro capo della selezione"
-#: clutter/clutter-text.c:2736 clutter/clutter-text.c:2737
+#: clutter/clutter-text.c:2760 clutter/clutter-text.c:2761
msgid "Selection Color"
msgstr "Colore selezione"
-#: clutter/clutter-text.c:2751
+#: clutter/clutter-text.c:2775
msgid "Selection Color Set"
msgstr "Imposta il colore selezione"
-#: clutter/clutter-text.c:2752
+#: clutter/clutter-text.c:2776
msgid "Whether the selection color has been set"
msgstr "Se il colore della selezione è stato impostato"
-#: clutter/clutter-text.c:2767
+#: clutter/clutter-text.c:2791
msgid "Attributes"
msgstr "Attributi"
-#: clutter/clutter-text.c:2768
+#: clutter/clutter-text.c:2792
msgid "A list of style attributes to apply to the contents of the actor"
msgstr "Una lista di attributi di stile da applicare ai contenuti degli attori"
-#: clutter/clutter-text.c:2790
+#: clutter/clutter-text.c:2814
msgid "Use markup"
msgstr "Usa marcatura"
-#: clutter/clutter-text.c:2791
+#: clutter/clutter-text.c:2815
msgid "Whether or not the text includes Pango markup"
msgstr "Se il testo include o meno la marcatura Pango"
-#: clutter/clutter-text.c:2807
+#: clutter/clutter-text.c:2831
msgid "Line wrap"
msgstr "Ritorno a capo"
-#: clutter/clutter-text.c:2808
+#: clutter/clutter-text.c:2832
msgid "If set, wrap the lines if the text becomes too wide"
msgstr "Se impostato, manda a capo le righe se il testo diviene troppo largo"
-#: clutter/clutter-text.c:2823
+#: clutter/clutter-text.c:2847
msgid "Line wrap mode"
msgstr "Modalità ritorno a capo"
-#: clutter/clutter-text.c:2824
+#: clutter/clutter-text.c:2848
msgid "Control how line-wrapping is done"
msgstr "Controlla come il ritorno a capo è fatto"
-#: clutter/clutter-text.c:2839
+#: clutter/clutter-text.c:2863
msgid "Ellipsize"
msgstr "Punteggiatura"
-#: clutter/clutter-text.c:2840
+#: clutter/clutter-text.c:2864
msgid "The preferred place to ellipsize the string"
msgstr "Il punto preferito per punteggiare la stringa"
-#: clutter/clutter-text.c:2856
+#: clutter/clutter-text.c:2880
msgid "Line Alignment"
msgstr "Allineamento riga"
-#: clutter/clutter-text.c:2857
+#: clutter/clutter-text.c:2881
msgid "The preferred alignment for the string, for multi-line text"
msgstr "L'allineamento preferito per la stringa, per il testo a righe multiple"
-#: clutter/clutter-text.c:2873
+#: clutter/clutter-text.c:2897
msgid "Justify"
msgstr "Giustifica"
-#: clutter/clutter-text.c:2874
+#: clutter/clutter-text.c:2898
msgid "Whether the text should be justified"
msgstr "Se il testo dovrebbe essere giustificato"
-#: clutter/clutter-text.c:2889
+#: clutter/clutter-text.c:2913
msgid "Password Character"
msgstr "Carattere password"
-#: clutter/clutter-text.c:2890
+#: clutter/clutter-text.c:2914
msgid "If non-zero, use this character to display the actor's contents"
msgstr ""
"Se non zero, usa questo carattere per mostrare il contenuto degli attori"
-#: clutter/clutter-text.c:2904
+#: clutter/clutter-text.c:2928
msgid "Max Length"
msgstr "Lunghezza massima"
-#: clutter/clutter-text.c:2905
+#: clutter/clutter-text.c:2929
msgid "Maximum length of the text inside the actor"
msgstr "Lunghezza massima del testo all'interno dell'attore"
-#: clutter/clutter-text.c:2928
+#: clutter/clutter-text.c:2952
msgid "Single Line Mode"
msgstr "Modalità linea singola"
-#: clutter/clutter-text.c:2929
+#: clutter/clutter-text.c:2953
msgid "Whether the text should be a single line"
msgstr "Se il testo dovrebbe essere in una linea singola"
msgid "Shape actor with alpha channel when picking"
msgstr "Attore di forma con canale alpha nella cattura"
-#: clutter/glx/clutter-backend-glx.c:128
+#: clutter/glx/clutter-backend-glx.c:131
msgid "VBlank method to be used (none, dri or glx)"
msgstr "Metodo VBlank da usare (none, dri o glx)"
-#: clutter/x11/clutter-backend-x11.c:364
+#: clutter/x11/clutter-backend-x11.c:473
msgid "X display to use"
msgstr "Display X da usare"
-#: clutter/x11/clutter-backend-x11.c:370
+#: clutter/x11/clutter-backend-x11.c:479
msgid "X screen to use"
msgstr "Schermo X da usare"
-#: clutter/x11/clutter-backend-x11.c:375
+#: clutter/x11/clutter-backend-x11.c:484
msgid "Make X calls synchronous"
msgstr "Rende le chiamate a X sincrone"
-#: clutter/x11/clutter-backend-x11.c:382
+#: clutter/x11/clutter-backend-x11.c:491
msgid "Enable XInput support"
msgstr "Abilita il supporto a XInput"
"Project-Id-Version: pl\n"
"Report-Msgid-Bugs-To: http://bugzilla.clutter-project.org/enter_bug.cgi?"
"product=clutter\n"
-"POT-Creation-Date: 2010-12-17 15:51+0000\n"
+"POT-Creation-Date: 2011-02-07 15:50+0000\n"
"PO-Revision-Date: 2010-10-01 17:03+0200\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
-#: clutter/clutter-actor.c:3480
+#: clutter/clutter-actor.c:3478
msgid "X coordinate"
msgstr "Współrzędna X"
-#: clutter/clutter-actor.c:3481
+#: clutter/clutter-actor.c:3479
msgid "X coordinate of the actor"
msgstr "Współrzędna X aktora"
-#: clutter/clutter-actor.c:3496
+#: clutter/clutter-actor.c:3494
msgid "Y coordinate"
msgstr "Współrzędna Y"
-#: clutter/clutter-actor.c:3497
+#: clutter/clutter-actor.c:3495
msgid "Y coordinate of the actor"
msgstr "Współrzędna Y aktora"
-#: clutter/clutter-actor.c:3512 clutter/clutter-behaviour-ellipse.c:475
+#: clutter/clutter-actor.c:3510 clutter/clutter-behaviour-ellipse.c:474
msgid "Width"
msgstr "Szerokość"
-#: clutter/clutter-actor.c:3513
+#: clutter/clutter-actor.c:3511
msgid "Width of the actor"
msgstr "Szerokość aktora"
-#: clutter/clutter-actor.c:3527 clutter/clutter-behaviour-ellipse.c:491
+#: clutter/clutter-actor.c:3525 clutter/clutter-behaviour-ellipse.c:490
msgid "Height"
msgstr "Wysokość"
-#: clutter/clutter-actor.c:3528
+#: clutter/clutter-actor.c:3526
msgid "Height of the actor"
msgstr "Wysokość aktora"
-#: clutter/clutter-actor.c:3546
+#: clutter/clutter-actor.c:3544
msgid "Fixed X"
msgstr "Stała współrzędna X"
-#: clutter/clutter-actor.c:3547
+#: clutter/clutter-actor.c:3545
msgid "Forced X position of the actor"
msgstr "Wymuszone położenie X aktora"
-#: clutter/clutter-actor.c:3565
+#: clutter/clutter-actor.c:3563
msgid "Fixed Y"
msgstr "Stała współrzędna Y"
-#: clutter/clutter-actor.c:3566
+#: clutter/clutter-actor.c:3564
msgid "Forced Y position of the actor"
msgstr "Wymuszone położenie Y aktora"
-#: clutter/clutter-actor.c:3582
+#: clutter/clutter-actor.c:3580
msgid "Fixed position set"
msgstr "Ustawienie stałego położenia"
-#: clutter/clutter-actor.c:3583
+#: clutter/clutter-actor.c:3581
msgid "Whether to use fixed positioning for the actor"
msgstr "Określa, czy używać stałego położenia aktora"
-#: clutter/clutter-actor.c:3605
+#: clutter/clutter-actor.c:3603
msgid "Min Width"
msgstr "Minimalna szerokość"
-#: clutter/clutter-actor.c:3606
+#: clutter/clutter-actor.c:3604
msgid "Forced minimum width request for the actor"
msgstr "Wymuszone żądanie minimalnej szerokości aktora"
-#: clutter/clutter-actor.c:3625
+#: clutter/clutter-actor.c:3623
msgid "Min Height"
msgstr "Minimalna wysokość"
-#: clutter/clutter-actor.c:3626
+#: clutter/clutter-actor.c:3624
msgid "Forced minimum height request for the actor"
msgstr "Wymuszone żądanie minimalnej wysokości aktora"
-#: clutter/clutter-actor.c:3645
+#: clutter/clutter-actor.c:3643
msgid "Natural Width"
msgstr "Naturalna szerokość"
-#: clutter/clutter-actor.c:3646
+#: clutter/clutter-actor.c:3644
msgid "Forced natural width request for the actor"
msgstr "Wymuszone żądanie naturalnej szerokości aktora"
-#: clutter/clutter-actor.c:3665
+#: clutter/clutter-actor.c:3663
msgid "Natural Height"
msgstr "Naturalna wysokość"
-#: clutter/clutter-actor.c:3666
+#: clutter/clutter-actor.c:3664
msgid "Forced natural height request for the actor"
msgstr "Wymuszone żądanie naturalnej wysokości aktora"
-#: clutter/clutter-actor.c:3682
+#: clutter/clutter-actor.c:3680
msgid "Minimum width set"
msgstr "Ustawienie minimalnej szerokości"
-#: clutter/clutter-actor.c:3683
+#: clutter/clutter-actor.c:3681
msgid "Whether to use the min-width property"
msgstr "Określa, czy używać właściwości \"min-width\""
-#: clutter/clutter-actor.c:3698
+#: clutter/clutter-actor.c:3696
msgid "Minimum height set"
msgstr "Ustawienie minimalnej wysokości"
-#: clutter/clutter-actor.c:3699
+#: clutter/clutter-actor.c:3697
msgid "Whether to use the min-height property"
msgstr "Określa, czy używać właściwości \"min-height\""
-#: clutter/clutter-actor.c:3714
+#: clutter/clutter-actor.c:3712
msgid "Natural width set"
msgstr "Ustawienie naturalnej szerokości"
-#: clutter/clutter-actor.c:3715
+#: clutter/clutter-actor.c:3713
msgid "Whether to use the natural-width property"
msgstr "Określa, czy używać właściwości \"natural-width\""
-#: clutter/clutter-actor.c:3732
+#: clutter/clutter-actor.c:3730
msgid "Natural height set"
msgstr "Ustawienie naturalnej wysokości"
-#: clutter/clutter-actor.c:3733
+#: clutter/clutter-actor.c:3731
msgid "Whether to use the natural-height property"
msgstr "Określa, czy używać właściwości \"natural-height\""
-#: clutter/clutter-actor.c:3752
+#: clutter/clutter-actor.c:3750
msgid "Allocation"
msgstr "Przydzielenie"
-#: clutter/clutter-actor.c:3753
+#: clutter/clutter-actor.c:3751
msgid "The actor's allocation"
msgstr "Przydzielenie aktora"
-#: clutter/clutter-actor.c:3809
+#: clutter/clutter-actor.c:3807
msgid "Request Mode"
msgstr "Tryb żądania"
-#: clutter/clutter-actor.c:3810
+#: clutter/clutter-actor.c:3808
msgid "The actor's request mode"
msgstr "Tryb żądania aktora"
-#: clutter/clutter-actor.c:3825
+#: clutter/clutter-actor.c:3823
msgid "Depth"
msgstr "Głębia"
-#: clutter/clutter-actor.c:3826
+#: clutter/clutter-actor.c:3824
msgid "Position on the Z axis"
msgstr "Położenie na osi Z"
-#: clutter/clutter-actor.c:3840
+#: clutter/clutter-actor.c:3838
msgid "Opacity"
msgstr "Nieprzezroczystość"
-#: clutter/clutter-actor.c:3841
+#: clutter/clutter-actor.c:3839
msgid "Opacity of an actor"
msgstr "Nieprzezroczystość aktora"
-#: clutter/clutter-actor.c:3856
+#: clutter/clutter-actor.c:3854
msgid "Visible"
msgstr "Widoczny"
-#: clutter/clutter-actor.c:3857
+#: clutter/clutter-actor.c:3855
msgid "Whether the actor is visible or not"
msgstr "Określa, czy aktor jest widoczny"
-#: clutter/clutter-actor.c:3872
+#: clutter/clutter-actor.c:3870
msgid "Mapped"
msgstr "Mapowany"
-#: clutter/clutter-actor.c:3873
+#: clutter/clutter-actor.c:3871
msgid "Whether the actor will be painted"
msgstr "Określa, czy aktor będzie pomalowany"
-#: clutter/clutter-actor.c:3887
+#: clutter/clutter-actor.c:3885
msgid "Realized"
msgstr "Zrealizowany"
-#: clutter/clutter-actor.c:3888
+#: clutter/clutter-actor.c:3886
msgid "Whether the actor has been realized"
msgstr "Określa, czy aktor został zrealizowany"
-#: clutter/clutter-actor.c:3904
+#: clutter/clutter-actor.c:3902
msgid "Reactive"
msgstr "Reakcyjny"
-#: clutter/clutter-actor.c:3905
+#: clutter/clutter-actor.c:3903
msgid "Whether the actor is reactive to events"
msgstr "Określa, czy aktor reaguje na zdarzenia"
-#: clutter/clutter-actor.c:3917
+#: clutter/clutter-actor.c:3915
msgid "Has Clip"
msgstr "Posiada klamrę"
-#: clutter/clutter-actor.c:3918
+#: clutter/clutter-actor.c:3916
msgid "Whether the actor has a clip set"
msgstr "Określa, czy aktor posiada ustawioną klamrę"
-#: clutter/clutter-actor.c:3933
+#: clutter/clutter-actor.c:3931
msgid "Clip"
msgstr "Klamra"
-#: clutter/clutter-actor.c:3934
+#: clutter/clutter-actor.c:3932
msgid "The clip region for the actor"
msgstr "Obszar klamry aktora"
-#: clutter/clutter-actor.c:3948 clutter/clutter-actor-meta.c:205
-#: clutter/clutter-binding-pool.c:320 clutter/clutter-input-device.c:151
+#: clutter/clutter-actor.c:3946 clutter/clutter-actor-meta.c:205
+#: clutter/clutter-binding-pool.c:319 clutter/clutter-input-device.c:235
msgid "Name"
msgstr "Nazwa"
-#: clutter/clutter-actor.c:3949
+#: clutter/clutter-actor.c:3947
msgid "Name of the actor"
msgstr "Nazwa aktora"
-#: clutter/clutter-actor.c:3963
+#: clutter/clutter-actor.c:3961
msgid "Scale X"
msgstr "Skalowanie współrzędnej X"
-#: clutter/clutter-actor.c:3964
+#: clutter/clutter-actor.c:3962
msgid "Scale factor on the X axis"
msgstr "Czynnik skalowania na osi X"
-#: clutter/clutter-actor.c:3979
+#: clutter/clutter-actor.c:3977
msgid "Scale Y"
msgstr "Skalowanie współrzędnej Y"
-#: clutter/clutter-actor.c:3980
+#: clutter/clutter-actor.c:3978
msgid "Scale factor on the Y axis"
msgstr "Czynnik skalowania na osi Y"
-#: clutter/clutter-actor.c:3995
+#: clutter/clutter-actor.c:3993
msgid "Scale Center X"
msgstr "Środek skalowania współrzędnej X"
-#: clutter/clutter-actor.c:3996
+#: clutter/clutter-actor.c:3994
msgid "Horizontal scale center"
msgstr "Poziomy środek skalowania"
-#: clutter/clutter-actor.c:4011
+#: clutter/clutter-actor.c:4009
msgid "Scale Center Y"
msgstr "Środek skalowania współrzędnej Y"
-#: clutter/clutter-actor.c:4012
+#: clutter/clutter-actor.c:4010
msgid "Vertical scale center"
msgstr "Pionowy środek skalowania"
-#: clutter/clutter-actor.c:4027
+#: clutter/clutter-actor.c:4025
msgid "Scale Gravity"
msgstr "Grawitacja skalowania"
-#: clutter/clutter-actor.c:4028
+#: clutter/clutter-actor.c:4026
msgid "The center of scaling"
msgstr "Środek skalowania"
-#: clutter/clutter-actor.c:4045
+#: clutter/clutter-actor.c:4043
msgid "Rotation Angle X"
msgstr "Kąt obrotu współrzędnej X"
-#: clutter/clutter-actor.c:4046
+#: clutter/clutter-actor.c:4044
msgid "The rotation angle on the X axis"
msgstr "Kąt obrotu na osi X"
-#: clutter/clutter-actor.c:4061
+#: clutter/clutter-actor.c:4059
msgid "Rotation Angle Y"
msgstr "Kąt obrotu współrzędnej Y"
-#: clutter/clutter-actor.c:4062
+#: clutter/clutter-actor.c:4060
msgid "The rotation angle on the Y axis"
msgstr "Kąt obrotu na osi Y"
-#: clutter/clutter-actor.c:4077
+#: clutter/clutter-actor.c:4075
msgid "Rotation Angle Z"
msgstr "Kąt obrotu współrzędnej Z"
-#: clutter/clutter-actor.c:4078
+#: clutter/clutter-actor.c:4076
msgid "The rotation angle on the Z axis"
msgstr "Kąt obrotu na osi Z"
-#: clutter/clutter-actor.c:4093
+#: clutter/clutter-actor.c:4091
msgid "Rotation Center X"
msgstr "Środek obrotu współrzędnej X"
-#: clutter/clutter-actor.c:4094
+#: clutter/clutter-actor.c:4092
msgid "The rotation center on the X axis"
msgstr "Środek obrotu na osi X"
-#: clutter/clutter-actor.c:4110
+#: clutter/clutter-actor.c:4108
msgid "Rotation Center Y"
msgstr "Środek obrotu współrzędnej Y"
-#: clutter/clutter-actor.c:4111
+#: clutter/clutter-actor.c:4109
msgid "The rotation center on the Y axis"
msgstr "Środek obrotu na osi Y"
-#: clutter/clutter-actor.c:4127
+#: clutter/clutter-actor.c:4125
msgid "Rotation Center Z"
msgstr "Środek obrotu współrzędnej Z"
-#: clutter/clutter-actor.c:4128
+#: clutter/clutter-actor.c:4126
msgid "The rotation center on the Z axis"
msgstr "Środek obrotu na osi Z"
-#: clutter/clutter-actor.c:4144
+#: clutter/clutter-actor.c:4142
msgid "Rotation Center Z Gravity"
msgstr "Grawitacja środka obrotu współrzędnej Z"
-#: clutter/clutter-actor.c:4145
+#: clutter/clutter-actor.c:4143
msgid "Center point for rotation around the Z axis"
msgstr "Punkt środkowy dla obrotu wokół osi Z"
-#: clutter/clutter-actor.c:4163
+#: clutter/clutter-actor.c:4161
msgid "Anchor X"
msgstr "Kotwica współrzędnej X"
-#: clutter/clutter-actor.c:4164
+#: clutter/clutter-actor.c:4162
msgid "X coordinate of the anchor point"
msgstr "Współrzędna X punktu kotwicy"
-#: clutter/clutter-actor.c:4180
+#: clutter/clutter-actor.c:4178
msgid "Anchor Y"
msgstr "Kotwica współrzędnej Y"
-#: clutter/clutter-actor.c:4181
+#: clutter/clutter-actor.c:4179
msgid "Y coordinate of the anchor point"
msgstr "Współrzędna Y punktu kotwicy"
-#: clutter/clutter-actor.c:4196
+#: clutter/clutter-actor.c:4194
msgid "Anchor Gravity"
msgstr "Grawitacja kotwicy"
-#: clutter/clutter-actor.c:4197
+#: clutter/clutter-actor.c:4195
msgid "The anchor point as a ClutterGravity"
msgstr "Punkt kotwicy jako \"ClutterGravity\""
-#: clutter/clutter-actor.c:4216
+#: clutter/clutter-actor.c:4214
msgid "Show on set parent"
msgstr "Wyświetlanie na ustawionym rodzicu"
-#: clutter/clutter-actor.c:4217
+#: clutter/clutter-actor.c:4215
msgid "Whether the actor is shown when parented"
msgstr "Określa, czy aktor jest wyświetlany, kiedy posiada rodzica"
-#: clutter/clutter-actor.c:4237
+#: clutter/clutter-actor.c:4235
msgid "Clip to Allocation"
msgstr "Klamra do przydziału"
-#: clutter/clutter-actor.c:4238
+#: clutter/clutter-actor.c:4236
msgid "Sets the clip region to track the actor's allocation"
msgstr "Ustawia obszar klamry do śledzenia przydzielenia aktora"
-#: clutter/clutter-actor.c:4248
+#: clutter/clutter-actor.c:4246
msgid "Text Direction"
msgstr "Kierunek tekstu"
-#: clutter/clutter-actor.c:4249
+#: clutter/clutter-actor.c:4247
msgid "Direction of the text"
msgstr "Kierunek tekstu"
-#: clutter/clutter-actor.c:4267
+#: clutter/clutter-actor.c:4265
msgid "Has Pointer"
msgstr "Posiada wskaźnik"
-#: clutter/clutter-actor.c:4268
+#: clutter/clutter-actor.c:4266
msgid "Whether the actor contains the pointer of an input device"
msgstr "Określa, czy aktor zawiera wskaźnik urządzenia wejścia"
-#: clutter/clutter-actor.c:4285
+#: clutter/clutter-actor.c:4283
msgid "Actions"
msgstr "Działania"
-#: clutter/clutter-actor.c:4286
+#: clutter/clutter-actor.c:4284
msgid "Adds an action to the actor"
msgstr "Dodaje działania do aktora"
-#: clutter/clutter-actor.c:4300
+#: clutter/clutter-actor.c:4298
msgid "Constraints"
msgstr "Ograniczenia"
-#: clutter/clutter-actor.c:4301
+#: clutter/clutter-actor.c:4299
msgid "Adds a constraint to the actor"
msgstr "Dodaje ograniczenie do aktora"
msgid "The name of the meta"
msgstr "Nazwa mety"
-#: clutter/clutter-actor-meta.c:219 clutter/clutter-shader.c:261
+#: clutter/clutter-actor-meta.c:219 clutter/clutter-input-device.c:314
+#: clutter/clutter-shader.c:295
msgid "Enabled"
msgstr "Włączone"
msgid "Whether the meta is enabled"
msgstr "Określa, czy meta jest włączona"
-#: clutter/clutter-align-constraint.c:231
-#: clutter/clutter-bind-constraint.c:286 clutter/clutter-clone.c:322
+#: clutter/clutter-align-constraint.c:252
+#: clutter/clutter-bind-constraint.c:316 clutter/clutter-clone.c:322
msgid "Source"
msgstr "Źródło"
-#: clutter/clutter-align-constraint.c:232
+#: clutter/clutter-align-constraint.c:253
msgid "The source of the alignment"
msgstr "Źródło wyrównania"
-#: clutter/clutter-align-constraint.c:245
+#: clutter/clutter-align-constraint.c:266
msgid "Align Axis"
msgstr "Osie wyrównania"
-#: clutter/clutter-align-constraint.c:246
+#: clutter/clutter-align-constraint.c:267
msgid "The axis to align the position to"
msgstr "Osie, do których wyrównać położenie"
-#: clutter/clutter-align-constraint.c:265
-#: clutter/clutter-desaturate-effect.c:309
+#: clutter/clutter-align-constraint.c:286
+#: clutter/clutter-desaturate-effect.c:307
msgid "Factor"
msgstr "Czynnik"
-#: clutter/clutter-align-constraint.c:266
+#: clutter/clutter-align-constraint.c:287
msgid "The alignment factor, between 0.0 and 1.0"
msgstr "Czynnik wyrównania, między 0.0 a 1.0"
#: clutter/clutter-alpha.c:339 clutter/clutter-animation.c:523
-#: clutter/clutter-animator.c:1801
+#: clutter/clutter-animator.c:1802
msgid "Timeline"
msgstr "Oś czasu"
msgid "The mode of the animation"
msgstr "Tryb animacji"
-#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1785
+#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1786
#: clutter/clutter-media.c:194 clutter/clutter-state.c:1282
msgid "Duration"
msgstr "Czas trwania"
msgid "The timeline used by the animation"
msgstr "Oś czasu używana przez animację"
-#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:299
+#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:298
msgid "Alpha"
msgstr "Alfa"
msgid "The alpha used by the animation"
msgstr "Alfa używana przez animację"
-#: clutter/clutter-animator.c:1786
+#: clutter/clutter-animator.c:1787
msgid "The duration of the animation"
msgstr "Czas trwania animacji"
-#: clutter/clutter-animator.c:1802
+#: clutter/clutter-animator.c:1803
msgid "The timeline of the animation"
msgstr "Oś czasu animacji"
-#: clutter/clutter-behaviour.c:300
+#: clutter/clutter-behaviour.c:299
msgid "Alpha Object to drive the behaviour"
msgstr "Obiekt alfa prowadzący zachowanie"
-#: clutter/clutter-behaviour-depth.c:175
+#: clutter/clutter-behaviour-depth.c:174
msgid "Start Depth"
msgstr "Głębia początkowa"
-#: clutter/clutter-behaviour-depth.c:176
+#: clutter/clutter-behaviour-depth.c:175
msgid "Initial depth to apply"
msgstr "Początkowa głębia do zastosowania"
-#: clutter/clutter-behaviour-depth.c:191
+#: clutter/clutter-behaviour-depth.c:190
msgid "End Depth"
msgstr "Głębia końcowa"
-#: clutter/clutter-behaviour-depth.c:192
+#: clutter/clutter-behaviour-depth.c:191
msgid "Final depth to apply"
msgstr "Końcowa głębia do zastosowania"
-#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-ellipse.c:394
msgid "Start Angle"
msgstr "Kąt początkowy"
-#: clutter/clutter-behaviour-ellipse.c:396
-#: clutter/clutter-behaviour-rotate.c:277
+#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-rotate.c:276
msgid "Initial angle"
msgstr "Kąt początkowy"
-#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-ellipse.c:410
msgid "End Angle"
msgstr "Kąt końcowy"
-#: clutter/clutter-behaviour-ellipse.c:412
-#: clutter/clutter-behaviour-rotate.c:295
+#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-rotate.c:294
msgid "Final angle"
msgstr "Kąt końcowy"
-#: clutter/clutter-behaviour-ellipse.c:427
+#: clutter/clutter-behaviour-ellipse.c:426
msgid "Angle x tilt"
msgstr "Nachylenie kąta współrzędnej X"
-#: clutter/clutter-behaviour-ellipse.c:428
+#: clutter/clutter-behaviour-ellipse.c:427
msgid "Tilt of the ellipse around x axis"
msgstr "Nachylenie elipsy wokół osi X"
-#: clutter/clutter-behaviour-ellipse.c:443
+#: clutter/clutter-behaviour-ellipse.c:442
msgid "Angle y tilt"
msgstr "Nachylenie kąta współrzędnej Y"
-#: clutter/clutter-behaviour-ellipse.c:444
+#: clutter/clutter-behaviour-ellipse.c:443
msgid "Tilt of the ellipse around y axis"
msgstr "Nachylenie elipsy wokół osi Y"
-#: clutter/clutter-behaviour-ellipse.c:459
+#: clutter/clutter-behaviour-ellipse.c:458
msgid "Angle z tilt"
msgstr "Nachylenie kąta współrzędnej Z"
-#: clutter/clutter-behaviour-ellipse.c:460
+#: clutter/clutter-behaviour-ellipse.c:459
msgid "Tilt of the ellipse around z axis"
msgstr "Nachylenie elipsy wokół osi Z"
-#: clutter/clutter-behaviour-ellipse.c:476
+#: clutter/clutter-behaviour-ellipse.c:475
msgid "Width of the ellipse"
msgstr "Szerokość alipsy"
-#: clutter/clutter-behaviour-ellipse.c:492
+#: clutter/clutter-behaviour-ellipse.c:491
msgid "Height of ellipse"
msgstr "Wysokość elipsy"
-#: clutter/clutter-behaviour-ellipse.c:507
+#: clutter/clutter-behaviour-ellipse.c:506
msgid "Center"
msgstr "Środek"
-#: clutter/clutter-behaviour-ellipse.c:508
+#: clutter/clutter-behaviour-ellipse.c:507
msgid "Center of ellipse"
msgstr "Środek elipsy"
-#: clutter/clutter-behaviour-ellipse.c:522
-#: clutter/clutter-behaviour-rotate.c:330
+#: clutter/clutter-behaviour-ellipse.c:521
+#: clutter/clutter-behaviour-rotate.c:329
msgid "Direction"
msgstr "Kierunek"
-#: clutter/clutter-behaviour-ellipse.c:523
-#: clutter/clutter-behaviour-rotate.c:331
+#: clutter/clutter-behaviour-ellipse.c:522
+#: clutter/clutter-behaviour-rotate.c:330
msgid "Direction of rotation"
msgstr "Kierunek obrotu"
-#: clutter/clutter-behaviour-opacity.c:178
+#: clutter/clutter-behaviour-opacity.c:177
msgid "Opacity Start"
msgstr "Początkowa nieprzezroczystość"
-#: clutter/clutter-behaviour-opacity.c:179
+#: clutter/clutter-behaviour-opacity.c:178
msgid "Initial opacity level"
msgstr "Początkowy poziom nieprzezroczystości"
-#: clutter/clutter-behaviour-opacity.c:196
+#: clutter/clutter-behaviour-opacity.c:195
msgid "Opacity End"
msgstr "Końcowa nieprzezroczystość"
-#: clutter/clutter-behaviour-opacity.c:197
+#: clutter/clutter-behaviour-opacity.c:196
msgid "Final opacity level"
msgstr "Końcowy poziom nieprzezroczystości"
-#: clutter/clutter-behaviour-path.c:220
+#: clutter/clutter-behaviour-path.c:219
msgid "Path"
msgstr "Ścieżka"
-#: clutter/clutter-behaviour-path.c:221
+#: clutter/clutter-behaviour-path.c:220
msgid "The ClutterPath object representing the path to animate along"
msgstr "Obiekt \"ClutterPath\" przedstawiający ścieżkę, na której animować"
-#: clutter/clutter-behaviour-rotate.c:276
+#: clutter/clutter-behaviour-rotate.c:275
msgid "Angle Begin"
msgstr "Kąt początkowy"
-#: clutter/clutter-behaviour-rotate.c:294
+#: clutter/clutter-behaviour-rotate.c:293
msgid "Angle End"
msgstr "Kąt końcowy"
-#: clutter/clutter-behaviour-rotate.c:312
+#: clutter/clutter-behaviour-rotate.c:311
msgid "Axis"
msgstr "Oś"
-#: clutter/clutter-behaviour-rotate.c:313
+#: clutter/clutter-behaviour-rotate.c:312
msgid "Axis of rotation"
msgstr "Oś obrotu"
-#: clutter/clutter-behaviour-rotate.c:348
+#: clutter/clutter-behaviour-rotate.c:347
msgid "Center X"
msgstr "Środek współrzędnej X"
-#: clutter/clutter-behaviour-rotate.c:349
+#: clutter/clutter-behaviour-rotate.c:348
msgid "X coordinate of the center of rotation"
msgstr "Współrzędna X środka obrotu"
-#: clutter/clutter-behaviour-rotate.c:366
+#: clutter/clutter-behaviour-rotate.c:365
msgid "Center Y"
msgstr "Środek współrzędnej Y"
-#: clutter/clutter-behaviour-rotate.c:367
+#: clutter/clutter-behaviour-rotate.c:366
msgid "Y coordinate of the center of rotation"
msgstr "Współrzędna Y środka obrotu"
-#: clutter/clutter-behaviour-rotate.c:384
+#: clutter/clutter-behaviour-rotate.c:383
msgid "Center Z"
msgstr "Środek współrzędnej Z"
-#: clutter/clutter-behaviour-rotate.c:385
+#: clutter/clutter-behaviour-rotate.c:384
msgid "Z coordinate of the center of rotation"
msgstr "Współrzędna Z środka obrotu"
-#: clutter/clutter-behaviour-scale.c:219
+#: clutter/clutter-behaviour-scale.c:218
msgid "X Start Scale"
msgstr "Początkowe skalowanie współrzędnej X"
-#: clutter/clutter-behaviour-scale.c:220
+#: clutter/clutter-behaviour-scale.c:219
msgid "Initial scale on the X axis"
msgstr "Początkowe skalowanie na osi X"
-#: clutter/clutter-behaviour-scale.c:238
+#: clutter/clutter-behaviour-scale.c:237
msgid "X End Scale"
msgstr "Końcowe skalowanie współrzędnej X"
-#: clutter/clutter-behaviour-scale.c:239
+#: clutter/clutter-behaviour-scale.c:238
msgid "Final scale on the X axis"
msgstr "Końcowe skalowanie na osi X"
-#: clutter/clutter-behaviour-scale.c:257
+#: clutter/clutter-behaviour-scale.c:256
msgid "Y Start Scale"
msgstr "Początkowe skalowanie współrzędnej Y"
-#: clutter/clutter-behaviour-scale.c:258
+#: clutter/clutter-behaviour-scale.c:257
msgid "Initial scale on the Y axis"
msgstr "Początkowe skalowanie na osi Y"
-#: clutter/clutter-behaviour-scale.c:276
+#: clutter/clutter-behaviour-scale.c:275
msgid "Y End Scale"
msgstr "Końcowe skalowanie współrzędnej Y"
-#: clutter/clutter-behaviour-scale.c:277
+#: clutter/clutter-behaviour-scale.c:276
msgid "Final scale on the Y axis"
msgstr "Końcowe skalowanie na osi Y"
-#: clutter/clutter-bind-constraint.c:287
+#: clutter/clutter-bind-constraint.c:317
msgid "The source of the binding"
msgstr "Źródło dowiązania"
-#: clutter/clutter-bind-constraint.c:300
+#: clutter/clutter-bind-constraint.c:330
msgid "Coordinate"
msgstr "Współrzędna"
-#: clutter/clutter-bind-constraint.c:301
+#: clutter/clutter-bind-constraint.c:331
msgid "The coordinate to bind"
msgstr "Współrzędna do dowiązania"
-#: clutter/clutter-bind-constraint.c:315
+#: clutter/clutter-bind-constraint.c:345
msgid "Offset"
msgstr "Offset"
-#: clutter/clutter-bind-constraint.c:316
+#: clutter/clutter-bind-constraint.c:346
msgid "The offset in pixels to apply to the binding"
msgstr "Offset w pikselach do zastosowania do dowiązania"
msgid "Default vertical alignment for the actors inside the layout manager"
msgstr "Domyślne pionowe wyrównanie aktora wewnątrz menedżera warstw"
-#: clutter/clutter-binding-pool.c:321
+#: clutter/clutter-binding-pool.c:320
msgid "The unique name of the binding pool"
msgstr "Unikalna nazwa puli dowiązania"
msgstr "Menedżer warstw używany przez to pole"
#: clutter/clutter-box.c:514 clutter/clutter-rectangle.c:258
-#: clutter/clutter-stage.c:1307
+#: clutter/clutter-stage.c:1317
msgid "Color"
msgstr "Kolor"
msgid "The actor wrapped by this data"
msgstr "Aktor opakowany przez te dane"
-#: clutter/clutter-click-action.c:283
+#: clutter/clutter-click-action.c:302
msgid "Pressed"
msgstr "Wciśnięte"
-#: clutter/clutter-click-action.c:284
+#: clutter/clutter-click-action.c:303
msgid "Whether the clickable should be in pressed state"
msgstr "Określa, czy element klikalny jest w stanie wciśniętym"
-#: clutter/clutter-click-action.c:297
+#: clutter/clutter-click-action.c:316
msgid "Held"
msgstr "Przytrzymane"
-#: clutter/clutter-click-action.c:298
+#: clutter/clutter-click-action.c:317
msgid "Whether the clickable has a grab"
msgstr "Określa, czy element klikalny posiada przytrzymanie"
msgid "Specifies the actor to be cloned"
msgstr "Podaje aktora do sklonowania"
-#: clutter/clutter-colorize-effect.c:309
+#: clutter/clutter-colorize-effect.c:307
msgid "Tint"
msgstr "Odcień"
-#: clutter/clutter-colorize-effect.c:310
+#: clutter/clutter-colorize-effect.c:308
msgid "The tint to apply"
msgstr "Odcień do zastosowania"
msgid "The material to be used when painting the back of the actor"
msgstr "Materiał używany podczas malowania tyłu aktora"
-#: clutter/clutter-desaturate-effect.c:310
+#: clutter/clutter-desaturate-effect.c:308
msgid "The desaturation factor"
msgstr "Czynnik usuwania nasycenia"
-#: clutter/clutter-device-manager.c:130
+#: clutter/clutter-device-manager.c:130 clutter/clutter-input-device.c:343
msgid "Backend"
msgstr "Mechanizm"
msgid "The ClutterBackend of the device manager"
msgstr "Mechanizm \"ClutterBackend\" menedżera urządzeń"
-#: clutter/clutter-drag-action.c:490
+#: clutter/clutter-drag-action.c:491
msgid "Horizontal Drag Threshold"
msgstr "Poziomy próg przeciągnięcia"
-#: clutter/clutter-drag-action.c:491
+#: clutter/clutter-drag-action.c:492
msgid "The horizontal amount of pixels required to start dragging"
msgstr "Liczba poziomych pikseli wymaganych do rozpoczęcia przeciągania"
-#: clutter/clutter-drag-action.c:510
+#: clutter/clutter-drag-action.c:511
msgid "Vertical Drag Threshold"
msgstr "Pionowy próg przeciągnięcia"
-#: clutter/clutter-drag-action.c:511
+#: clutter/clutter-drag-action.c:512
msgid "The vertical amount of pixels required to start dragging"
msgstr "Liczba pionowych pikseli wymaganych do rozpoczęcia przeciągania"
-#: clutter/clutter-drag-action.c:532
+#: clutter/clutter-drag-action.c:533
msgid "Drag Handle"
msgstr "Uchwyt przeciągnięcia"
-#: clutter/clutter-drag-action.c:533
+#: clutter/clutter-drag-action.c:534
msgid "The actor that is being dragged"
msgstr "Przeciągany aktor"
-#: clutter/clutter-drag-action.c:546
+#: clutter/clutter-drag-action.c:547
msgid "Drag Axis"
msgstr "Osie przeciągnięcia"
-#: clutter/clutter-drag-action.c:547
+#: clutter/clutter-drag-action.c:548
msgid "Constraints the dragging to an axis"
msgstr "Ogranicza przeciągnięcia do osi"
msgid "Maximum height for each row"
msgstr "Maksymalna wysokość każdego wiersza"
-#: clutter/clutter-input-device.c:134
+#: clutter/clutter-input-device.c:219
msgid "Id"
msgstr "Identyfikator"
-#: clutter/clutter-input-device.c:135
+#: clutter/clutter-input-device.c:220
msgid "Unique identifier of the device"
msgstr "Unikalny identyfikator urządzenia"
-#: clutter/clutter-input-device.c:152
+#: clutter/clutter-input-device.c:236
msgid "The name of the device"
msgstr "Nazwa urządzenia"
-#: clutter/clutter-input-device.c:167
+#: clutter/clutter-input-device.c:250
msgid "Device Type"
msgstr "Typ urządzenia"
-#: clutter/clutter-input-device.c:168
+#: clutter/clutter-input-device.c:251
msgid "The type of the device"
msgstr "Typ urządzenia"
+#: clutter/clutter-input-device.c:266
+#, fuzzy
+msgid "Device Manager"
+msgstr "Menedżer"
+
+#: clutter/clutter-input-device.c:267
+msgid "The device manager instance"
+msgstr ""
+
+#: clutter/clutter-input-device.c:280
+#, fuzzy
+msgid "Device Mode"
+msgstr "Typ urządzenia"
+
+#: clutter/clutter-input-device.c:281
+#, fuzzy
+msgid "The mode of the device"
+msgstr "Nazwa urządzenia"
+
+#: clutter/clutter-input-device.c:295
+#, fuzzy
+msgid "Has Cursor"
+msgstr "Posiada krawędź"
+
+#: clutter/clutter-input-device.c:296
+#, fuzzy
+msgid "Whether the device has a cursor"
+msgstr "Określa, czy element klikalny posiada przytrzymanie"
+
+#: clutter/clutter-input-device.c:315
+#, fuzzy
+msgid "Whether the device is enabled"
+msgstr "Określa, czy cieniowanie jest włączone"
+
+#: clutter/clutter-input-device.c:328
+msgid "Number of Axes"
+msgstr ""
+
+#: clutter/clutter-input-device.c:329
+#, fuzzy
+msgid "The number of axes on the device"
+msgstr "Nazwa urządzenia"
+
+#: clutter/clutter-input-device.c:344
+msgid "The backend instance"
+msgstr ""
+
#: clutter/clutter-interval.c:397
msgid "Value Type"
msgstr "Typ wartości"
msgid "The manager that created this data"
msgstr "Menedżer, który utworzył te dane"
-#: clutter/clutter-main.c:756
+#: clutter/clutter-main.c:753
msgid "default:LTR"
msgstr "default:LTR"
-#: clutter/clutter-main.c:1560
+#: clutter/clutter-main.c:1557
msgid "Show frames per second"
msgstr "Wyświetla liczbę klatek na sekundę"
-#: clutter/clutter-main.c:1562
+#: clutter/clutter-main.c:1559
msgid "Default frame rate"
msgstr "Domyślna liczba klatek na sekundę"
-#: clutter/clutter-main.c:1564
+#: clutter/clutter-main.c:1561
msgid "Make all warnings fatal"
msgstr "Wszystkie ostrzeżenia są krytyczne"
-#: clutter/clutter-main.c:1567
+#: clutter/clutter-main.c:1564
msgid "Direction for the text"
msgstr "Kierunek tekstu"
-#: clutter/clutter-main.c:1570
+#: clutter/clutter-main.c:1567
msgid "Disable mipmapping on text"
msgstr "Wyłącza mipmapowanie na tekście"
-#: clutter/clutter-main.c:1573
+#: clutter/clutter-main.c:1570
msgid "Use 'fuzzy' picking"
msgstr "Używa wybierania \"rozmytego\""
-#: clutter/clutter-main.c:1576
+#: clutter/clutter-main.c:1573
msgid "Clutter debugging flags to set"
msgstr "Flagi debugowania biblioteki Clutter do ustawienia"
-#: clutter/clutter-main.c:1578
+#: clutter/clutter-main.c:1575
msgid "Clutter debugging flags to unset"
msgstr "Flagi debugowania biblioteki Clutter do usunięcia"
-#: clutter/clutter-main.c:1582
+#: clutter/clutter-main.c:1579
msgid "Clutter profiling flags to set"
msgstr "Flagi profilowania biblioteki Clutter do ustawienia"
-#: clutter/clutter-main.c:1584
+#: clutter/clutter-main.c:1581
msgid "Clutter profiling flags to unset"
msgstr "Flagi profilowania biblioteki Clutter do usunięcia"
-#: clutter/clutter-main.c:1587
+#: clutter/clutter-main.c:1584
msgid "Enable accessibility"
msgstr "Włącza dostępność"
-#: clutter/clutter-main.c:1774
+#: clutter/clutter-main.c:1771
msgid "Clutter Options"
msgstr "Opcje biblioteki Clutter"
-#: clutter/clutter-main.c:1775
+#: clutter/clutter-main.c:1772
msgid "Show Clutter Options"
msgstr "Wyświetla opcje biblioteki Clutter"
msgid "The path of the currently parsed file"
msgstr "Ścieżka do obecnie przetwarzanego pliku"
-#: clutter/clutter-shader.c:215
+#: clutter/clutter-shader.c:249
msgid "Vertex Source"
msgstr "Źródło wierzchołków"
-#: clutter/clutter-shader.c:216
+#: clutter/clutter-shader.c:250
msgid "Source of vertex shader"
msgstr "Źródło cieniowania wierzchołkowego"
-#: clutter/clutter-shader.c:230
+#: clutter/clutter-shader.c:264
msgid "Fragment Source"
msgstr "Źródło fragmentów"
-#: clutter/clutter-shader.c:231
+#: clutter/clutter-shader.c:265
msgid "Source of fragment shader"
msgstr "Źródło cieniowania fragmentów"
-#: clutter/clutter-shader.c:246
+#: clutter/clutter-shader.c:280
msgid "Compiled"
msgstr "Skompilowany"
-#: clutter/clutter-shader.c:247
+#: clutter/clutter-shader.c:281
msgid "Whether the shader is compiled and linked"
msgstr "Określa, czy cieniowanie jest skompilowane i skonsolidowane"
-#: clutter/clutter-shader.c:262
+#: clutter/clutter-shader.c:296
msgid "Whether the shader is enabled"
msgstr "Określa, czy cieniowanie jest włączone"
-#: clutter/clutter-shader.c:467
+#: clutter/clutter-shader.c:501
#, c-format
msgid "%s compilation failed: %s"
msgstr "Kompilacja %s się nie powiodła: %s"
-#: clutter/clutter-shader.c:468
+#: clutter/clutter-shader.c:502
msgid "Vertex shader"
msgstr "Cieniowanie wierzchołkowe"
-#: clutter/clutter-shader.c:469
+#: clutter/clutter-shader.c:503
msgid "Fragment shader"
msgstr "Cieniowanie fragmentów"
msgid "The type of shader used"
msgstr "Typ używanego cieniowania"
-#: clutter/clutter-stage.c:1249
+#: clutter/clutter-stage.c:1259
msgid "Fullscreen Set"
msgstr "Ustawienie pełnego ekranu"
-#: clutter/clutter-stage.c:1250
+#: clutter/clutter-stage.c:1260
msgid "Whether the main stage is fullscreen"
msgstr "Określa, czy główna scena jest na pełnym ekranie"
-#: clutter/clutter-stage.c:1266
+#: clutter/clutter-stage.c:1276
msgid "Offscreen"
msgstr "Poza ekranem"
-#: clutter/clutter-stage.c:1267
+#: clutter/clutter-stage.c:1277
msgid "Whether the main stage should be rendered offscreen"
msgstr "Określa, czy główna scena powinna być wyświetlana poza ekranem"
-#: clutter/clutter-stage.c:1279 clutter/clutter-text.c:2643
+#: clutter/clutter-stage.c:1289 clutter/clutter-text.c:2667
msgid "Cursor Visible"
msgstr "Widoczność kursora"
-#: clutter/clutter-stage.c:1280
+#: clutter/clutter-stage.c:1290
msgid "Whether the mouse pointer is visible on the main stage"
msgstr "Określa, czy kursor myszy jest widoczny na głównej scenie"
-#: clutter/clutter-stage.c:1294
+#: clutter/clutter-stage.c:1304
msgid "User Resizable"
msgstr "Użytkownik może zmieniać rozmiar"
-#: clutter/clutter-stage.c:1295
+#: clutter/clutter-stage.c:1305
msgid "Whether the stage is able to be resized via user interaction"
msgstr "Określa, czy można zmieniać rozmiar sceny przez działania użytkownika"
-#: clutter/clutter-stage.c:1308
+#: clutter/clutter-stage.c:1318
msgid "The color of the stage"
msgstr "Kolor sceny"
-#: clutter/clutter-stage.c:1322
+#: clutter/clutter-stage.c:1332
msgid "Perspective"
msgstr "Perspektywa"
-#: clutter/clutter-stage.c:1323
+#: clutter/clutter-stage.c:1333
msgid "Perspective projection parameters"
msgstr "Parametry projekcji perspektywy"
-#: clutter/clutter-stage.c:1338
+#: clutter/clutter-stage.c:1348
msgid "Title"
msgstr "Tytuł"
-#: clutter/clutter-stage.c:1339
+#: clutter/clutter-stage.c:1349
msgid "Stage Title"
msgstr "Tytuł sceny"
-#: clutter/clutter-stage.c:1354
+#: clutter/clutter-stage.c:1364
msgid "Use Fog"
msgstr "Użycie mgły"
-#: clutter/clutter-stage.c:1355
+#: clutter/clutter-stage.c:1365
msgid "Whether to enable depth cueing"
msgstr "Określa, czy włączyć wskazówki głębi"
-#: clutter/clutter-stage.c:1369
+#: clutter/clutter-stage.c:1379
msgid "Fog"
msgstr "Mgła"
-#: clutter/clutter-stage.c:1370
+#: clutter/clutter-stage.c:1380
msgid "Settings for the depth cueing"
msgstr "Ustawienia dla wskazówek głębi"
-#: clutter/clutter-stage.c:1386
+#: clutter/clutter-stage.c:1396
msgid "Use Alpha"
msgstr "Użycie alfy"
-#: clutter/clutter-stage.c:1387
+#: clutter/clutter-stage.c:1397
msgid "Whether to honour the alpha component of the stage color"
msgstr "Określa, czy uwzględniać składnik alfa koloru sceny"
-#: clutter/clutter-stage.c:1403
+#: clutter/clutter-stage.c:1413
msgid "Key Focus"
msgstr "Aktywny klawisz"
-#: clutter/clutter-stage.c:1404
+#: clutter/clutter-stage.c:1414
msgid "The currently key focused actor"
msgstr "Aktor obecnie posiadający aktywny klawisz"
-#: clutter/clutter-stage.c:1420
+#: clutter/clutter-stage.c:1430
msgid "No Clear Hint"
msgstr "Bez wskazówki czyszczenia"
-#: clutter/clutter-stage.c:1421
+#: clutter/clutter-stage.c:1431
msgid "Whether the stage should clear its contents"
msgstr "Określa, czy scena powinna czyścić swoją zawartość"
+#: clutter/clutter-stage.c:1444
+#, fuzzy
+msgid "Accept Focus"
+msgstr "Aktywny klawisz"
+
+#: clutter/clutter-stage.c:1445
+#, fuzzy
+msgid "Whether the stage should accept focus on show"
+msgstr "Określa, czy scena powinna czyścić swoją zawartość"
+
#: clutter/clutter-state.c:1268
msgid "State"
msgstr "Stan"
msgid "Default transition duration"
msgstr "Domyślny czas trwania przejścia"
-#: clutter/clutter-text.c:2530
+#: clutter/clutter-text.c:2554
msgid "Font Name"
msgstr "Nazwa czcionki"
-#: clutter/clutter-text.c:2531
+#: clutter/clutter-text.c:2555
msgid "The font to be used by the text"
msgstr "Czcionka używana przez tekst"
-#: clutter/clutter-text.c:2548
+#: clutter/clutter-text.c:2572
msgid "Font Description"
msgstr "Opis czcionki"
-#: clutter/clutter-text.c:2549
+#: clutter/clutter-text.c:2573
msgid "The font description to be used"
msgstr "Używany opis czcionki"
-#: clutter/clutter-text.c:2565
+#: clutter/clutter-text.c:2589
msgid "Text"
msgstr "Tekst"
-#: clutter/clutter-text.c:2566
+#: clutter/clutter-text.c:2590
msgid "The text to render"
msgstr "Tekst do wyświetlenia"
-#: clutter/clutter-text.c:2580
+#: clutter/clutter-text.c:2604
msgid "Font Color"
msgstr "Kolor czcionki"
-#: clutter/clutter-text.c:2581
+#: clutter/clutter-text.c:2605
msgid "Color of the font used by the text"
msgstr "Kolor czcionki używanej przez tekst"
-#: clutter/clutter-text.c:2595
+#: clutter/clutter-text.c:2619
msgid "Editable"
msgstr "Można modyfikować"
-#: clutter/clutter-text.c:2596
+#: clutter/clutter-text.c:2620
msgid "Whether the text is editable"
msgstr "Określa, czy tekst można modyfikować"
-#: clutter/clutter-text.c:2611
+#: clutter/clutter-text.c:2635
msgid "Selectable"
msgstr "Można skalować"
-#: clutter/clutter-text.c:2612
+#: clutter/clutter-text.c:2636
msgid "Whether the text is selectable"
msgstr "Określa, czy tekst można skalować"
-#: clutter/clutter-text.c:2626
+#: clutter/clutter-text.c:2650
msgid "Activatable"
msgstr "Można aktywować"
-#: clutter/clutter-text.c:2627
+#: clutter/clutter-text.c:2651
msgid "Whether pressing return causes the activate signal to be emitted"
msgstr ""
"Określa, czy wciśnięcie klawisza Return powoduje wysłanie sygnały aktywacji"
-#: clutter/clutter-text.c:2644
+#: clutter/clutter-text.c:2668
msgid "Whether the input cursor is visible"
msgstr "Określa, czy kursor wejścia jest widoczny"
-#: clutter/clutter-text.c:2658 clutter/clutter-text.c:2659
+#: clutter/clutter-text.c:2682 clutter/clutter-text.c:2683
msgid "Cursor Color"
msgstr "Kolor kursora"
-#: clutter/clutter-text.c:2673
+#: clutter/clutter-text.c:2697
msgid "Cursor Color Set"
msgstr "Ustawienie koloru kursora"
-#: clutter/clutter-text.c:2674
+#: clutter/clutter-text.c:2698
msgid "Whether the cursor color has been set"
msgstr "Określa, czy kolor kursora został ustawiony"
-#: clutter/clutter-text.c:2689
+#: clutter/clutter-text.c:2713
msgid "Cursor Size"
msgstr "Rozmiar kursora"
-#: clutter/clutter-text.c:2690
+#: clutter/clutter-text.c:2714
msgid "The width of the cursor, in pixels"
msgstr "Szerokość kursora w pikselach"
-#: clutter/clutter-text.c:2704
+#: clutter/clutter-text.c:2728
msgid "Cursor Position"
msgstr "Położenie kursora"
-#: clutter/clutter-text.c:2705
+#: clutter/clutter-text.c:2729
msgid "The cursor position"
msgstr "Położenie kursora"
-#: clutter/clutter-text.c:2720
+#: clutter/clutter-text.c:2744
msgid "Selection-bound"
msgstr "Powiązanie zaznaczenia"
-#: clutter/clutter-text.c:2721
+#: clutter/clutter-text.c:2745
msgid "The cursor position of the other end of the selection"
msgstr "Położenie kursora na drugim końcu zaznaczenia"
-#: clutter/clutter-text.c:2736 clutter/clutter-text.c:2737
+#: clutter/clutter-text.c:2760 clutter/clutter-text.c:2761
msgid "Selection Color"
msgstr "Kolor zaznaczenia"
-#: clutter/clutter-text.c:2751
+#: clutter/clutter-text.c:2775
msgid "Selection Color Set"
msgstr "Ustawienie koloru zaznaczenia"
-#: clutter/clutter-text.c:2752
+#: clutter/clutter-text.c:2776
msgid "Whether the selection color has been set"
msgstr "Określa, czy kolor zaznaczenia został ustawiony"
-#: clutter/clutter-text.c:2767
+#: clutter/clutter-text.c:2791
msgid "Attributes"
msgstr "Atrybuty"
-#: clutter/clutter-text.c:2768
+#: clutter/clutter-text.c:2792
msgid "A list of style attributes to apply to the contents of the actor"
msgstr "Lista atrybutów stylu do zastosowania do zawartości aktora"
-#: clutter/clutter-text.c:2790
+#: clutter/clutter-text.c:2814
msgid "Use markup"
msgstr "Użycie znaczników"
-#: clutter/clutter-text.c:2791
+#: clutter/clutter-text.c:2815
msgid "Whether or not the text includes Pango markup"
msgstr "Określa, czy tekst zawiera znaczniki biblioteki Pango"
-#: clutter/clutter-text.c:2807
+#: clutter/clutter-text.c:2831
msgid "Line wrap"
msgstr "Zawijanie wierszy"
-#: clutter/clutter-text.c:2808
+#: clutter/clutter-text.c:2832
msgid "If set, wrap the lines if the text becomes too wide"
msgstr "Jeśli ustawione, zawija wiersze, jeśli tekst staje się za szeroki"
-#: clutter/clutter-text.c:2823
+#: clutter/clutter-text.c:2847
msgid "Line wrap mode"
msgstr "Tryb zawijania wierszy"
-#: clutter/clutter-text.c:2824
+#: clutter/clutter-text.c:2848
msgid "Control how line-wrapping is done"
msgstr "Kontroluje, jak wykonywać zawijanie wierszy"
-#: clutter/clutter-text.c:2839
+#: clutter/clutter-text.c:2863
msgid "Ellipsize"
msgstr "Przycięcie"
-#: clutter/clutter-text.c:2840
+#: clutter/clutter-text.c:2864
msgid "The preferred place to ellipsize the string"
msgstr "Preferowane miejsce do przycięcia ciągu"
-#: clutter/clutter-text.c:2856
+#: clutter/clutter-text.c:2880
msgid "Line Alignment"
msgstr "Wyrównanie wiersza"
-#: clutter/clutter-text.c:2857
+#: clutter/clutter-text.c:2881
msgid "The preferred alignment for the string, for multi-line text"
msgstr "Preferowane wyrównanie ciągu dla tekstu wielowierszowego"
-#: clutter/clutter-text.c:2873
+#: clutter/clutter-text.c:2897
msgid "Justify"
msgstr "Justowanie"
-#: clutter/clutter-text.c:2874
+#: clutter/clutter-text.c:2898
msgid "Whether the text should be justified"
msgstr "Określa, czy tekst powinien być justowany"
-#: clutter/clutter-text.c:2889
+#: clutter/clutter-text.c:2913
msgid "Password Character"
msgstr "Znak hasła"
-#: clutter/clutter-text.c:2890
+#: clutter/clutter-text.c:2914
msgid "If non-zero, use this character to display the actor's contents"
msgstr ""
"Jeśli nie wynosi zero, używa tego znaku do wyświetlania zawartości aktora"
-#: clutter/clutter-text.c:2904
+#: clutter/clutter-text.c:2928
msgid "Max Length"
msgstr "Maksymalna długość"
-#: clutter/clutter-text.c:2905
+#: clutter/clutter-text.c:2929
msgid "Maximum length of the text inside the actor"
msgstr "Maksymalna długość tekstu w aktorze"
-#: clutter/clutter-text.c:2928
+#: clutter/clutter-text.c:2952
msgid "Single Line Mode"
msgstr "Tryb pojedynczego wiersza"
-#: clutter/clutter-text.c:2929
+#: clutter/clutter-text.c:2953
msgid "Whether the text should be a single line"
msgstr "Określa, czy tekst powinien być pojedynczym wierszem"
msgid "Shape actor with alpha channel when picking"
msgstr "Kształtowanie aktora za pomocą kanału alfa podczas wybierania"
-#: clutter/glx/clutter-backend-glx.c:128
+#: clutter/glx/clutter-backend-glx.c:131
msgid "VBlank method to be used (none, dri or glx)"
msgstr "Używana metoda VBlank (\"none\" (brak), \"dri\" lub \"glx\")"
-#: clutter/x11/clutter-backend-x11.c:364
+#: clutter/x11/clutter-backend-x11.c:473
msgid "X display to use"
msgstr "Używany ekran X"
-#: clutter/x11/clutter-backend-x11.c:370
+#: clutter/x11/clutter-backend-x11.c:479
msgid "X screen to use"
msgstr "Używany ekran X"
-#: clutter/x11/clutter-backend-x11.c:375
+#: clutter/x11/clutter-backend-x11.c:484
msgid "Make X calls synchronous"
msgstr "Synchroniczne wywołania X"
-#: clutter/x11/clutter-backend-x11.c:382
+#: clutter/x11/clutter-backend-x11.c:491
msgid "Enable XInput support"
msgstr "Włącza obsługę XInput"
"Project-Id-Version: clutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.clutter-project.org/enter_bug.cgi?"
"product=clutter\n"
-"POT-Creation-Date: 2010-12-17 15:51+0000\n"
+"POT-Creation-Date: 2011-02-07 15:50+0000\n"
"PO-Revision-Date: 2010-09-30 15:09+0800\n"
"Last-Translator: Aron Xu <happyaron.xu@gmail.com>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: clutter/clutter-actor.c:3480
+#: clutter/clutter-actor.c:3478
msgid "X coordinate"
msgstr "X 坐标"
-#: clutter/clutter-actor.c:3481
+#: clutter/clutter-actor.c:3479
msgid "X coordinate of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3496
+#: clutter/clutter-actor.c:3494
msgid "Y coordinate"
msgstr "Y 坐标"
-#: clutter/clutter-actor.c:3497
+#: clutter/clutter-actor.c:3495
msgid "Y coordinate of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3512 clutter/clutter-behaviour-ellipse.c:475
+#: clutter/clutter-actor.c:3510 clutter/clutter-behaviour-ellipse.c:474
msgid "Width"
msgstr "宽度"
-#: clutter/clutter-actor.c:3513
+#: clutter/clutter-actor.c:3511
msgid "Width of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3527 clutter/clutter-behaviour-ellipse.c:491
+#: clutter/clutter-actor.c:3525 clutter/clutter-behaviour-ellipse.c:490
msgid "Height"
msgstr "高度"
-#: clutter/clutter-actor.c:3528
+#: clutter/clutter-actor.c:3526
msgid "Height of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3546
+#: clutter/clutter-actor.c:3544
msgid "Fixed X"
msgstr "固定 X 坐标"
-#: clutter/clutter-actor.c:3547
+#: clutter/clutter-actor.c:3545
msgid "Forced X position of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3565
+#: clutter/clutter-actor.c:3563
msgid "Fixed Y"
msgstr "固定 Y 坐标"
-#: clutter/clutter-actor.c:3566
+#: clutter/clutter-actor.c:3564
msgid "Forced Y position of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3582
+#: clutter/clutter-actor.c:3580
msgid "Fixed position set"
msgstr ""
-#: clutter/clutter-actor.c:3583
+#: clutter/clutter-actor.c:3581
msgid "Whether to use fixed positioning for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3605
+#: clutter/clutter-actor.c:3603
msgid "Min Width"
msgstr "最小宽度"
-#: clutter/clutter-actor.c:3606
+#: clutter/clutter-actor.c:3604
msgid "Forced minimum width request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3625
+#: clutter/clutter-actor.c:3623
msgid "Min Height"
msgstr "最小高度"
-#: clutter/clutter-actor.c:3626
+#: clutter/clutter-actor.c:3624
msgid "Forced minimum height request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3645
+#: clutter/clutter-actor.c:3643
msgid "Natural Width"
msgstr ""
-#: clutter/clutter-actor.c:3646
+#: clutter/clutter-actor.c:3644
msgid "Forced natural width request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3665
+#: clutter/clutter-actor.c:3663
msgid "Natural Height"
msgstr ""
-#: clutter/clutter-actor.c:3666
+#: clutter/clutter-actor.c:3664
msgid "Forced natural height request for the actor"
msgstr ""
-#: clutter/clutter-actor.c:3682
+#: clutter/clutter-actor.c:3680
msgid "Minimum width set"
msgstr ""
-#: clutter/clutter-actor.c:3683
+#: clutter/clutter-actor.c:3681
msgid "Whether to use the min-width property"
msgstr ""
-#: clutter/clutter-actor.c:3698
+#: clutter/clutter-actor.c:3696
msgid "Minimum height set"
msgstr ""
-#: clutter/clutter-actor.c:3699
+#: clutter/clutter-actor.c:3697
msgid "Whether to use the min-height property"
msgstr ""
-#: clutter/clutter-actor.c:3714
+#: clutter/clutter-actor.c:3712
msgid "Natural width set"
msgstr ""
-#: clutter/clutter-actor.c:3715
+#: clutter/clutter-actor.c:3713
msgid "Whether to use the natural-width property"
msgstr ""
-#: clutter/clutter-actor.c:3732
+#: clutter/clutter-actor.c:3730
msgid "Natural height set"
msgstr ""
-#: clutter/clutter-actor.c:3733
+#: clutter/clutter-actor.c:3731
msgid "Whether to use the natural-height property"
msgstr ""
-#: clutter/clutter-actor.c:3752
+#: clutter/clutter-actor.c:3750
msgid "Allocation"
msgstr "分配"
-#: clutter/clutter-actor.c:3753
+#: clutter/clutter-actor.c:3751
msgid "The actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:3809
+#: clutter/clutter-actor.c:3807
msgid "Request Mode"
msgstr "请求模式"
-#: clutter/clutter-actor.c:3810
+#: clutter/clutter-actor.c:3808
msgid "The actor's request mode"
msgstr ""
-#: clutter/clutter-actor.c:3825
+#: clutter/clutter-actor.c:3823
msgid "Depth"
msgstr "色深"
-#: clutter/clutter-actor.c:3826
+#: clutter/clutter-actor.c:3824
msgid "Position on the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:3840
+#: clutter/clutter-actor.c:3838
msgid "Opacity"
msgstr "透明度"
-#: clutter/clutter-actor.c:3841
+#: clutter/clutter-actor.c:3839
msgid "Opacity of an actor"
msgstr ""
-#: clutter/clutter-actor.c:3856
+#: clutter/clutter-actor.c:3854
msgid "Visible"
msgstr "可见性"
-#: clutter/clutter-actor.c:3857
+#: clutter/clutter-actor.c:3855
msgid "Whether the actor is visible or not"
msgstr ""
-#: clutter/clutter-actor.c:3872
+#: clutter/clutter-actor.c:3870
msgid "Mapped"
msgstr ""
-#: clutter/clutter-actor.c:3873
+#: clutter/clutter-actor.c:3871
msgid "Whether the actor will be painted"
msgstr ""
-#: clutter/clutter-actor.c:3887
+#: clutter/clutter-actor.c:3885
msgid "Realized"
msgstr ""
-#: clutter/clutter-actor.c:3888
+#: clutter/clutter-actor.c:3886
msgid "Whether the actor has been realized"
msgstr ""
-#: clutter/clutter-actor.c:3904
+#: clutter/clutter-actor.c:3902
msgid "Reactive"
msgstr "重新激活"
-#: clutter/clutter-actor.c:3905
+#: clutter/clutter-actor.c:3903
msgid "Whether the actor is reactive to events"
msgstr ""
-#: clutter/clutter-actor.c:3917
+#: clutter/clutter-actor.c:3915
msgid "Has Clip"
msgstr ""
-#: clutter/clutter-actor.c:3918
+#: clutter/clutter-actor.c:3916
msgid "Whether the actor has a clip set"
msgstr ""
-#: clutter/clutter-actor.c:3933
+#: clutter/clutter-actor.c:3931
msgid "Clip"
msgstr ""
-#: clutter/clutter-actor.c:3934
+#: clutter/clutter-actor.c:3932
#, fuzzy
msgid "The clip region for the actor"
msgstr "文本方向"
-#: clutter/clutter-actor.c:3948 clutter/clutter-actor-meta.c:205
-#: clutter/clutter-binding-pool.c:320 clutter/clutter-input-device.c:151
+#: clutter/clutter-actor.c:3946 clutter/clutter-actor-meta.c:205
+#: clutter/clutter-binding-pool.c:319 clutter/clutter-input-device.c:235
msgid "Name"
msgstr "名称"
-#: clutter/clutter-actor.c:3949
+#: clutter/clutter-actor.c:3947
msgid "Name of the actor"
msgstr ""
-#: clutter/clutter-actor.c:3963
+#: clutter/clutter-actor.c:3961
msgid "Scale X"
msgstr "缩放 X 坐标"
-#: clutter/clutter-actor.c:3964
+#: clutter/clutter-actor.c:3962
msgid "Scale factor on the X axis"
msgstr ""
-#: clutter/clutter-actor.c:3979
+#: clutter/clutter-actor.c:3977
msgid "Scale Y"
msgstr "缩放 Y 坐标"
-#: clutter/clutter-actor.c:3980
+#: clutter/clutter-actor.c:3978
msgid "Scale factor on the Y axis"
msgstr ""
-#: clutter/clutter-actor.c:3995
+#: clutter/clutter-actor.c:3993
msgid "Scale Center X"
msgstr ""
-#: clutter/clutter-actor.c:3996
+#: clutter/clutter-actor.c:3994
msgid "Horizontal scale center"
msgstr ""
-#: clutter/clutter-actor.c:4011
+#: clutter/clutter-actor.c:4009
msgid "Scale Center Y"
msgstr ""
-#: clutter/clutter-actor.c:4012
+#: clutter/clutter-actor.c:4010
msgid "Vertical scale center"
msgstr ""
-#: clutter/clutter-actor.c:4027
+#: clutter/clutter-actor.c:4025
msgid "Scale Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4028
+#: clutter/clutter-actor.c:4026
msgid "The center of scaling"
msgstr ""
-#: clutter/clutter-actor.c:4045
+#: clutter/clutter-actor.c:4043
msgid "Rotation Angle X"
msgstr ""
-#: clutter/clutter-actor.c:4046
+#: clutter/clutter-actor.c:4044
msgid "The rotation angle on the X axis"
msgstr ""
-#: clutter/clutter-actor.c:4061
+#: clutter/clutter-actor.c:4059
msgid "Rotation Angle Y"
msgstr ""
-#: clutter/clutter-actor.c:4062
+#: clutter/clutter-actor.c:4060
msgid "The rotation angle on the Y axis"
msgstr ""
-#: clutter/clutter-actor.c:4077
+#: clutter/clutter-actor.c:4075
msgid "Rotation Angle Z"
msgstr ""
-#: clutter/clutter-actor.c:4078
+#: clutter/clutter-actor.c:4076
msgid "The rotation angle on the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:4093
+#: clutter/clutter-actor.c:4091
msgid "Rotation Center X"
msgstr ""
-#: clutter/clutter-actor.c:4094
+#: clutter/clutter-actor.c:4092
msgid "The rotation center on the X axis"
msgstr ""
-#: clutter/clutter-actor.c:4110
+#: clutter/clutter-actor.c:4108
msgid "Rotation Center Y"
msgstr ""
-#: clutter/clutter-actor.c:4111
+#: clutter/clutter-actor.c:4109
msgid "The rotation center on the Y axis"
msgstr ""
-#: clutter/clutter-actor.c:4127
+#: clutter/clutter-actor.c:4125
msgid "Rotation Center Z"
msgstr ""
-#: clutter/clutter-actor.c:4128
+#: clutter/clutter-actor.c:4126
msgid "The rotation center on the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:4144
+#: clutter/clutter-actor.c:4142
msgid "Rotation Center Z Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4145
+#: clutter/clutter-actor.c:4143
msgid "Center point for rotation around the Z axis"
msgstr ""
-#: clutter/clutter-actor.c:4163
+#: clutter/clutter-actor.c:4161
msgid "Anchor X"
msgstr ""
-#: clutter/clutter-actor.c:4164
+#: clutter/clutter-actor.c:4162
msgid "X coordinate of the anchor point"
msgstr ""
-#: clutter/clutter-actor.c:4180
+#: clutter/clutter-actor.c:4178
msgid "Anchor Y"
msgstr ""
-#: clutter/clutter-actor.c:4181
+#: clutter/clutter-actor.c:4179
msgid "Y coordinate of the anchor point"
msgstr ""
-#: clutter/clutter-actor.c:4196
+#: clutter/clutter-actor.c:4194
msgid "Anchor Gravity"
msgstr ""
-#: clutter/clutter-actor.c:4197
+#: clutter/clutter-actor.c:4195
msgid "The anchor point as a ClutterGravity"
msgstr ""
-#: clutter/clutter-actor.c:4216
+#: clutter/clutter-actor.c:4214
msgid "Show on set parent"
msgstr ""
-#: clutter/clutter-actor.c:4217
+#: clutter/clutter-actor.c:4215
msgid "Whether the actor is shown when parented"
msgstr ""
-#: clutter/clutter-actor.c:4237
+#: clutter/clutter-actor.c:4235
msgid "Clip to Allocation"
msgstr ""
-#: clutter/clutter-actor.c:4238
+#: clutter/clutter-actor.c:4236
msgid "Sets the clip region to track the actor's allocation"
msgstr ""
-#: clutter/clutter-actor.c:4248
+#: clutter/clutter-actor.c:4246
msgid "Text Direction"
msgstr "文本方向"
-#: clutter/clutter-actor.c:4249
+#: clutter/clutter-actor.c:4247
msgid "Direction of the text"
msgstr "文本的方向"
-#: clutter/clutter-actor.c:4267
+#: clutter/clutter-actor.c:4265
msgid "Has Pointer"
msgstr ""
-#: clutter/clutter-actor.c:4268
+#: clutter/clutter-actor.c:4266
msgid "Whether the actor contains the pointer of an input device"
msgstr ""
-#: clutter/clutter-actor.c:4285
+#: clutter/clutter-actor.c:4283
msgid "Actions"
msgstr "动作"
-#: clutter/clutter-actor.c:4286
+#: clutter/clutter-actor.c:4284
msgid "Adds an action to the actor"
msgstr ""
-#: clutter/clutter-actor.c:4300
+#: clutter/clutter-actor.c:4298
msgid "Constraints"
msgstr ""
-#: clutter/clutter-actor.c:4301
+#: clutter/clutter-actor.c:4299
msgid "Adds a constraint to the actor"
msgstr ""
msgid "The name of the meta"
msgstr ""
-#: clutter/clutter-actor-meta.c:219 clutter/clutter-shader.c:261
+#: clutter/clutter-actor-meta.c:219 clutter/clutter-input-device.c:314
+#: clutter/clutter-shader.c:295
msgid "Enabled"
msgstr "启用"
msgid "Whether the meta is enabled"
msgstr ""
-#: clutter/clutter-align-constraint.c:231
-#: clutter/clutter-bind-constraint.c:286 clutter/clutter-clone.c:322
+#: clutter/clutter-align-constraint.c:252
+#: clutter/clutter-bind-constraint.c:316 clutter/clutter-clone.c:322
msgid "Source"
msgstr "来源"
-#: clutter/clutter-align-constraint.c:232
+#: clutter/clutter-align-constraint.c:253
msgid "The source of the alignment"
msgstr ""
-#: clutter/clutter-align-constraint.c:245
+#: clutter/clutter-align-constraint.c:266
msgid "Align Axis"
msgstr ""
-#: clutter/clutter-align-constraint.c:246
+#: clutter/clutter-align-constraint.c:267
msgid "The axis to align the position to"
msgstr ""
-#: clutter/clutter-align-constraint.c:265
-#: clutter/clutter-desaturate-effect.c:309
+#: clutter/clutter-align-constraint.c:286
+#: clutter/clutter-desaturate-effect.c:307
msgid "Factor"
msgstr ""
-#: clutter/clutter-align-constraint.c:266
+#: clutter/clutter-align-constraint.c:287
msgid "The alignment factor, between 0.0 and 1.0"
msgstr ""
#: clutter/clutter-alpha.c:339 clutter/clutter-animation.c:523
-#: clutter/clutter-animator.c:1801
+#: clutter/clutter-animator.c:1802
msgid "Timeline"
msgstr "时间轴"
msgid "The mode of the animation"
msgstr "动画的模式"
-#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1785
+#: clutter/clutter-animation.c:494 clutter/clutter-animator.c:1786
#: clutter/clutter-media.c:194 clutter/clutter-state.c:1282
msgid "Duration"
msgstr "时长"
msgid "The timeline used by the animation"
msgstr "动画使用的时间轴"
-#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:299
+#: clutter/clutter-animation.c:537 clutter/clutter-behaviour.c:298
msgid "Alpha"
msgstr "Alpha"
msgid "The alpha used by the animation"
msgstr "动画使用的 alpha"
-#: clutter/clutter-animator.c:1786
+#: clutter/clutter-animator.c:1787
msgid "The duration of the animation"
msgstr "动画的时长"
-#: clutter/clutter-animator.c:1802
+#: clutter/clutter-animator.c:1803
msgid "The timeline of the animation"
msgstr "动画的时间轴"
-#: clutter/clutter-behaviour.c:300
+#: clutter/clutter-behaviour.c:299
msgid "Alpha Object to drive the behaviour"
msgstr ""
-#: clutter/clutter-behaviour-depth.c:175
+#: clutter/clutter-behaviour-depth.c:174
msgid "Start Depth"
msgstr "起始色深"
-#: clutter/clutter-behaviour-depth.c:176
+#: clutter/clutter-behaviour-depth.c:175
msgid "Initial depth to apply"
msgstr "应用的初始色深"
-#: clutter/clutter-behaviour-depth.c:191
+#: clutter/clutter-behaviour-depth.c:190
msgid "End Depth"
msgstr "终点色深"
-#: clutter/clutter-behaviour-depth.c:192
+#: clutter/clutter-behaviour-depth.c:191
msgid "Final depth to apply"
msgstr "应用的终点色深"
-#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-ellipse.c:394
msgid "Start Angle"
msgstr "起始角度"
-#: clutter/clutter-behaviour-ellipse.c:396
-#: clutter/clutter-behaviour-rotate.c:277
+#: clutter/clutter-behaviour-ellipse.c:395
+#: clutter/clutter-behaviour-rotate.c:276
msgid "Initial angle"
msgstr "初始的角度"
-#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-ellipse.c:410
msgid "End Angle"
msgstr "终点角度"
-#: clutter/clutter-behaviour-ellipse.c:412
-#: clutter/clutter-behaviour-rotate.c:295
+#: clutter/clutter-behaviour-ellipse.c:411
+#: clutter/clutter-behaviour-rotate.c:294
msgid "Final angle"
msgstr "终点的角度"
-#: clutter/clutter-behaviour-ellipse.c:427
+#: clutter/clutter-behaviour-ellipse.c:426
msgid "Angle x tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:428
+#: clutter/clutter-behaviour-ellipse.c:427
msgid "Tilt of the ellipse around x axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:443
+#: clutter/clutter-behaviour-ellipse.c:442
msgid "Angle y tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:444
+#: clutter/clutter-behaviour-ellipse.c:443
msgid "Tilt of the ellipse around y axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:459
+#: clutter/clutter-behaviour-ellipse.c:458
msgid "Angle z tilt"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:460
+#: clutter/clutter-behaviour-ellipse.c:459
msgid "Tilt of the ellipse around z axis"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:476
+#: clutter/clutter-behaviour-ellipse.c:475
msgid "Width of the ellipse"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:492
+#: clutter/clutter-behaviour-ellipse.c:491
msgid "Height of ellipse"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:507
+#: clutter/clutter-behaviour-ellipse.c:506
msgid "Center"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:508
+#: clutter/clutter-behaviour-ellipse.c:507
msgid "Center of ellipse"
msgstr ""
-#: clutter/clutter-behaviour-ellipse.c:522
-#: clutter/clutter-behaviour-rotate.c:330
+#: clutter/clutter-behaviour-ellipse.c:521
+#: clutter/clutter-behaviour-rotate.c:329
msgid "Direction"
msgstr "方向"
-#: clutter/clutter-behaviour-ellipse.c:523
-#: clutter/clutter-behaviour-rotate.c:331
+#: clutter/clutter-behaviour-ellipse.c:522
+#: clutter/clutter-behaviour-rotate.c:330
#, fuzzy
msgid "Direction of rotation"
msgstr "文本方向"
-#: clutter/clutter-behaviour-opacity.c:178
+#: clutter/clutter-behaviour-opacity.c:177
msgid "Opacity Start"
msgstr ""
-#: clutter/clutter-behaviour-opacity.c:179
+#: clutter/clutter-behaviour-opacity.c:178
msgid "Initial opacity level"
msgstr ""
-#: clutter/clutter-behaviour-opacity.c:196
+#: clutter/clutter-behaviour-opacity.c:195
msgid "Opacity End"
msgstr ""
-#: clutter/clutter-behaviour-opacity.c:197
+#: clutter/clutter-behaviour-opacity.c:196
msgid "Final opacity level"
msgstr ""
-#: clutter/clutter-behaviour-path.c:220
+#: clutter/clutter-behaviour-path.c:219
msgid "Path"
msgstr "路径"
-#: clutter/clutter-behaviour-path.c:221
+#: clutter/clutter-behaviour-path.c:220
msgid "The ClutterPath object representing the path to animate along"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:276
+#: clutter/clutter-behaviour-rotate.c:275
msgid "Angle Begin"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:294
+#: clutter/clutter-behaviour-rotate.c:293
msgid "Angle End"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:312
+#: clutter/clutter-behaviour-rotate.c:311
msgid "Axis"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:313
+#: clutter/clutter-behaviour-rotate.c:312
msgid "Axis of rotation"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:348
+#: clutter/clutter-behaviour-rotate.c:347
msgid "Center X"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:349
+#: clutter/clutter-behaviour-rotate.c:348
msgid "X coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:366
+#: clutter/clutter-behaviour-rotate.c:365
msgid "Center Y"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:367
+#: clutter/clutter-behaviour-rotate.c:366
msgid "Y coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:384
+#: clutter/clutter-behaviour-rotate.c:383
msgid "Center Z"
msgstr ""
-#: clutter/clutter-behaviour-rotate.c:385
+#: clutter/clutter-behaviour-rotate.c:384
msgid "Z coordinate of the center of rotation"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:219
+#: clutter/clutter-behaviour-scale.c:218
msgid "X Start Scale"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:220
+#: clutter/clutter-behaviour-scale.c:219
msgid "Initial scale on the X axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:238
+#: clutter/clutter-behaviour-scale.c:237
msgid "X End Scale"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:239
+#: clutter/clutter-behaviour-scale.c:238
msgid "Final scale on the X axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:257
+#: clutter/clutter-behaviour-scale.c:256
msgid "Y Start Scale"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:258
+#: clutter/clutter-behaviour-scale.c:257
msgid "Initial scale on the Y axis"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:276
+#: clutter/clutter-behaviour-scale.c:275
msgid "Y End Scale"
msgstr ""
-#: clutter/clutter-behaviour-scale.c:277
+#: clutter/clutter-behaviour-scale.c:276
msgid "Final scale on the Y axis"
msgstr ""
-#: clutter/clutter-bind-constraint.c:287
+#: clutter/clutter-bind-constraint.c:317
msgid "The source of the binding"
msgstr ""
-#: clutter/clutter-bind-constraint.c:300
+#: clutter/clutter-bind-constraint.c:330
msgid "Coordinate"
msgstr ""
-#: clutter/clutter-bind-constraint.c:301
+#: clutter/clutter-bind-constraint.c:331
msgid "The coordinate to bind"
msgstr ""
-#: clutter/clutter-bind-constraint.c:315
+#: clutter/clutter-bind-constraint.c:345
msgid "Offset"
msgstr "偏移"
-#: clutter/clutter-bind-constraint.c:316
+#: clutter/clutter-bind-constraint.c:346
msgid "The offset in pixels to apply to the binding"
msgstr ""
msgid "Default vertical alignment for the actors inside the layout manager"
msgstr ""
-#: clutter/clutter-binding-pool.c:321
+#: clutter/clutter-binding-pool.c:320
msgid "The unique name of the binding pool"
msgstr ""
msgstr ""
#: clutter/clutter-box.c:514 clutter/clutter-rectangle.c:258
-#: clutter/clutter-stage.c:1307
+#: clutter/clutter-stage.c:1317
msgid "Color"
msgstr "色彩"
msgid "The actor wrapped by this data"
msgstr ""
-#: clutter/clutter-click-action.c:283
+#: clutter/clutter-click-action.c:302
msgid "Pressed"
msgstr "按下时"
-#: clutter/clutter-click-action.c:284
+#: clutter/clutter-click-action.c:303
msgid "Whether the clickable should be in pressed state"
msgstr ""
-#: clutter/clutter-click-action.c:297
+#: clutter/clutter-click-action.c:316
msgid "Held"
msgstr "保持时"
-#: clutter/clutter-click-action.c:298
+#: clutter/clutter-click-action.c:317
msgid "Whether the clickable has a grab"
msgstr ""
msgid "Specifies the actor to be cloned"
msgstr ""
-#: clutter/clutter-colorize-effect.c:309
+#: clutter/clutter-colorize-effect.c:307
msgid "Tint"
msgstr ""
-#: clutter/clutter-colorize-effect.c:310
+#: clutter/clutter-colorize-effect.c:308
msgid "The tint to apply"
msgstr ""
msgid "The material to be used when painting the back of the actor"
msgstr ""
-#: clutter/clutter-desaturate-effect.c:310
+#: clutter/clutter-desaturate-effect.c:308
msgid "The desaturation factor"
msgstr ""
-#: clutter/clutter-device-manager.c:130
+#: clutter/clutter-device-manager.c:130 clutter/clutter-input-device.c:343
msgid "Backend"
msgstr "后端"
msgid "The ClutterBackend of the device manager"
msgstr ""
-#: clutter/clutter-drag-action.c:490
+#: clutter/clutter-drag-action.c:491
msgid "Horizontal Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:491
+#: clutter/clutter-drag-action.c:492
msgid "The horizontal amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:510
+#: clutter/clutter-drag-action.c:511
msgid "Vertical Drag Threshold"
msgstr ""
-#: clutter/clutter-drag-action.c:511
+#: clutter/clutter-drag-action.c:512
msgid "The vertical amount of pixels required to start dragging"
msgstr ""
-#: clutter/clutter-drag-action.c:532
+#: clutter/clutter-drag-action.c:533
msgid "Drag Handle"
msgstr ""
-#: clutter/clutter-drag-action.c:533
+#: clutter/clutter-drag-action.c:534
msgid "The actor that is being dragged"
msgstr ""
-#: clutter/clutter-drag-action.c:546
+#: clutter/clutter-drag-action.c:547
msgid "Drag Axis"
msgstr ""
-#: clutter/clutter-drag-action.c:547
+#: clutter/clutter-drag-action.c:548
msgid "Constraints the dragging to an axis"
msgstr ""
msgid "Maximum height for each row"
msgstr "每行的最大高度"
-#: clutter/clutter-input-device.c:134
+#: clutter/clutter-input-device.c:219
msgid "Id"
msgstr "ID"
-#: clutter/clutter-input-device.c:135
+#: clutter/clutter-input-device.c:220
msgid "Unique identifier of the device"
msgstr "设备识别符"
-#: clutter/clutter-input-device.c:152
+#: clutter/clutter-input-device.c:236
msgid "The name of the device"
msgstr "设备名称"
-#: clutter/clutter-input-device.c:167
+#: clutter/clutter-input-device.c:250
msgid "Device Type"
msgstr "设备类型"
-#: clutter/clutter-input-device.c:168
+#: clutter/clutter-input-device.c:251
msgid "The type of the device"
msgstr "设备的类型"
+#: clutter/clutter-input-device.c:266
+#, fuzzy
+msgid "Device Manager"
+msgstr "管理器"
+
+#: clutter/clutter-input-device.c:267
+msgid "The device manager instance"
+msgstr ""
+
+#: clutter/clutter-input-device.c:280
+#, fuzzy
+msgid "Device Mode"
+msgstr "设备类型"
+
+#: clutter/clutter-input-device.c:281
+#, fuzzy
+msgid "The mode of the device"
+msgstr "设备名称"
+
+#: clutter/clutter-input-device.c:295
+#, fuzzy
+msgid "Has Cursor"
+msgstr "带有边界"
+
+#: clutter/clutter-input-device.c:296
+msgid "Whether the device has a cursor"
+msgstr ""
+
+#: clutter/clutter-input-device.c:315
+#, fuzzy
+msgid "Whether the device is enabled"
+msgstr "文本是否可以编辑"
+
+#: clutter/clutter-input-device.c:328
+msgid "Number of Axes"
+msgstr ""
+
+#: clutter/clutter-input-device.c:329
+#, fuzzy
+msgid "The number of axes on the device"
+msgstr "设备名称"
+
+#: clutter/clutter-input-device.c:344
+msgid "The backend instance"
+msgstr ""
+
#: clutter/clutter-interval.c:397
msgid "Value Type"
msgstr "值类型"
msgid "The manager that created this data"
msgstr "创建此数据的管理器"
-#: clutter/clutter-main.c:756
+#: clutter/clutter-main.c:753
msgid "default:LTR"
msgstr "default:LTR"
-#: clutter/clutter-main.c:1560
+#: clutter/clutter-main.c:1557
msgid "Show frames per second"
msgstr "显示帧速率"
-#: clutter/clutter-main.c:1562
+#: clutter/clutter-main.c:1559
msgid "Default frame rate"
msgstr "默认帧率"
-#: clutter/clutter-main.c:1564
+#: clutter/clutter-main.c:1561
msgid "Make all warnings fatal"
msgstr "视所有警告为致命错误"
-#: clutter/clutter-main.c:1567
+#: clutter/clutter-main.c:1564
msgid "Direction for the text"
msgstr "文本方向"
-#: clutter/clutter-main.c:1570
+#: clutter/clutter-main.c:1567
msgid "Disable mipmapping on text"
msgstr "在文本上禁用 MIP 映射"
-#: clutter/clutter-main.c:1573
+#: clutter/clutter-main.c:1570
msgid "Use 'fuzzy' picking"
msgstr "使用模糊选取"
-#: clutter/clutter-main.c:1576
+#: clutter/clutter-main.c:1573
msgid "Clutter debugging flags to set"
msgstr "要设置的 Clutter 调试标志"
-#: clutter/clutter-main.c:1578
+#: clutter/clutter-main.c:1575
msgid "Clutter debugging flags to unset"
msgstr "要取消设置的 Clutter 调试标志"
-#: clutter/clutter-main.c:1582
+#: clutter/clutter-main.c:1579
msgid "Clutter profiling flags to set"
msgstr "要设置的 Clutter 性能分析标志"
-#: clutter/clutter-main.c:1584
+#: clutter/clutter-main.c:1581
msgid "Clutter profiling flags to unset"
msgstr "要取消设置的 Clutter 性能分析标志"
-#: clutter/clutter-main.c:1587
+#: clutter/clutter-main.c:1584
msgid "Enable accessibility"
msgstr "启用辅助功能"
-#: clutter/clutter-main.c:1774
+#: clutter/clutter-main.c:1771
msgid "Clutter Options"
msgstr "Clutter 选项"
-#: clutter/clutter-main.c:1775
+#: clutter/clutter-main.c:1772
msgid "Show Clutter Options"
msgstr "显示 Clutter 选项"
msgid "The path of the currently parsed file"
msgstr ""
-#: clutter/clutter-shader.c:215
+#: clutter/clutter-shader.c:249
#, fuzzy
msgid "Vertex Source"
msgstr "顶点着色引擎"
-#: clutter/clutter-shader.c:216
+#: clutter/clutter-shader.c:250
#, fuzzy
msgid "Source of vertex shader"
msgstr "顶点着色引擎"
-#: clutter/clutter-shader.c:230
+#: clutter/clutter-shader.c:264
#, fuzzy
msgid "Fragment Source"
msgstr "片段着色引擎"
-#: clutter/clutter-shader.c:231
+#: clutter/clutter-shader.c:265
#, fuzzy
msgid "Source of fragment shader"
msgstr "片段着色引擎"
-#: clutter/clutter-shader.c:246
+#: clutter/clutter-shader.c:280
msgid "Compiled"
msgstr ""
-#: clutter/clutter-shader.c:247
+#: clutter/clutter-shader.c:281
msgid "Whether the shader is compiled and linked"
msgstr ""
-#: clutter/clutter-shader.c:262
+#: clutter/clutter-shader.c:296
msgid "Whether the shader is enabled"
msgstr ""
-#: clutter/clutter-shader.c:467
+#: clutter/clutter-shader.c:501
#, c-format
msgid "%s compilation failed: %s"
msgstr "%s 编译失败:%s"
-#: clutter/clutter-shader.c:468
+#: clutter/clutter-shader.c:502
msgid "Vertex shader"
msgstr "顶点着色引擎"
-#: clutter/clutter-shader.c:469
+#: clutter/clutter-shader.c:503
msgid "Fragment shader"
msgstr "片段着色引擎"
msgid "The type of shader used"
msgstr "使用的着色引擎类型"
-#: clutter/clutter-stage.c:1249
+#: clutter/clutter-stage.c:1259
msgid "Fullscreen Set"
msgstr ""
-#: clutter/clutter-stage.c:1250
+#: clutter/clutter-stage.c:1260
msgid "Whether the main stage is fullscreen"
msgstr ""
-#: clutter/clutter-stage.c:1266
+#: clutter/clutter-stage.c:1276
msgid "Offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1267
+#: clutter/clutter-stage.c:1277
msgid "Whether the main stage should be rendered offscreen"
msgstr ""
-#: clutter/clutter-stage.c:1279 clutter/clutter-text.c:2643
+#: clutter/clutter-stage.c:1289 clutter/clutter-text.c:2667
msgid "Cursor Visible"
msgstr ""
-#: clutter/clutter-stage.c:1280
+#: clutter/clutter-stage.c:1290
msgid "Whether the mouse pointer is visible on the main stage"
msgstr ""
-#: clutter/clutter-stage.c:1294
+#: clutter/clutter-stage.c:1304
msgid "User Resizable"
msgstr "用户可改变大小"
-#: clutter/clutter-stage.c:1295
+#: clutter/clutter-stage.c:1305
msgid "Whether the stage is able to be resized via user interaction"
msgstr ""
-#: clutter/clutter-stage.c:1308
+#: clutter/clutter-stage.c:1318
msgid "The color of the stage"
msgstr ""
-#: clutter/clutter-stage.c:1322
+#: clutter/clutter-stage.c:1332
msgid "Perspective"
msgstr ""
-#: clutter/clutter-stage.c:1323
+#: clutter/clutter-stage.c:1333
msgid "Perspective projection parameters"
msgstr ""
-#: clutter/clutter-stage.c:1338
+#: clutter/clutter-stage.c:1348
msgid "Title"
msgstr "标题"
-#: clutter/clutter-stage.c:1339
+#: clutter/clutter-stage.c:1349
msgid "Stage Title"
msgstr ""
-#: clutter/clutter-stage.c:1354
+#: clutter/clutter-stage.c:1364
msgid "Use Fog"
msgstr ""
-#: clutter/clutter-stage.c:1355
+#: clutter/clutter-stage.c:1365
msgid "Whether to enable depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1369
+#: clutter/clutter-stage.c:1379
msgid "Fog"
msgstr ""
-#: clutter/clutter-stage.c:1370
+#: clutter/clutter-stage.c:1380
msgid "Settings for the depth cueing"
msgstr ""
-#: clutter/clutter-stage.c:1386
+#: clutter/clutter-stage.c:1396
msgid "Use Alpha"
msgstr "使用 Alpha"
-#: clutter/clutter-stage.c:1387
+#: clutter/clutter-stage.c:1397
msgid "Whether to honour the alpha component of the stage color"
msgstr ""
-#: clutter/clutter-stage.c:1403
+#: clutter/clutter-stage.c:1413
msgid "Key Focus"
msgstr ""
-#: clutter/clutter-stage.c:1404
+#: clutter/clutter-stage.c:1414
msgid "The currently key focused actor"
msgstr ""
-#: clutter/clutter-stage.c:1420
+#: clutter/clutter-stage.c:1430
msgid "No Clear Hint"
msgstr ""
-#: clutter/clutter-stage.c:1421
+#: clutter/clutter-stage.c:1431
msgid "Whether the stage should clear its contents"
msgstr ""
+#: clutter/clutter-stage.c:1444
+msgid "Accept Focus"
+msgstr ""
+
+#: clutter/clutter-stage.c:1445
+#, fuzzy
+msgid "Whether the stage should accept focus on show"
+msgstr "文本是否只应使用一行"
+
#: clutter/clutter-state.c:1268
msgid "State"
msgstr ""
msgid "Default transition duration"
msgstr "默认帧率"
-#: clutter/clutter-text.c:2530
+#: clutter/clutter-text.c:2554
msgid "Font Name"
msgstr "字体名称"
-#: clutter/clutter-text.c:2531
+#: clutter/clutter-text.c:2555
msgid "The font to be used by the text"
msgstr "文本使用的字体"
-#: clutter/clutter-text.c:2548
+#: clutter/clutter-text.c:2572
msgid "Font Description"
msgstr "字体描述"
-#: clutter/clutter-text.c:2549
+#: clutter/clutter-text.c:2573
msgid "The font description to be used"
msgstr "使用的字体描述"
-#: clutter/clutter-text.c:2565
+#: clutter/clutter-text.c:2589
msgid "Text"
msgstr "文本"
-#: clutter/clutter-text.c:2566
+#: clutter/clutter-text.c:2590
msgid "The text to render"
msgstr "要渲染的文本"
-#: clutter/clutter-text.c:2580
+#: clutter/clutter-text.c:2604
msgid "Font Color"
msgstr "字体颜色"
-#: clutter/clutter-text.c:2581
+#: clutter/clutter-text.c:2605
msgid "Color of the font used by the text"
msgstr "文本字体使用的颜色"
-#: clutter/clutter-text.c:2595
+#: clutter/clutter-text.c:2619
msgid "Editable"
msgstr "可编辑"
-#: clutter/clutter-text.c:2596
+#: clutter/clutter-text.c:2620
msgid "Whether the text is editable"
msgstr "文本是否可以编辑"
-#: clutter/clutter-text.c:2611
+#: clutter/clutter-text.c:2635
msgid "Selectable"
msgstr "可选择"
-#: clutter/clutter-text.c:2612
+#: clutter/clutter-text.c:2636
msgid "Whether the text is selectable"
msgstr "文本是否可以选择"
-#: clutter/clutter-text.c:2626
+#: clutter/clutter-text.c:2650
msgid "Activatable"
msgstr "可激活"
-#: clutter/clutter-text.c:2627
+#: clutter/clutter-text.c:2651
msgid "Whether pressing return causes the activate signal to be emitted"
msgstr ""
-#: clutter/clutter-text.c:2644
+#: clutter/clutter-text.c:2668
msgid "Whether the input cursor is visible"
msgstr ""
-#: clutter/clutter-text.c:2658 clutter/clutter-text.c:2659
+#: clutter/clutter-text.c:2682 clutter/clutter-text.c:2683
msgid "Cursor Color"
msgstr "指针颜色"
-#: clutter/clutter-text.c:2673
+#: clutter/clutter-text.c:2697
msgid "Cursor Color Set"
msgstr ""
-#: clutter/clutter-text.c:2674
+#: clutter/clutter-text.c:2698
msgid "Whether the cursor color has been set"
msgstr ""
-#: clutter/clutter-text.c:2689
+#: clutter/clutter-text.c:2713
msgid "Cursor Size"
msgstr "指针大小"
-#: clutter/clutter-text.c:2690
+#: clutter/clutter-text.c:2714
msgid "The width of the cursor, in pixels"
msgstr "指针的宽度,以像素计"
-#: clutter/clutter-text.c:2704
+#: clutter/clutter-text.c:2728
#, fuzzy
msgid "Cursor Position"
msgstr "指针位置"
-#: clutter/clutter-text.c:2705
+#: clutter/clutter-text.c:2729
msgid "The cursor position"
msgstr "指针位置"
-#: clutter/clutter-text.c:2720
+#: clutter/clutter-text.c:2744
msgid "Selection-bound"
msgstr "选区边界"
-#: clutter/clutter-text.c:2721
+#: clutter/clutter-text.c:2745
msgid "The cursor position of the other end of the selection"
msgstr ""
-#: clutter/clutter-text.c:2736 clutter/clutter-text.c:2737
+#: clutter/clutter-text.c:2760 clutter/clutter-text.c:2761
msgid "Selection Color"
msgstr "选区颜色"
-#: clutter/clutter-text.c:2751
+#: clutter/clutter-text.c:2775
msgid "Selection Color Set"
msgstr ""
-#: clutter/clutter-text.c:2752
+#: clutter/clutter-text.c:2776
msgid "Whether the selection color has been set"
msgstr ""
-#: clutter/clutter-text.c:2767
+#: clutter/clutter-text.c:2791
msgid "Attributes"
msgstr "属性"
-#: clutter/clutter-text.c:2768
+#: clutter/clutter-text.c:2792
msgid "A list of style attributes to apply to the contents of the actor"
msgstr ""
-#: clutter/clutter-text.c:2790
+#: clutter/clutter-text.c:2814
msgid "Use markup"
msgstr "使用标记"
-#: clutter/clutter-text.c:2791
+#: clutter/clutter-text.c:2815
msgid "Whether or not the text includes Pango markup"
msgstr ""
-#: clutter/clutter-text.c:2807
+#: clutter/clutter-text.c:2831
msgid "Line wrap"
msgstr "换行"
-#: clutter/clutter-text.c:2808
+#: clutter/clutter-text.c:2832
msgid "If set, wrap the lines if the text becomes too wide"
msgstr ""
-#: clutter/clutter-text.c:2823
+#: clutter/clutter-text.c:2847
msgid "Line wrap mode"
msgstr "换行模式"
-#: clutter/clutter-text.c:2824
+#: clutter/clutter-text.c:2848
msgid "Control how line-wrapping is done"
msgstr "控制换行行为"
-#: clutter/clutter-text.c:2839
+#: clutter/clutter-text.c:2863
msgid "Ellipsize"
msgstr ""
-#: clutter/clutter-text.c:2840
+#: clutter/clutter-text.c:2864
msgid "The preferred place to ellipsize the string"
msgstr ""
-#: clutter/clutter-text.c:2856
+#: clutter/clutter-text.c:2880
msgid "Line Alignment"
msgstr ""
-#: clutter/clutter-text.c:2857
+#: clutter/clutter-text.c:2881
msgid "The preferred alignment for the string, for multi-line text"
msgstr ""
-#: clutter/clutter-text.c:2873
+#: clutter/clutter-text.c:2897
msgid "Justify"
msgstr ""
-#: clutter/clutter-text.c:2874
+#: clutter/clutter-text.c:2898
msgid "Whether the text should be justified"
msgstr ""
-#: clutter/clutter-text.c:2889
+#: clutter/clutter-text.c:2913
msgid "Password Character"
msgstr "密码字符"
-#: clutter/clutter-text.c:2890
+#: clutter/clutter-text.c:2914
msgid "If non-zero, use this character to display the actor's contents"
msgstr ""
-#: clutter/clutter-text.c:2904
+#: clutter/clutter-text.c:2928
msgid "Max Length"
msgstr "最大长度"
-#: clutter/clutter-text.c:2905
+#: clutter/clutter-text.c:2929
msgid "Maximum length of the text inside the actor"
msgstr ""
-#: clutter/clutter-text.c:2928
+#: clutter/clutter-text.c:2952
msgid "Single Line Mode"
msgstr "单行模式"
-#: clutter/clutter-text.c:2929
+#: clutter/clutter-text.c:2953
msgid "Whether the text should be a single line"
msgstr "文本是否只应使用一行"
msgid "Shape actor with alpha channel when picking"
msgstr ""
-#: clutter/glx/clutter-backend-glx.c:128
+#: clutter/glx/clutter-backend-glx.c:131
msgid "VBlank method to be used (none, dri or glx)"
msgstr "要使用的 VBlank 方式(none、dir 或 glx)"
-#: clutter/x11/clutter-backend-x11.c:364
+#: clutter/x11/clutter-backend-x11.c:473
msgid "X display to use"
msgstr "要使用的 X 显示"
-#: clutter/x11/clutter-backend-x11.c:370
+#: clutter/x11/clutter-backend-x11.c:479
msgid "X screen to use"
msgstr "要使用的 X 屏幕"
-#: clutter/x11/clutter-backend-x11.c:375
+#: clutter/x11/clutter-backend-x11.c:484
msgid "Make X calls synchronous"
msgstr "使 X 调用同步"
-#: clutter/x11/clutter-backend-x11.c:382
+#: clutter/x11/clutter-backend-x11.c:491
msgid "Enable XInput support"
msgstr "启用 XInput 支持"
test-cogl-depth-test.c \
test-cogl-fixed.c \
test-cogl-materials.c \
+ test-cogl-pipeline-user-matrix.c \
test-cogl-viewport.c \
test-cogl-multitexture.c \
test-cogl-npot-texture.c \
--- /dev/null
+#include <clutter/clutter.h>
+#include <string.h>
+
+#include "test-conform-common.h"
+
+static const ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff };
+
+static void
+paint_cb (ClutterActor *stage)
+{
+ /* This texture is painted mirrored around the x-axis */
+ guint8 data0[] = {
+ 0xff, 0x00, 0x00, /* red -> becomes bottom left */
+ 0x00, 0xff, 0x00, /* green -> becomes bottom right */
+ 0x00, 0x00, 0xff, /* blue -> becomes top left */
+ 0xff, 0x00, 0xff /* magenta -> becomes top right */
+ };
+ /* This texture is painted mirrored about the y-axis */
+ guint8 data1[] = {
+ 0x00, 0xff, 0x00, /* green -> becomes top right */
+ 0xff, 0xff, 0x00, /* yellow -> becomes top left */
+ 0xff, 0x00, 0xff, /* magenta -> becomes bottom right */
+ 0x00, 0xff, 0xff /* cyan -> becomes bottom left */
+ };
+ CoglHandle tex0, tex1;
+ CoglPipeline *pipeline;
+ CoglMatrix matrix;
+ int width, height;
+ guint8 *pixels, *p;
+
+ width = clutter_actor_get_width (stage);
+ height = clutter_actor_get_height (stage);
+
+ tex0 = cogl_texture_new_from_data (2, 2,
+ COGL_TEXTURE_NO_ATLAS,
+ COGL_PIXEL_FORMAT_RGB_888,
+ COGL_PIXEL_FORMAT_ANY,
+ 6,
+ data0);
+ tex1 = cogl_texture_new_from_data (2, 2,
+ COGL_TEXTURE_NO_ATLAS,
+ COGL_PIXEL_FORMAT_RGB_888,
+ COGL_PIXEL_FORMAT_ANY,
+ 6,
+ data1);
+
+ pipeline = cogl_pipeline_new ();
+
+ /* Set the two textures as layers */
+ cogl_pipeline_set_layer_texture (pipeline, 0, tex0);
+ cogl_pipeline_set_layer_filters (pipeline, 0,
+ COGL_PIPELINE_FILTER_NEAREST,
+ COGL_PIPELINE_FILTER_NEAREST);
+ cogl_pipeline_set_layer_texture (pipeline, 1, tex1);
+ cogl_pipeline_set_layer_filters (pipeline, 1,
+ COGL_PIPELINE_FILTER_NEAREST,
+ COGL_PIPELINE_FILTER_NEAREST);
+
+ /* Set a combine mode so that the two textures get added together */
+ cogl_pipeline_set_layer_combine (pipeline, 1,
+ "RGBA=ADD(PREVIOUS, TEXTURE)",
+ NULL);
+
+ /* Set a matrix on the first layer so that it will mirror about the y-axis */
+ cogl_matrix_init_identity (&matrix);
+ cogl_matrix_translate (&matrix, 0.0f, 1.0f, 0.0f);
+ cogl_matrix_scale (&matrix, 1.0f, -1.0f, 1.0f);
+ cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
+
+ /* Set a matrix on the second layer so that it will mirror about the x-axis */
+ cogl_matrix_init_identity (&matrix);
+ cogl_matrix_translate (&matrix, 1.0f, 0.0f, 0.0f);
+ cogl_matrix_scale (&matrix, -1.0f, 1.0f, 1.0f);
+ cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix);
+
+ cogl_set_source (pipeline);
+ cogl_rectangle (0, 0, width, height);
+
+ cogl_handle_unref (tex1);
+ cogl_handle_unref (tex0);
+ cogl_object_unref (pipeline);
+
+ /* The textures are setup so that when added together with the
+ correct matrices then all of the pixels should be white. We can
+ verify this by reading back the entire stage */
+ pixels = g_malloc (width * height * 4);
+
+ cogl_read_pixels (0, 0, width, height,
+ COGL_READ_PIXELS_COLOR_BUFFER,
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+ pixels);
+
+ for (p = pixels + width * height * 4; p > pixels;)
+ {
+ p -= 4;
+ g_assert_cmpint (p[0], ==, 0xff);
+ g_assert_cmpint (p[1], ==, 0xff);
+ g_assert_cmpint (p[2], ==, 0xff);
+ }
+
+ g_free (pixels);
+
+ clutter_main_quit ();
+}
+
+static gboolean
+queue_redraw (gpointer stage)
+{
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
+
+ return TRUE;
+}
+
+void
+test_cogl_pipeline_user_matrix (TestConformSimpleFixture *fixture,
+ gconstpointer data)
+{
+ ClutterActor *stage;
+ guint idle_source;
+ guint paint_handler;
+
+ stage = clutter_stage_get_default ();
+
+ clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
+
+ /* We force continuous redrawing of the stage, since we need to skip
+ * the first few frames, and we wont be doing anything else that
+ * will trigger redrawing. */
+ idle_source = g_idle_add (queue_redraw, stage);
+
+ paint_handler = g_signal_connect_after (stage, "paint",
+ G_CALLBACK (paint_cb),
+ NULL);
+
+ clutter_actor_show (stage);
+
+ clutter_main ();
+
+ g_source_remove (idle_source);
+ g_signal_handler_disconnect (stage, paint_handler);
+
+ if (g_test_verbose ())
+ g_print ("OK\n");
+}
static CoglPrimitive *
test_prim_p2 (ClutterColor *expected_color)
{
- static const CoglP2Vertex verts[] =
+ static const CoglVertexP2 verts[] =
{ { 0, 0 }, { 0, 10 }, { 10, 0 } };
return cogl_primitive_new_p2 (COGL_VERTICES_MODE_TRIANGLES,
static CoglPrimitive *
test_prim_p3 (ClutterColor *expected_color)
{
- static const CoglP3Vertex verts[] =
+ static const CoglVertexP3 verts[] =
{ { 0, 0, 0 }, { 0, 10, 0 }, { 10, 0, 0 } };
return cogl_primitive_new_p3 (COGL_VERTICES_MODE_TRIANGLES,
static CoglPrimitive *
test_prim_p2c4 (ClutterColor *expected_color)
{
- static const CoglP2C4Vertex verts[] =
+ static const CoglVertexP2C4 verts[] =
{ { 0, 0, 255, 255, 0, 255 },
{ 0, 10, 255, 255, 0, 255 },
{ 10, 0, 255, 255, 0, 255 } };
static CoglPrimitive *
test_prim_p3c4 (ClutterColor *expected_color)
{
- static const CoglP3C4Vertex verts[] =
+ static const CoglVertexP3C4 verts[] =
{ { 0, 0, 0, 255, 255, 0, 255 },
{ 0, 10, 0, 255, 255, 0, 255 },
{ 10, 0, 0, 255, 255, 0, 255 } };
static CoglPrimitive *
test_prim_p2t2 (ClutterColor *expected_color)
{
- static const CoglP2T2Vertex verts[] =
+ static const CoglVertexP2T2 verts[] =
{ { 0, 0, 1, 0 },
{ 0, 10, 1, 0 },
{ 10, 0, 1, 0 } };
static CoglPrimitive *
test_prim_p3t2 (ClutterColor *expected_color)
{
- static const CoglP3T2Vertex verts[] =
+ static const CoglVertexP3T2 verts[] =
{ { 0, 0, 0, 1, 0 },
{ 0, 10, 0, 1, 0 },
{ 10, 0, 0, 1, 0 } };
static CoglPrimitive *
test_prim_p2t2c4 (ClutterColor *expected_color)
{
- static const CoglP2T2C4Vertex verts[] =
+ static const CoglVertexP2T2C4 verts[] =
{ { 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff },
{ 0, 10, 1, 0, 0xff, 0xff, 0xf0, 0xff },
{ 10, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff } };
static CoglPrimitive *
test_prim_p3t2c4 (ClutterColor *expected_color)
{
- static const CoglP3T2C4Vertex verts[] =
+ static const CoglVertexP3T2C4 verts[] =
{ { 0, 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff },
{ 0, 10, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff },
{ 10, 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff } };
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_fixed);
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_backface_culling);
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_materials);
+ TEST_CONFORM_SIMPLE ("/cogl", test_cogl_pipeline_user_matrix);
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_blend_strings);
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_premult);
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_readpixels);
gchar *test_file;
const gchar *name;
GType type;
+ ClutterModelIter *iter;
+ GValue value = { 0, };
test_file = clutter_test_get_data_file ("test-script-model.json");
clutter_script_load_from_file (script, test_file, &error);
g_assert (strcmp (name, "actor-column") == 0);
g_assert (type == CLUTTER_TYPE_RECTANGLE);
+
+ g_assert (clutter_model_get_n_rows (CLUTTER_MODEL (model)) == 3);
+
+ iter = clutter_model_get_iter_at_row (CLUTTER_MODEL (model), 0);
+ clutter_model_iter_get_value (iter, 0, &value);
+ g_assert (G_VALUE_HOLDS_STRING (&value));
+ g_assert (strcmp (g_value_get_string (&value), "text-row-1") == 0);
+ g_value_unset (&value);
+
+ clutter_model_iter_get_value (iter, 1, &value);
+ g_assert (G_VALUE_HOLDS_INT (&value));
+ g_assert (g_value_get_int (&value) == 1);
+ g_value_unset (&value);
+
+ clutter_model_iter_get_value (iter, 2, &value);
+ g_assert (G_VALUE_HOLDS_OBJECT (&value));
+ g_assert (g_value_get_object (&value) == NULL);
+ g_value_unset (&value);
+
+ iter = clutter_model_iter_next (iter);
+ clutter_model_iter_get_value (iter, 2, &value);
+ g_assert (G_VALUE_HOLDS_OBJECT (&value));
+ g_assert (CLUTTER_IS_RECTANGLE (g_value_get_object (&value)));
+ g_value_unset (&value);
+
+ iter = clutter_model_iter_next (iter);
+ clutter_model_iter_get_value (iter, 2, &value);
+ g_assert (G_VALUE_HOLDS_OBJECT (&value));
+ g_assert (CLUTTER_IS_RECTANGLE (g_value_get_object (&value)));
+ g_assert (strcmp (clutter_actor_get_name (g_value_get_object (&value)),
+ "actor-row-3") == 0);
+ g_value_unset (&value);
+ g_object_unref (iter);
}
last_point = path_start;
/* Cairo always adds a move to after every close so we need
- to insert one here */
- memmove (data->nodes + i + 2, data->nodes + i + 1,
- (data->n_nodes - i - 1) * sizeof (ClutterPathNode));
- data->nodes[i + 1].type = CLUTTER_PATH_MOVE_TO;
- data->nodes[i + 1].points[0] = last_point;
- data->n_nodes++;
+ to insert one here. Since Cairo commit 166453c1abf2 it
+ doesn't seem to do this anymore so will assume that if
+ Cairo's minor version is >= 11 then it includes that
+ commit */
+ if (cairo_version () < CAIRO_VERSION_ENCODE (1, 11, 0))
+ {
+ memmove (data->nodes + i + 2, data->nodes + i + 1,
+ (data->n_nodes - i - 1) * sizeof (ClutterPathNode));
+ data->nodes[i + 1].type = CLUTTER_PATH_MOVE_TO;
+ data->nodes[i + 1].points[0] = last_point;
+ data->n_nodes++;
+ }
break;
}
}
static void
new_frame_cb (ClutterTimeline *timeline,
- gint frame_num,
+ gint elapsed_time,
TestState *state)
{
- gint elapsed_time = clutter_timeline_get_elapsed_time (timeline);
-
if (elapsed_time == TEST_TIMELINE_DURATION)
{
g_test_message ("new-frame signal received (end of timeline)");
[ "text-column", "gchararray" ],
[ "int-column", "gint" ],
[ "actor-column", "ClutterRectangle" ]
+ ],
+ "rows" : [
+ [ "text-row-1", 1, null ],
+ [ "text-row-2", 2, { "type" : "ClutterRectangle", "color" : "blue" } ],
+ {
+ "int-column" : 3,
+ "actor-column" : { "type" : "ClutterRectangle", "name" : "actor-row-3" }
+ }
]
}
{ NULL }
};
+static void
+on_group_destroy (ClutterActor *actor,
+ SuperOH *oh)
+{
+ oh->group = NULL;
+}
+
+static void
+on_hand_destroy (ClutterActor *actor,
+ SuperOH *oh)
+{
+ int i;
+
+ for (i = 0; i < n_hands; i++)
+ {
+ if (oh->hand[i] == actor)
+ oh->hand[i] = NULL;
+ }
+}
+
static gboolean
on_button_press_event (ClutterActor *actor,
ClutterEvent *event,
gint i;
for (i = 0; i < n_hands; i++)
- clutter_actor_show (oh->hand[i]);
+ {
+ if (oh->hand[i] != NULL)
+ clutter_actor_show (oh->hand[i]);
+ }
return TRUE;
}
float rotation = clutter_timeline_get_progress (timeline) * 360.0f;
/* Rotate everything clockwise about stage center*/
-
- clutter_actor_set_rotation (oh->group,
- CLUTTER_Z_AXIS,
- rotation,
- oh->stage_width / 2,
- oh->stage_height / 2,
- 0);
+ if (oh->group != NULL)
+ clutter_actor_set_rotation (oh->group,
+ CLUTTER_Z_AXIS,
+ rotation,
+ oh->stage_width / 2,
+ oh->stage_height / 2,
+ 0);
for (i = 0; i < n_hands; i++)
{
/* Rotate each hand around there centers - to get this we need
* to take into account any scaling.
*/
- clutter_actor_set_rotation (oh->hand[i],
- CLUTTER_Z_AXIS,
- -6.0 * rotation,
- 0, 0, 0);
+ if (oh->hand[i] != NULL)
+ clutter_actor_set_rotation (oh->hand[i],
+ CLUTTER_Z_AXIS,
+ -6.0 * rotation,
+ 0, 0, 0);
}
}
/* create a new group to hold multiple actors in a group */
oh->group = clutter_group_new();
clutter_actor_set_name (oh->group, "Group");
+ g_signal_connect (oh->group, "destroy", G_CALLBACK (on_group_destroy), oh);
oh->hand = g_new (ClutterActor*, n_hands);
G_CALLBACK (on_button_press_event),
oh);
+ g_signal_connect (oh->hand[i], "destroy",
+ G_CALLBACK (on_hand_destroy),
+ oh);
+
if (i % 2)
clutter_behaviour_apply (oh->scaler_1, oh->hand[i]);
else
clutter_main ();
+ clutter_timeline_stop (oh->timeline);
+
/* clean up */
g_object_unref (oh->scaler_1);
g_object_unref (oh->scaler_2);
#include <clutter/clutter.h>
#include <gmodule.h>
+#include <math.h>
typedef struct _CallbackData CallbackData;
typedef struct _Clip Clip;
{
CLIP_NONE,
CLIP_RECTANGLE,
- CLIP_ELLIPSE,
+ CLIP_ROTATED_RECTANGLE,
CLIP_SHAPES
} ClipType;
clip->y2);
break;
- case CLIP_ELLIPSE:
- cogl_path_ellipse ((clip->x1 + clip->x2) / 2,
- (clip->y1 + clip->y2) / 2,
- (clip->x2 - clip->x1) / 2,
- (clip->y2 - clip->y1) / 2);
+ case CLIP_ROTATED_RECTANGLE:
+ {
+ int size = MIN (ABS (clip->x2 - clip->x1),
+ ABS (clip->y2 - clip->y1));
+ int cx = (clip->x1 + clip->x2) / 2;
+ int cy = (clip->y1 + clip->y2) / 2;
+
+ cogl_path_move_to (cx - size / 2, cy);
+ cogl_path_line_to (cx, cy - size / 2);
+ cogl_path_line_to (cx + size / 2, cy);
+ cogl_path_line_to (cx, cy + size / 2);
+ cogl_path_close ();
+ }
break;
case CLIP_SHAPES:
clip->y1,
clip->x2,
clip->y2);
+ else if (clip->type == CLIP_ROTATED_RECTANGLE)
+ {
+ float size = MIN (ABS (clip->x2 - clip->x1),
+ ABS (clip->y2 - clip->y1));
+ int cx = (clip->x1 + clip->x2) / 2;
+ int cy = (clip->y1 + clip->y2) / 2;
+
+ size = sqrtf ((size / 2) * (size / 2) * 2);
+
+ cogl_push_matrix ();
+
+ /* Rotate 45° about the centre point */
+ cogl_translate (cx, cy, 0.0f);
+ cogl_rotate (45.0f, 0.0f, 0.0f, 1.0f);
+ cogl_clip_push_rectangle (-size / 2, -size / 2, size / 2, size / 2);
+
+ cogl_pop_matrix ();
+ }
else
{
make_clip_path (clip);
data->current_clip.type
= event->button == 1 ? CLIP_RECTANGLE
: event->button == 2 ? CLIP_SHAPES
- : CLIP_ELLIPSE;
+ : CLIP_ROTATED_RECTANGLE;
clutter_actor_queue_redraw (stage);
-#include <config.h>
#include <glib.h>
#include <gmodule.h>
#include <stdlib.h>
-#include <config.h>
-#undef COGL_ENABLE_EXPERIMENTAL_2_0_API
#include <glib.h>
#include <gmodule.h>
#include <stdlib.h>
-#include <clutter/clutter.h>
+
+#undef COGL_ENABLE_EXPERIMENTAL_2_0_API
#include <cogl/cogl.h>
+#include <clutter/clutter.h>
typedef void (*PaintFunc) (void);
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
error = NULL;
- redhand = cogl_texture_new_from_file (file, 0, COGL_PIXEL_FORMAT_ANY,
+ redhand = cogl_texture_new_from_file (file,
+ COGL_TEXTURE_NO_ATLAS,
+ COGL_PIXEL_FORMAT_ANY,
&error);
if (redhand == COGL_INVALID_HANDLE)
g_error ("image load failed: %s", error->message);
-#include <config.h>
#include <glib.h>
#include <gmodule.h>
#include <stdlib.h>
-#include <config.h>
#include <glib.h>
#include <gmodule.h>
#include <stdlib.h>
-#include <config.h>
#include <glib.h>
#include <gmodule.h>
#include <stdlib.h>
-#include <config.h>
#include <glib.h>
#include <gmodule.h>
#include <stdlib.h>
-#include <config.h>
#include <glib.h>
#include <gmodule.h>
#include <stdlib.h>
-#include <config.h>
#include <glib.h>
#include <gmodule.h>
#include <stdlib.h>
clutter_color_from_string (&rect_color, colors[i]);
rect = clutter_rectangle_new ();
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color);
- clutter_actor_set_size (rect, 128, 128);
clutter_actor_set_opacity (rect, 0);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_Y, 0.0);
clutter_actor_add_constraint_with_name (rect, "y-bind", constraint);
+ constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_SIZE, 0.0);
+ clutter_actor_add_constraint_with_name (rect, "size-bind", constraint);
+
rects[i] = rect;
}
#include <clutter/x11/clutter-x11.h>
typedef struct {
+ ClutterActor *stage;
GHashTable *devices;
-
} TestDevicesApp;
static const gchar *
case CLUTTER_EXTENSION_DEVICE:
return "Extension";
+ case CLUTTER_PEN_DEVICE:
+ return "Pen";
+
+ case CLUTTER_ERASER_DEVICE:
+ return "Eraser";
+
+ case CLUTTER_CURSOR_DEVICE:
+ return "Cursor";
+
+ default:
+ return "Unknown";
+ }
+
+ g_warn_if_reached ();
+
+ return NULL;
+}
+
+static const gchar *
+axis_type_name (ClutterInputAxis axis)
+{
+ switch (axis)
+ {
+ case CLUTTER_INPUT_AXIS_X:
+ return "Absolute X";
+
+ case CLUTTER_INPUT_AXIS_Y:
+ return "Absolute Y";
+
+ case CLUTTER_INPUT_AXIS_PRESSURE:
+ return "Pressure";
+
+ case CLUTTER_INPUT_AXIS_XTILT:
+ return "X Tilt";
+
+ case CLUTTER_INPUT_AXIS_YTILT:
+ return "Y Tilt";
+
+ case CLUTTER_INPUT_AXIS_WHEEL:
+ return "Wheel";
+
default:
return "Unknown";
}
}
static gboolean
-stage_motion_event_cb (ClutterActor *actor,
- ClutterEvent *event,
- gpointer userdata)
+stage_button_event_cb (ClutterActor *actor,
+ ClutterEvent *event,
+ TestDevicesApp *app)
{
- TestDevicesApp *app = (TestDevicesApp *)userdata;
ClutterInputDevice *device;
+ ClutterInputDevice *source_device;
ClutterActor *hand = NULL;
+ gdouble *axes;
+ guint n_axes, i;
device = clutter_event_get_device (event);
+ source_device = clutter_event_get_source_device (event);
hand = g_hash_table_lookup (app->devices, device);
- g_print ("Device: '%s' (id:%d, type:%s)\n",
+ g_print ("Device: '%s' (id:%d, type: %s, source: '%s', axes: %d)\n",
clutter_input_device_get_device_name (device),
clutter_input_device_get_device_id (device),
- device_type_name (device));
+ device_type_name (device),
+ source_device != device
+ ? clutter_input_device_get_device_name (source_device)
+ : "<same>",
+ clutter_input_device_get_n_axes (device));
+
+ if (hand != NULL)
+ {
+ gfloat event_x, event_y;
+
+ clutter_event_get_coords (event, &event_x, &event_y);
+ clutter_actor_set_position (hand, event_x, event_y);
+ }
+
+ axes = clutter_event_get_axes (event, &n_axes);
+ for (i = 0; i < n_axes; i++)
+ {
+ ClutterInputAxis axis;
+
+ axis = clutter_input_device_get_axis (device, i);
+ if (axis == CLUTTER_INPUT_AXIS_IGNORE)
+ continue;
+
+ g_print ("\tAxis[%2d][%s].value: %.2f\n",
+ i,
+ axis_type_name (axis),
+ axes[i]);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+stage_motion_event_cb (ClutterActor *actor,
+ ClutterEvent *event,
+ TestDevicesApp *app)
+{
+ ClutterInputDevice *device;
+ ClutterActor *hand = NULL;
+
+ device = clutter_event_get_device (event);
+ hand = g_hash_table_lookup (app->devices, device);
if (hand != NULL)
{
gfloat event_x, event_y;
return FALSE;
}
+static void
+manager_device_added_cb (ClutterDeviceManager *manager,
+ ClutterInputDevice *device,
+ TestDevicesApp *app)
+{
+ ClutterInputDeviceType device_type;
+ ClutterActor *hand = NULL;
+
+ g_print ("got a %s device '%s' with id %d\n",
+ device_type_name (device),
+ clutter_input_device_get_device_name (device),
+ clutter_input_device_get_device_id (device));
+
+ device_type = clutter_input_device_get_device_type (device);
+ if (device_type == CLUTTER_POINTER_DEVICE ||
+ device_type == CLUTTER_PEN_DEVICE ||
+ device_type == CLUTTER_POINTER_DEVICE)
+ {
+ g_print ("*** enabling device '%s' ***\n",
+ clutter_input_device_get_device_name (device));
+
+ clutter_input_device_set_enabled (device, TRUE);
+
+ hand = clutter_texture_new_from_file (TESTS_DATADIR
+ G_DIR_SEPARATOR_S
+ "redhand.png",
+ NULL);
+ g_hash_table_insert (app->devices, device, hand);
+
+ clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand);
+ }
+}
+
+static void
+manager_device_removed_cb (ClutterDeviceManager *manager,
+ ClutterInputDevice *device,
+ TestDevicesApp *app)
+{
+ ClutterInputDeviceType device_type;
+ ClutterActor *hand = NULL;
+
+ g_print ("removed a %s device '%s' with id %d\n",
+ device_type_name (device),
+ clutter_input_device_get_device_name (device),
+ clutter_input_device_get_device_id (device));
+
+ device_type = clutter_input_device_get_device_type (device);
+ if (device_type == CLUTTER_POINTER_DEVICE ||
+ device_type == CLUTTER_PEN_DEVICE ||
+ device_type == CLUTTER_POINTER_DEVICE)
+ {
+ hand = g_hash_table_lookup (app->devices, device);
+ if (hand != NULL)
+ clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand);
+
+ g_hash_table_remove (app->devices, device);
+ }
+}
+
G_MODULE_EXPORT int
test_devices_main (int argc, char **argv)
{
ClutterActor *stage;
TestDevicesApp *app;
- ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
ClutterDeviceManager *manager;
const GSList *stage_devices, *l;
app = g_new0 (TestDevicesApp, 1);
app->devices = g_hash_table_new (g_direct_hash, g_direct_equal) ;
- stage = clutter_stage_get_default ();
- clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
- //clutter_stage_fullscreen (CLUTTER_STAGE (stage));
-
+ stage = clutter_stage_new ();
+ clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_LightSkyBlue);
+ clutter_stage_set_title (CLUTTER_STAGE (stage), "Devices");
+ clutter_stage_hide_cursor (CLUTTER_STAGE (stage));
+ g_signal_connect (stage,
+ "destroy", G_CALLBACK (clutter_main_quit),
+ NULL);
g_signal_connect (stage,
- "motion-event", G_CALLBACK(stage_motion_event_cb),
+ "motion-event", G_CALLBACK (stage_motion_event_cb),
app);
+ g_signal_connect (stage,
+ "button-press-event", G_CALLBACK (stage_button_event_cb),
+ app);
+ app->stage = stage;
clutter_actor_show_all (stage);
manager = clutter_device_manager_get_default ();
+ g_signal_connect (manager,
+ "device-added", G_CALLBACK (manager_device_added_cb),
+ app);
+ g_signal_connect (manager,
+ "device-removed", G_CALLBACK (manager_device_removed_cb),
+ app);
+
stage_devices = clutter_device_manager_peek_devices (manager);
if (stage_devices == NULL)
ClutterInputDeviceType device_type;
ClutterActor *hand = NULL;
- g_print ("got a %s device '%s' with id %d...\n",
+ g_print ("got a %s device '%s' with id %d\n",
device_type_name (device),
clutter_input_device_get_device_name (device),
clutter_input_device_get_device_id (device));
device_type = clutter_input_device_get_device_type (device);
if (device_type == CLUTTER_POINTER_DEVICE ||
- device_type == CLUTTER_EXTENSION_DEVICE)
+ device_type == CLUTTER_PEN_DEVICE ||
+ device_type == CLUTTER_POINTER_DEVICE)
{
+ g_print ("*** enabling device '%s' ***\n",
+ clutter_input_device_get_device_name (device));
+
+ clutter_input_device_set_enabled (device, TRUE);
+
hand = clutter_texture_new_from_file (TESTS_DATADIR
G_DIR_SEPARATOR_S
"redhand.png",
clutter_container_add_actor (CLUTTER_CONTAINER (stage), box);
if (!fixed_size)
- {
- clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_WIDTH, 0.0));
- clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, 0.0));
- }
+ clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0));
clutter_actor_set_position (box, 0, 0);
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <gmodule.h>
#undef CLUTTER_DISABLE_DEPRECATED
#include <stdlib.h>
#include <glib.h>
-#ifdef HAVE_CLUTTER_GLX
+#ifdef CLUTTER_WINDOWING_X11
#include "clutter/x11/clutter-x11.h"
#endif
error = NULL;
-#ifdef HAVE_CLUTTER_GLX
+#ifdef CLUTTER_WINDOWING_X11
clutter_x11_set_use_argb_visual (TRUE);
#endif
-#include <config.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <stdlib.h>
#include <string.h>
#undef CLUTTER_DISABLE_DEPRECATED
#include <clutter/clutter.h>
-#if HAVE_CLUTTER_GLX
+#ifdef CLUTTER_WINDOWING_X11
-#include <clutter/x11/clutter-x11.h>
-#include <clutter/x11/clutter-x11-texture-pixmap.h>
+# include <clutter/x11/clutter-x11.h>
+# include <clutter/x11/clutter-x11-texture-pixmap.h>
-#include <clutter/glx/clutter-glx.h>
-#include <clutter/glx/clutter-glx-texture-pixmap.h>
-
-#include <X11/Xlib.h>
-#include <X11/extensions/Xcomposite.h>
+# include <X11/Xlib.h>
+# include <X11/extensions/Xcomposite.h>
#define IMAGE TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png"
# include <gdk-pixbuf/gdk-pixbuf.h>
static gboolean disable_x11 = FALSE;
-static gboolean disable_glx = FALSE;
static gboolean disable_animation = FALSE;
static GOptionEntry g_options[] =
&disable_x11,
"Disable redirection through X11 pixmap",
NULL },
- { "disable-glx",
- 0, 0,
- G_OPTION_ARG_NONE,
- &disable_glx,
- "Disable redirection through GLX pixmap",
- NULL },
{ "disable-animation",
0, 0,
G_OPTION_ARG_NONE,
clutter_behaviour_apply (depth_behavior, group);
}
-#ifdef HAVE_CLUTTER_GLX
- /* a window with glx */
- if (!disable_glx)
- {
- group = clutter_group_new ();
- clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
- label = clutter_text_new_with_text ("fixed",
- "ClutterGLXTexture (Window)");
- clutter_container_add_actor (CLUTTER_CONTAINER (group), label);
- tex = clutter_glx_texture_pixmap_new_with_window (win_remote);
- clutter_container_add_actor (CLUTTER_CONTAINER (group), tex);
- clutter_actor_set_position (tex, 0, 20);
- clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex),
- TRUE);
- clutter_texture_set_filter_quality (CLUTTER_TEXTURE (tex),
- CLUTTER_TEXTURE_QUALITY_HIGH);
- clutter_actor_set_position (group,
- clutter_actor_get_width (stage)
- - clutter_actor_get_width (tex),
- 0);
- if (!disable_animation)
- clutter_behaviour_apply (depth_behavior, group);
-
- if (!clutter_glx_texture_pixmap_using_extension (
- CLUTTER_GLX_TEXTURE_PIXMAP (tex)))
- g_print ("NOTE: Using fallback path, not GLX TFP!\n");
- }
-#endif /* HAVE_CLUTTER_GLX */
-
if (group)
row_height = clutter_actor_get_height (group);
else
return EXIT_SUCCESS;
}
-#else /* HAVE_CLUTTER_GLX */
-int test_pixmap_main (int argc, char **argv) { return EXIT_SUCCESS; };
-#endif /* HAVE_CLUTTER_GLX */
+#else
+
+int
+test_pixmap_main (int argc, char **argv)
+{
+ return EXIT_SUCCESS;
+};
+
+#endif /* CLUTTER_WINDOWING_X11 */
FRAGMENT_SHADER_VARS
"float get_avg_rel(sampler2D texB, float dx, float dy)"
"{"
- " vec4 colorB = texture2D (texB, cogl_tex_coord_in.st + vec2(dx, dy));"
+ " vec4 colorB = texture2D (texB, cogl_tex_coord_in[0].st + vec2(dx, dy));"
" return (colorB.r + colorB.g + colorB.b) / 3.0;"
"}"
FRAGMENT_SHADER_BEGIN
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <stdlib.h>
#include <gmodule.h>
}
}
-static gboolean
-fps_cb (gpointer data)
+static void
+on_paint (ClutterActor *stage, gconstpointer *data)
{
- ClutterActor *stage = CLUTTER_ACTOR (data);
-
- static GTimer *timer = NULL;
- static gint fps = 0;
-
- if (!timer)
- {
- timer = g_timer_new ();
- g_timer_start (timer);
- }
-
- if (g_timer_elapsed (timer, NULL) >= 1)
- {
- printf ("fps: %d\n", fps);
- g_timer_start (timer);
- fps = 0;
- }
-
- clutter_actor_paint (stage);
do_events (stage);
- ++fps;
+}
+
+static gboolean
+queue_redraw (gpointer stage)
+{
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
return TRUE;
}
ClutterColor color = { 0x00, 0x00, 0x00, 0xff };
ClutterActor *stage, *rect;
+ g_setenv ("CLUTTER_VBLANK", "none", FALSE);
+ g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE);
+ g_setenv ("CLUTTER_SHOW_FPS", "1", FALSE);
+
clutter_init_with_args (&argc, &argv,
NULL,
entries,
clutter_actor_show (stage);
- g_idle_add (fps_cb, (gpointer)stage);
+ g_idle_add (queue_redraw, stage);
+
+ g_signal_connect (stage, "paint", G_CALLBACK (on_paint), NULL);
clutter_main ();