From 4bd3fa583e75407cabfc099aa8ca64565a6593bd Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 22 Mar 2007 18:21:59 +0000 Subject: [PATCH] 2007-03-22 Emmanuele Bassi * clutter/clutter-private.h: Remove inclusion of backend-specific headers; update the main context object; add the declarations for the event queue functions. * clutter/clutter-backend.[ch]: Add the abstract ClutterBackend object, which holds backend-specific settings, the main stage, and the event queue. Every backend must implement a subclass of ClutterBackend and ClutterStage. * clutter/clutter-feature.c: Protect the GLX specific calls behing #ifdef HAVE_CLUTTER_GLX. * clutter/clutter-actor.c: * clutter/clutter-group.c: * clutter/clutter-clone-texture.c: Include GL/gl.h * clutter/clutter-event.[ch]: Update public API and implement the event queue private API; hold a reference on the event objects; move out the keysym-to-unicode table; add the new event types. * clutter/clutter-color.h: Include clutter-fixed.h * clutter/clutter-main.c: Update API; get the main stage from the backend object; process the event received from the queue; lock/unlock the main mutex if we have one; move the initialisation process sooner in the init sequence, in order to have the backend object when we check for options; call the backed vfuncs in the pre/post parse hooks. * clutter/clutter-stage.c: Make ClutterStage and abstract class, implemented by the backends. * clutter/clutter/glx/clutter-glx.h: * clutter/clutter/glx/clutter-backend-glx.[ch]: * clutter/clutter/glx/clutter-event-glx.c: * clutter/clutter/glx/clutter-stage-glx.[ch]: * clutter/clutter/glx/Makefile.am: Add the GLX backend. * clutter/clutter/egl/clutter-backend-egl.[ch]: * clutter/clutter/egl/clutter-event-egl.c: * clutter/clutter/egl/clutter-stage-egl.[ch]: * clutter/clutter/egl/Makefile.am: Add the stub for a EGL backend. * examples/*.c: Update for the new API. --- ChangeLog | 47 + clutter.pc.in | 9 +- clutter/Makefile.am | 185 +-- clutter/clutter-actor.c | 85 +- clutter/clutter-backend-glx.c | 173 --- clutter/clutter-backend-glx.h | 54 - clutter/clutter-backend.c | 156 +++ clutter/clutter-backend.h | 101 ++ clutter/clutter-clone-texture.c | 2 + clutter/clutter-color.h | 1 + clutter/clutter-event.c | 1246 +++++------------ clutter/clutter-event.h | 143 +- clutter/clutter-feature.c | 37 +- clutter/clutter-group.c | 2 + clutter/clutter-keysyms-table.h | 827 +++++++++++ clutter/clutter-main.c | 233 +-- clutter/clutter-main.h | 11 +- clutter/clutter-private.h | 57 +- clutter/clutter-stage-glx.c | 898 ------------ clutter/clutter-stage.c | 512 ++++--- clutter/clutter-stage.h | 131 +- clutter/clutter-texture.c | 1 - clutter/clutter-version.h.in | 2 +- clutter/egl/Makefile.am | 19 + clutter/egl/clutter-backend-egl.c | 75 + clutter/egl/clutter-backend-egl.h | 56 + clutter/egl/clutter-event-egl.c | 0 clutter/egl/clutter-stage-egl.c | 19 + clutter/egl/clutter-stage-egl.h | 28 + clutter/glx/clutter-backend-glx.c | 437 ++++++ clutter/glx/clutter-backend-glx.h | 70 + clutter/glx/clutter-event-glx.c | 413 ++++++ .../clutter-glx.h} | 41 +- clutter/glx/clutter-stage-glx.c | 776 ++++++++++ clutter/glx/clutter-stage-glx.h | 74 + clutter/pango/pangoclutter.h | 2 +- configure.ac | 35 +- doc/reference/Makefile.am | 2 +- doc/reference/tmpl/clutter-event.sgml | 46 +- doc/reference/tmpl/clutter-main.sgml | 35 +- doc/reference/tmpl/clutter-media.sgml | 15 + doc/reference/tmpl/clutter-stage.sgml | 39 +- doc/reference/tmpl/clutter-util.sgml | 15 - examples/behave.c | 43 +- examples/super-oh.c | 39 +- examples/test.c | 20 + 46 files changed, 4361 insertions(+), 2851 deletions(-) delete mode 100644 clutter/clutter-backend-glx.c delete mode 100644 clutter/clutter-backend-glx.h create mode 100644 clutter/clutter-backend.c create mode 100644 clutter/clutter-backend.h create mode 100644 clutter/clutter-keysyms-table.h delete mode 100644 clutter/clutter-stage-glx.c create mode 100644 clutter/egl/Makefile.am create mode 100644 clutter/egl/clutter-backend-egl.c create mode 100644 clutter/egl/clutter-backend-egl.h create mode 100644 clutter/egl/clutter-event-egl.c create mode 100644 clutter/egl/clutter-stage-egl.c create mode 100644 clutter/egl/clutter-stage-egl.h create mode 100644 clutter/glx/clutter-backend-glx.c create mode 100644 clutter/glx/clutter-backend-glx.h create mode 100644 clutter/glx/clutter-event-glx.c rename clutter/{clutter-stage-glx.h => glx/clutter-glx.h} (62%) create mode 100644 clutter/glx/clutter-stage-glx.c create mode 100644 clutter/glx/clutter-stage-glx.h diff --git a/ChangeLog b/ChangeLog index c0a534fca..33c19c915 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,50 @@ +2007-03-22 Emmanuele Bassi + + * clutter/clutter-private.h: Remove inclusion of backend-specific + headers; update the main context object; add the declarations for + the event queue functions. + + * clutter/clutter-backend.[ch]: Add the abstract ClutterBackend + object, which holds backend-specific settings, the main stage, + and the event queue. Every backend must implement a subclass of + ClutterBackend and ClutterStage. + + * clutter/clutter-feature.c: Protect the GLX specific calls + behing #ifdef HAVE_CLUTTER_GLX. + + * clutter/clutter-actor.c: + * clutter/clutter-group.c: + * clutter/clutter-clone-texture.c: Include GL/gl.h + + * clutter/clutter-event.[ch]: Update public API and implement the + event queue private API; hold a reference on the event objects; + move out the keysym-to-unicode table; add the new event types. + + * clutter/clutter-color.h: Include clutter-fixed.h + + * clutter/clutter-main.c: Update API; get the main stage + from the backend object; process the event received from the + queue; lock/unlock the main mutex if we have one; move the + initialisation process sooner in the init sequence, in order to + have the backend object when we check for options; call the + backed vfuncs in the pre/post parse hooks. + + * clutter/clutter-stage.c: Make ClutterStage and abstract class, + implemented by the backends. + + * clutter/clutter/glx/clutter-glx.h: + * clutter/clutter/glx/clutter-backend-glx.[ch]: + * clutter/clutter/glx/clutter-event-glx.c: + * clutter/clutter/glx/clutter-stage-glx.[ch]: + * clutter/clutter/glx/Makefile.am: Add the GLX backend. + + * clutter/clutter/egl/clutter-backend-egl.[ch]: + * clutter/clutter/egl/clutter-event-egl.c: + * clutter/clutter/egl/clutter-stage-egl.[ch]: + * clutter/clutter/egl/Makefile.am: Add the stub for a EGL backend. + + * examples/*.c: Update for the new API. + 2007-03-19 Matthew Allum * clutter/clutter-label.c: diff --git a/clutter.pc.in b/clutter.pc.in index 0399d5b1c..acc94f74d 100644 --- a/clutter.pc.in +++ b/clutter.pc.in @@ -2,10 +2,11 @@ prefix=@prefix@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include +backend=@clutterbackend@ -Name: clutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@ -Description: Clutter library +Name: Clutter +Description: Clutter Core Library (${backend} backend) Version: @VERSION@ -Libs: -L${libdir} -lclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@ -Cflags: -I${includedir}/clutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@ +Libs: -L${libdir} -lclutter-${backend}-0.3 +Cflags: -I${includedir}/clutter-0.3 Requires: pangoft2 glib-2.0 >= 2.8 gthread-2.0 gdk-pixbuf-2.0 gdk-pixbuf-xlib-2.0 diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 61f0a9705..6686aaf06 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -1,4 +1,10 @@ -SUBDIRS=pango +NULL = + +SUBDIRS = pango $(clutterbackend) + +DIST_SUBDIRS = pango glx egl + +target = $(clutterbackend) MARSHALFILES = clutter-marshal.c clutter-marshal.h ENUMFILES = clutter-enum-types.c clutter-enum-types.h @@ -6,35 +12,51 @@ STAMPFILES = stamp-clutter-marshal.h stamp-clutter-enum-types.h GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0` GLIB_MKENUMS=`pkg-config --variable=glib_mkenums glib-2.0` +INCLUDES = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/clutter/pango \ + -DPREFIX=\""$(prefix)"\" \ + -DLIBDIR=\""$(libdir)"\" \ + -DDATADIR=\""$(datadir)"\" \ + -DG_DISABLE_DEPRECATED \ + -DG_LOG_DOMAIN=\"Clutter\" \ + $(GCC_FLAGS) \ + $(CLUTTER_CFLAGS) \ + $(CLUTTER_DEBUG_CFLAGS) \ + $(NULL) + +LDADD = \ + -version-info $(LT_VERSION_INFO) \ + -export-dynamic \ + -rpath $(libdir) \ + $(NULL) + BUILT_SOURCES = $(MARSHALFILES) $(ENUMFILES) source_h = \ - $(srcdir)/clutter-keysyms.h \ - $(srcdir)/clutter-util.h \ - $(srcdir)/clutter-fixed.h \ - $(srcdir)/clutter-event.h \ - $(srcdir)/clutter-color.h \ - $(srcdir)/clutter-feature.h \ - $(srcdir)/clutter-timeline.h \ $(srcdir)/clutter-actor.h \ - $(srcdir)/clutter-group.h \ - $(srcdir)/clutter-stage.h \ - $(srcdir)/clutter-rectangle.h \ - $(srcdir)/clutter-texture.h \ - $(srcdir)/clutter-clone-texture.h \ - $(srcdir)/clutter-label.h \ + $(srcdir)/clutter-alpha.h \ $(srcdir)/clutter-behaviour.h \ $(srcdir)/clutter-behaviour-opacity.h \ $(srcdir)/clutter-behaviour-path.h \ $(srcdir)/clutter-behaviour-scale.h \ - $(srcdir)/clutter-alpha.h \ + $(srcdir)/clutter-clone-texture.h \ + $(srcdir)/clutter-color.h \ + $(srcdir)/clutter-event.h \ + $(srcdir)/clutter-feature.h \ + $(srcdir)/clutter-fixed.h \ + $(srcdir)/clutter-group.h \ + $(srcdir)/clutter-keysyms.h \ + $(srcdir)/clutter-label.h \ + $(srcdir)/clutter-main.h \ $(srcdir)/clutter-media.h \ + $(srcdir)/clutter-rectangle.h \ + $(srcdir)/clutter-stage.h \ + $(srcdir)/clutter-texture.h \ + $(srcdir)/clutter-timeline.h \ + $(srcdir)/clutter-util.h \ $(srcdir)/clutter-version.h \ - $(srcdir)/clutter-main.h - -backend_h = \ - $(srcdir)/clutter-stage-glx.h \ - $(srcdir)/clutter-backend-glx.h + $(NULL) clutter-marshal.h: stamp-clutter-marshal.h @true @@ -91,75 +113,76 @@ clutter-enum-types.c: clutter-enum-types.h && cp xgen-cetc clutter-enum-types.c \ && rm -f xgen-cetc -CLEANFILES = \ - $(BUILT_SOURCES) \ - $(STAMPFILES) +CLEANFILES = $(STAMPFILES) -source_c = clutter-main.c \ - clutter-util.c \ - clutter-feature.c \ - clutter-fixed.c \ - clutter-event.c \ - clutter-color.c \ - clutter-timeline.c \ - clutter-group.c \ - clutter-stage.c \ - clutter-rectangle.c \ - clutter-texture.c \ - clutter-clone-texture.c \ - clutter-label.c \ - clutter-actor.c \ - clutter-behaviour.c \ - clutter-behaviour-opacity.c \ - clutter-behaviour-path.c \ - clutter-behaviour-scale.c \ - clutter-alpha.c \ - clutter-media.c \ - clutter-enum-types.c +source_c = \ + clutter-actor.c \ + clutter-alpha.c \ + clutter-backend.c \ + clutter-behaviour.c \ + clutter-behaviour-opacity.c \ + clutter-behaviour-path.c \ + clutter-behaviour-scale.c \ + clutter-color.c \ + clutter-clone-texture.c \ + clutter-enum-types.c \ + clutter-event.c \ + clutter-feature.c \ + clutter-fixed.c \ + clutter-group.c \ + clutter-label.c \ + clutter-main.c \ + clutter-marshal.c \ + clutter-media.c \ + clutter-stage.c \ + clutter-rectangle.c \ + clutter-texture.c \ + clutter-timeline.c \ + clutter-util.c \ + $(NULL) -backend_c = \ - $(srcdir)/clutter-stage-glx.c \ - $(srcdir)/clutter-backend-glx.c +source_h_priv = \ + clutter-keysyms-table.h \ + clutter-backend.h \ + clutter-debug.h \ + clutter-private.h \ + $(NULL) -source_h_priv = clutter-debug.h clutter-private.h -libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_MAJORMINOR@_la_SOURCES = \ - $(MARSHALFILES) \ - $(source_c) \ - $(source_h) \ - $(backend_c) \ - $(backend_h) \ - $(source_h_priv) +libclutter_glx_0_3_la_LIBADD = \ + $(CLUTTER_LIBS) \ + pango/libpangoclutter.la \ + glx/libclutter-glx.la + +libclutter_glx_0_3_la_SOURCES = \ + $(source_c) \ + $(source_h) \ + $(source_h_priv) -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/clutter/pango \ - -DPREFIX=\""$(prefix)"\" \ - -DLIBDIR=\""$(libdir)"\" \ - -DDATADIR=\""$(datadir)"\" \ - -DG_DISABLE_DEPRECATED \ - -DG_LOG_DOMAIN=\"Clutter\" \ - $(GCC_FLAGS) \ - $(CLUTTER_CFLAGS) \ - $(CLUTTER_DEBUG_CFLAGS) +#libclutter_egl_0_3_la_LIBADD = \ +# $(CLUTTER_LIBS) \ +# pango/libpangoclutter.la \ +# egl/libclutter-egl.la +#libclutter_egl_0_3_la_SOURCES = \ +# $(source_c) \ +# $(source_h) \ +# $(source_h_priv) -lib_LTLIBRARIES = libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la +lib_LTLIBRARIES = $(clutterbackendlib) -libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_MAJORMINOR@_la_LIBADD = \ - @CLUTTER_LIBS@ $(top_builddir)/clutter/pango/libpangoclutter.la +EXTRA_LTLIBRARIES = libclutter-glx-0.3.la -libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_MAJORMINOR@_la_LDFLAGS = \ - @CLUTTER_LT_LDFLAGS@ +clutterdir = $(includedir)/clutter-@CLUTTER_MAJORMINOR@/clutter +clutter_HEADERS = \ + $(source_h) \ + clutter-enum-types.h \ + clutter-version.h \ + clutter.h -libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_MAJORMINOR@_la_DEPENDENCIES = \ - $(top_builddir)/clutter/pango/libpangoclutter.la - -clutterheadersdir = \ - $(includedir)/clutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@/clutter - -clutterheaders_HEADERS = $(source_h) \ - clutter-marshal.h \ - clutter-enum-types.h \ - clutter.h +DISTCLEANFILES = \ + $(ENUMFILES) \ + $(MARSHALFILES) \ + clutter-version.h \ + $(NULL) EXTRA_DIST = clutter-marshal.list clutter-version.h.in diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 1c2da67e2..a4414135f 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -40,6 +40,8 @@ #include "clutter-private.h" #include "clutter-debug.h" +#include + G_DEFINE_ABSTRACT_TYPE (ClutterActor, clutter_actor, G_TYPE_INITIALLY_UNOWNED); @@ -281,8 +283,12 @@ clutter_actor_unrealize (ClutterActor *self) void clutter_actor_paint (ClutterActor *self) { + ClutterActorPrivate *priv; ClutterActorClass *klass; + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + priv = self->priv; + if (!CLUTTER_ACTOR_IS_REALIZED (self)) { CLUTTER_NOTE (PAINT, "Attempting realize via paint()"); @@ -303,73 +309,74 @@ clutter_actor_paint (ClutterActor *self) if (clutter_actor_get_parent (self) != NULL) { - glTranslatef((float)(self->priv->coords.x1), - (float)(self->priv->coords.y1), - 0.0); + glTranslatef((float) (priv->coords.x1), + (float) (priv->coords.y1), + 0.0); } if (self->priv->rzang) { - glTranslatef ( self->priv->rzx, - self->priv->rzy, + glTranslatef (priv->rzx, + priv->rzy, + 0.0); + + glRotatef (priv->rzang, 0.0f, 0.0f, 1.0f); + + glTranslatef (-1. * priv->rzx, + -1. * priv->rzy, 0.0); - - glRotatef (self->priv->rzang, 0.0f, 0.0f, 1.0f); - - glTranslatef ( - self->priv->rzx, - - self->priv->rzy, - 0.0 ); } if (self->priv->ryang) { - glTranslatef ( self->priv->ryx, - 0.0, - (float)(self->priv->z) + self->priv->ryz); + glTranslatef (priv->ryx, + 0.0, + (float) (priv->z) + priv->ryz); - glRotatef (self->priv->ryang, 0.0f, 1.0f, 0.0f); + glRotatef (priv->ryang, 0.0f, 1.0f, 0.0f); - glTranslatef ( (float) - self->priv->ryx, - 0.0, - (float)(-1.0 * self->priv->z) - self->priv->ryz); + glTranslatef ((float) - priv->ryx, + 0.0, + (float) (-1. * priv->z) - priv->ryz); } if (self->priv->rxang) { - glTranslatef ( 0.0, - (float)self->priv->rxy, - (float)(self->priv->z) + self->priv->rxz); + glTranslatef (0.0, + (float) priv->rxy, + (float) (priv->z) + priv->rxz); - glRotatef (self->priv->rxang, 1.0f, 0.0f, 0.0f); + glRotatef (priv->rxang, 1.0f, 0.0f, 0.0f); - glTranslatef ( 0.0, - (float) - self->priv->rxy, - (float)(-1.0 * self->priv->z) - self->priv->rxz); + glTranslatef (0.0, + -1. * priv->rxy, + -1. * priv->z - priv->rxz); } if (self->priv->z) - glTranslatef ( 0.0, 0.0, (float)self->priv->z); + glTranslatef (0.0, 0.0, (float) priv->z); - if (self->priv->scale_x != CFX_ONE || self->priv->scale_y != CFX_ONE) + if (self->priv->scale_x != CFX_ONE || + self->priv->scale_y != CFX_ONE) { - glScaled (CLUTTER_FIXED_TO_DOUBLE (self->priv->scale_x), - CLUTTER_FIXED_TO_DOUBLE (self->priv->scale_y), + glScaled (CLUTTER_FIXED_TO_DOUBLE (priv->scale_x), + CLUTTER_FIXED_TO_DOUBLE (priv->scale_y), 1.0); } - if (self->priv->has_clip) + if (priv->has_clip) { - ClutterGeometry *clip = &(self->priv->clip); + ClutterGeometry *clip = &(priv->clip); glEnable (GL_STENCIL_TEST); glClearStencil (0.0f); - glClear(GL_STENCIL_BUFFER_BIT); + glClear (GL_STENCIL_BUFFER_BIT); glStencilFunc (GL_NEVER, 0x1, 0x1); glStencilOp (GL_INCR, GL_INCR, GL_INCR); - glColor3f(1.0f, 1.0f, 1.0f); + glColor3f (1.0f, 1.0f, 1.0f); glRecti (clip->x, clip->y, @@ -383,15 +390,11 @@ clutter_actor_paint (ClutterActor *self) if (klass->paint) (klass->paint) (self); - if (self->priv->has_clip) - { - glDisable (GL_STENCIL_TEST); - } + if (priv->has_clip) + glDisable (GL_STENCIL_TEST); - if (self->priv->scale_x != CFX_ONE || self->priv->scale_y != CFX_ONE) - { - glScaled (1.0, 1.0, 1.0); - } + if (priv->scale_x != CFX_ONE || priv->scale_y != CFX_ONE) + glScaled (1.0, 1.0, 1.0); glPopMatrix(); } diff --git a/clutter/clutter-backend-glx.c b/clutter/clutter-backend-glx.c deleted file mode 100644 index d65a65a37..000000000 --- a/clutter/clutter-backend-glx.c +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include -#include -#include -#include - -#include "clutter-main.h" - -static Display *_xdpy = NULL; -static Window _xwin_root; -static int _xscreen; - -static gchar *clutter_display_name = NULL; -static int clutter_screen = 0; - -static int TrappedErrorCode = 0; -static int (*old_error_handler) (Display *, XErrorEvent *); - -static int -error_handler(Display *xdpy, - XErrorEvent *error) -{ - TrappedErrorCode = error->error_code; - return 0; -} - -/** - * clutter_util_trap_x_errors: - * - * Trap X errors so they don't cause an abort. - */ -void -clutter_glx_trap_x_errors(void) -{ - TrappedErrorCode = 0; - old_error_handler = XSetErrorHandler(error_handler); -} - -/** - * clutter_util_untrap_x_errors: - * - * Stop trapping X errors. - * - * Return value: 0 if there was no error, or the last X error that occurred. - */ -int -clutter_glx_untrap_x_errors(void) -{ - XSetErrorHandler(old_error_handler); - return TrappedErrorCode; -} - - -/** - * clutter_glx_display: - * - * Retrieves the X display that Clutter is using - * - * Return value: A pointer to an X Display structure. - */ -Display* -clutter_glx_display (void) -{ - return _xdpy; -} - -/** - * clutter_glx_screen: - * - * Retrieves the X screen that Clutter is using. - * - * Return value: the X screen ID - */ -int -clutter_glx_screen (void) -{ - return _xscreen; -} - -/** - * clutter_glx_root_window: - * - * FIXME - * - * Return value: FIXME - */ -Window -clutter_glx_root_window (void) -{ - return _xwin_root; -} - -static GOptionEntry clutter_glx_args[] = { - { "display", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &clutter_display_name, - "X display to use", "DISPLAY" }, - { "screen", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT, &clutter_screen, - "X screen to use", "SCREEN" }, - { NULL, } -}; - - -static gboolean -pre_parse_hook (GOptionContext *context, - GOptionGroup *group, - gpointer data, - GError **error) -{ - const char *env_string; - - env_string = g_getenv ("DISPLAY"); - if (env_string) - { - clutter_display_name = g_strdup (env_string); - env_string = NULL; - } - - return TRUE; -} - -static gboolean -post_parse_hook (GOptionContext *context, - GOptionGroup *group, - gpointer data, - GError **error) -{ - _xdpy = XOpenDisplay (clutter_display_name); - - if (_xdpy) - { - if (clutter_screen == 0) - _xscreen = DefaultScreen (_xdpy); - else - { - Screen *xscreen; - - xscreen = ScreenOfDisplay (_xdpy, clutter_screen); - _xscreen = XScreenNumberOfScreen (xscreen); - } - - _xwin_root = RootWindow (_xdpy, _xscreen); - - /* we don't need it anymore */ - g_free (clutter_display_name); - } - else - { - g_set_error (error, - clutter_init_error_quark (), - CLUTTER_INIT_ERROR_BACKEND, - "Unable to connect to X Server DISPLAY."); - return FALSE; - } - - return TRUE; -} - -gboolean -clutter_backend_init (GOptionContext *context) -{ - GOptionGroup *group; - - group = g_option_group_new ("clutter-glx", - "Clutter GLX Options", - "Show Clutter GLX Options", - NULL, - NULL); - - g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook); - g_option_group_add_entries (group, clutter_glx_args); - g_option_context_add_group (context, group); - - return TRUE; -} diff --git a/clutter/clutter-backend-glx.h b/clutter/clutter-backend-glx.h deleted file mode 100644 index 6829a6414..000000000 --- a/clutter/clutter-backend-glx.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Authored By Matthew Allum - * - * Copyright (C) 2006 OpenedHand - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _HAVE_CLUTTER_GLX_H -#define _HAVE_CLUTTER_GLX_H - -#include -#include - -#include -#include - -gboolean -clutter_backend_init (GOptionContext *context) G_GNUC_INTERNAL; - -void -clutter_glx_trap_x_errors(void); - -int -clutter_glx_untrap_x_errors(void); - -Display* -clutter_glx_display (void); - -int -clutter_glx_screen (void); - -Window -clutter_glx_root_window (void); - - -#endif diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c new file mode 100644 index 000000000..871a58229 --- /dev/null +++ b/clutter/clutter-backend.c @@ -0,0 +1,156 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-backend.h" +#include "clutter-private.h" + +G_DEFINE_ABSTRACT_TYPE (ClutterBackend, + clutter_backend, + G_TYPE_OBJECT); + +static void +clutter_backend_class_init (ClutterBackendClass *klass) +{ + +} + +static void +clutter_backend_init (ClutterBackend *backend) +{ + backend->events_queue = g_queue_new (); + + backend->button_click_time[0] = backend->button_click_time[1] = 0; + backend->button_number[0] = backend->button_number[1] = -1; + backend->button_x[0] = backend->button_x[1] = 0; + backend->button_y[0] = backend->button_y[1] = 0; + + backend->double_click_time = 250; + backend->double_click_distance = 5; +} + +ClutterActor * +clutter_backend_get_stage (ClutterBackend *backend) +{ + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL); + + return CLUTTER_BACKEND_GET_CLASS (backend)->get_stage (backend); +} + +void +clutter_backend_add_options (ClutterBackend *backend, + GOptionGroup *group) +{ + g_return_if_fail (CLUTTER_IS_BACKEND (backend)); + + CLUTTER_BACKEND_GET_CLASS (backend)->add_options (backend, group); +} + +gboolean +clutter_backend_pre_parse (ClutterBackend *backend, + GError **error) +{ + ClutterBackendClass *klass; + + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->pre_parse) + return klass->pre_parse (backend, error); + + return TRUE; +} + +gboolean +clutter_backend_post_parse (ClutterBackend *backend, + GError **error) +{ + ClutterBackendClass *klass; + + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->post_parse) + return klass->post_parse (backend, error); + + return TRUE; +} + +gboolean +clutter_backend_init_stage (ClutterBackend *backend, + GError **error) +{ + ClutterBackendClass *klass; + + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->init_stage) + return klass->init_stage (backend, error); + + return TRUE; +} + +void +clutter_backend_init_events (ClutterBackend *backend) +{ + ClutterBackendClass *klass; + + g_return_if_fail (CLUTTER_IS_BACKEND (backend)); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->init_events) + klass->init_events (backend); +} + +ClutterEvent * +clutter_backend_get_event (ClutterBackend *backend) +{ + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL); + + _clutter_events_queue (backend); + return _clutter_event_queue_pop (backend); +} + +ClutterEvent * +clutter_backend_peek_event (ClutterBackend *backend) +{ + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL); + + return _clutter_event_queue_peek (backend); +} + +void +clutter_backend_put_event (ClutterBackend *backend, + ClutterEvent *event) +{ + g_return_if_fail (CLUTTER_IS_BACKEND (backend)); + g_return_if_fail (event != NULL); + + _clutter_event_queue_push (backend, clutter_event_copy (event)); +} diff --git a/clutter/clutter-backend.h b/clutter/clutter-backend.h new file mode 100644 index 000000000..7a5952e5b --- /dev/null +++ b/clutter/clutter-backend.h @@ -0,0 +1,101 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_BACKEND_H__ +#define __CLUTTER_BACKEND_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND (clutter_backend_get_type ()) +#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)) +#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)) +#define CLUTTER_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND, ClutterBackendClass)) + +typedef struct _ClutterBackend ClutterBackend; +typedef struct _ClutterBackendClass ClutterBackendClass; + +struct _ClutterBackend +{ + GObject parent_instance; + + /*< private >*/ + /* events queue: every backend must implement one */ + GQueue *events_queue; + gpointer queue_head; + + /* settings */ + guint double_click_time; + guint double_click_distance; + + /* multiple button click detection */ + guint32 button_click_time[2]; + guint32 button_number[2]; + gint button_x[2]; + gint button_y[2]; +}; + +struct _ClutterBackendClass +{ + GObjectClass parent_class; + + /* vfuncs */ + gboolean (* pre_parse) (ClutterBackend *backend, + GError **error); + gboolean (* post_parse) (ClutterBackend *backend, + GError **error); + gboolean (* init_stage) (ClutterBackend *backend, + GError **error); + void (* init_events) (ClutterBackend *backend); + ClutterActor *(* get_stage) (ClutterBackend *backend); + void (* add_options) (ClutterBackend *backend, + GOptionGroup *group); +}; + +GType clutter_backend_get_type (void) G_GNUC_CONST; +ClutterActor *clutter_backend_get_stage (ClutterBackend *backend); +void clutter_backend_add_options (ClutterBackend *backend, + GOptionGroup *group); +gboolean clutter_backend_pre_parse (ClutterBackend *backend, + GError **error); +gboolean clutter_backend_post_parse (ClutterBackend *backend, + GError **error); +gboolean clutter_backend_init_stage (ClutterBackend *backend, + GError **error); +void clutter_backend_init_events (ClutterBackend *backend); + +ClutterEvent *clutter_backend_get_event (ClutterBackend *backend); +ClutterEvent *clutter_backend_peek_event (ClutterBackend *backend); +void clutter_backend_put_event (ClutterBackend *backend, + ClutterEvent *event); + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_H__ */ diff --git a/clutter/clutter-clone-texture.c b/clutter/clutter-clone-texture.c index b99761979..39d4d9f12 100644 --- a/clutter/clutter-clone-texture.c +++ b/clutter/clutter-clone-texture.c @@ -41,6 +41,8 @@ #include "clutter-private.h" #include "clutter-debug.h" +#include + enum { PROP_0, diff --git a/clutter/clutter-color.h b/clutter/clutter-color.h index c85ee8a5d..6785a9445 100644 --- a/clutter/clutter-color.h +++ b/clutter/clutter-color.h @@ -27,6 +27,7 @@ #define _HAVE_CLUTTER_COLOR_H #include +#include G_BEGIN_DECLS diff --git a/clutter/clutter-event.c b/clutter/clutter-event.c index b55562ad4..53b892874 100644 --- a/clutter/clutter-event.c +++ b/clutter/clutter-event.c @@ -27,7 +27,15 @@ #include "config.h" #endif +#include "clutter-keysyms-table.h" #include "clutter-event.h" +#include "clutter-private.h" +#include "clutter-debug.h" + +/* main event handler */ +ClutterEventFunc _clutter_event_func = NULL; +gpointer _clutter_event_data = NULL; +GDestroyNotify _clutter_event_destroy = NULL; /** * clutter_event_type: @@ -40,119 +48,153 @@ ClutterEventType clutter_event_type (ClutterEvent *event) { + g_return_val_if_fail (event != NULL, CLUTTER_NOTHING); + return event->type; } /** - * clutter_button_event_time: - * @buttev: a #ClutterButtonEvent + * clutter_event_get_time: + * @event: a #ClutterEvent * * Retrieves the time of the event. * - * Return value: the time of the event. + * Return value: the time of the event, or %CLUTTER_CURRENT_TIME + * + * Since: 0.4 */ guint32 -clutter_button_event_time (ClutterButtonEvent *buttev) +clutter_event_get_time (ClutterEvent *event) { - return buttev->time; + g_return_val_if_fail (event != NULL, CLUTTER_CURRENT_TIME); + + switch (event->type) + { + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + return event->key.time; + case CLUTTER_BUTTON_PRESS: + case CLUTTER_2BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + return event->button.time; + case CLUTTER_MOTION: + return event->motion.time; + case CLUTTER_SCROLL: + return event->scroll.time; + default: + break; + } + + return CLUTTER_CURRENT_TIME; } /** - * clutter_button_event_x: - * @buttev: a #ClutterButtonEvent + * clutter_event_get_state: + * @event: a #ClutterEvent * - * Retrieve the x coordinate of the event. + * Retrieves the modifier state of the event. * - * Return value: the x coordinate. + * Return value the modifier state parameter, or 0 + * + * Since: 0.4 */ -gint -clutter_button_event_x (ClutterButtonEvent *buttev) +guint32 +clutter_event_get_state (ClutterEvent *event) { - return buttev->x; + g_return_val_if_fail (event != NULL, 0); + + switch (event->type) + { + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + return event->key.modifier_state; + case CLUTTER_BUTTON_PRESS: + case CLUTTER_2BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + return event->button.modifier_state; + case CLUTTER_MOTION: + return event->motion.modifier_state; + case CLUTTER_SCROLL: + return event->scroll.modifier_state; + default: + break; + } + + return 0; } /** - * clutter_button_event_y: + * clutter_event_get_coords: + * @event: a #ClutterEvent + * @x: return location for the X coordinate + * @y: return location for the Y coordinate + * + * Retrieves the coordinates of @event and puts them into @x and @y. + * + * Since: 0.4 + */ +void +clutter_event_get_coords (ClutterEvent *event, + gint *x, + gint *y) +{ + gint event_x, event_y; + + g_return_if_fail (event != NULL); + + event_x = event_y = 0; + + switch (event->type) + { + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + event_x = event_y = 0; + break; + case CLUTTER_BUTTON_PRESS: + case CLUTTER_2BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + event_x = event->button.x; + event_y = event->button.y; + break; + case CLUTTER_MOTION: + event_x = event->motion.x; + event_y = event->motion.y; + break; + case CLUTTER_SCROLL: + event_x = event->scroll.x; + event_y = event->scroll.y; + break; + default: + break; + } + + if (x) + *x = event_x; + + if (y) + *y = event_y; +} + +/** + * clutter_button_event_button: * @buttev: a #ClutterButtonEvent * - * Retrieve the y coordinate of the event. + * Retrieve the button number of the event. * - * Return value: the y coordinate + * Return value: the button number. + * + * Since: 0.4 */ -gint -clutter_button_event_y (ClutterButtonEvent *buttev) -{ - return buttev->y; -} - -guint32 -clutter_button_event_state (ClutterButtonEvent *buttev) -{ - return buttev->modifier_state; -} - guint32 clutter_button_event_button (ClutterButtonEvent *buttev) { + g_return_val_if_fail (buttev != NULL, 0); + return buttev->button; } -/* Motion */ - -guint32 -clutter_motion_event_time (ClutterMotionEvent *motionev) -{ - return motionev->time; -} - -gint -clutter_motion_event_x (ClutterMotionEvent *motionev) -{ - return motionev->x; -} - -gint -clutter_motion_event_y (ClutterMotionEvent *motionev) -{ - return motionev->y; -} - -guint32 -clutter_motion_event_state (ClutterMotionEvent *motionev) -{ - return motionev->modifier_state; -} - /* keys */ -/** - * clutter_key_event_time: - * @keyev: A #ClutterKeyEvent - * - * Retrieves the time of @keyev - * - * Return value: The time that the event occurred - */ -guint32 -clutter_key_event_time (ClutterKeyEvent *keyev) -{ - return keyev->time; -} - -/** - * clutter_key_event_state: - * @keyev: A #ClutterKeyEvent - * - * Retrieves the state of the modifier keys whenever the event occurred - * - * Return value: A mask representing the state of the modifier keys - */ -guint -clutter_key_event_state (ClutterKeyEvent *keyev) -{ - return keyev->modifier_state; -} - /** * clutter_key_event_symbol: * @keyev: A #ClutterKeyEvent @@ -164,6 +206,8 @@ clutter_key_event_state (ClutterKeyEvent *keyev) guint clutter_key_event_symbol (ClutterKeyEvent *keyev) { + g_return_val_if_fail (keyev != NULL, 0); + return keyev->keyval; } @@ -178,6 +222,8 @@ clutter_key_event_symbol (ClutterKeyEvent *keyev) guint16 clutter_key_event_code (ClutterKeyEvent *keyev) { + g_return_val_if_fail (keyev != NULL, 0); + return keyev->hardware_keycode; } @@ -192,832 +238,11 @@ clutter_key_event_code (ClutterKeyEvent *keyev) guint32 clutter_key_event_unicode (ClutterKeyEvent *keyev) { + g_return_val_if_fail (keyev != NULL, 0); + return clutter_keysym_to_unicode (keyev->keyval); } -/* Code below from GDK, which contains following comment; - * - * Thanks to Markus G. Kuhn for the ksysym<->Unicode - * mapping functions, from the xterm sources. - */ -static struct { - unsigned short keysym; - unsigned short ucs; -} clutter_keysym_to_unicode_tab[] = { - { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ - { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ - { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ - { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ - { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ - { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ - { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ - { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ - { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ - { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ - { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ - { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ - { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ - { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ - { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ - { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ - { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ - { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ - { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ - { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ - { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ - { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ - { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ - { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ - { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ - { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ - { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ - { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ - { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ - { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ - { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ - { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ - { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ - { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ - { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ - { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ - { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ - { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ - { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ - { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ - { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ - { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ - { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ - { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ - { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ - { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ - { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ - { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ - { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ - { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ - { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ - { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ - { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ - { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ - { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ - { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ - { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ - { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ - { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ - { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ - { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ - { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ - { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ - { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ - { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ - { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ - { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ - { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ - { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ - { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ - { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ - { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ - { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ - { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ - { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ - { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ - { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ - { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ - { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ - { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ - { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ - { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ - { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ - { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ - { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ - { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ - { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ - { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ - { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ - { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ - { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ - { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ - { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ - { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ - { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ - { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ - { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ - { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ - { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ - { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ - { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ - { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ - { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ - { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ - { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ - { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ - { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ - { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ - { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ - { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ - { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ - { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ - { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ - { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ - { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ - { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ - { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ - { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ - { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ - { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ - { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ - { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ - { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ - { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ - { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ - { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ - { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ - { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ - { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ - { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ - { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ - { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ - { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ - { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ - { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ - { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ - { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ - { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ - { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ - { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ - { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ - { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ - { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ - { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ - { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ - { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ - { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ - { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ - { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ - { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ - { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ - { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ - { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ - { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ - { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ - { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ - { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ - { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ - { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ - { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ - { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ - { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ - { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ - { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ - { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ - { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ - { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ - { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ - { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ - { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ - { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ - { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ - { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ - { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ - { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ - { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ - { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ - { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ - { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ - { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ - { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ - { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ - { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ - { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ - { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ - { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ - { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ - { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ - { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ - { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ - { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ - { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ - { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ - { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ - { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ - { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ - { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ - { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ - { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ - { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ - { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ - { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ - { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ - { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ - { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ - { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ - { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ - { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ - { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ - { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ - { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ - { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ - { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ - { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ - { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ - { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ - { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ - { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ - { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ - { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ - { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ - { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ - { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ - { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ - { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ - { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ - { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ - { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ - { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ - { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ - { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ - { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ - { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ - { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ - { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ - { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ - { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ - { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ - { 0x06ad, 0x0491 }, /* Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN */ - { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ - { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ - { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ - { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ - { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ - { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ - { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ - { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ - { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ - { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ - { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ - { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ - { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ - { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ - { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ - { 0x06bd, 0x0490 }, /* Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ - { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ - { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ - { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ - { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ - { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ - { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ - { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ - { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ - { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ - { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ - { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ - { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ - { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ - { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ - { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ - { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ - { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ - { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ - { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ - { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ - { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ - { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ - { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ - { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ - { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ - { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ - { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ - { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ - { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ - { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ - { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ - { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ - { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ - { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ - { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ - { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ - { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ - { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ - { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ - { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ - { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ - { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ - { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ - { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ - { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ - { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ - { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ - { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ - { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ - { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ - { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ - { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ - { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ - { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ - { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ - { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ - { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ - { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ - { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ - { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ - { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ - { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ - { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ - { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ - { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ - { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ - { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ - { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ - { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ - { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ - { 0x07a5, 0x03aa }, /* Greek_IOTAdieresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ - { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ - { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ - { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ - { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ - { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ - { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ - { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ - { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ - { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ - { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ - { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ - { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ - { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ - { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ - { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ - { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ - { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ - { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ - { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ - { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ - { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ - { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ - { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ - { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ - { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ - { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ - { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ - { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ - { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ - { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ - { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ - { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ - { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ - { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ - { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ - { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ - { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ - { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ - { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ - { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ - { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ - { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ - { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ - { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ - { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ - { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ - { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ - { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ - { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ - { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ - { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ - { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ - { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ - { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ - { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ - { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ - { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ - { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ - { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ - { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ - { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ - { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ - { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ - { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ - { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ - { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ -/* 0x08a1 leftradical ? ??? */ -/* 0x08a2 topleftradical ? ??? */ -/* 0x08a3 horizconnector ? ??? */ - { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ - { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ - { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ -/* 0x08a7 topleftsqbracket ? ??? */ -/* 0x08a8 botleftsqbracket ? ??? */ -/* 0x08a9 toprightsqbracket ? ??? */ -/* 0x08aa botrightsqbracket ? ??? */ -/* 0x08ab topleftparens ? ??? */ -/* 0x08ac botleftparens ? ??? */ -/* 0x08ad toprightparens ? ??? */ -/* 0x08ae botrightparens ? ??? */ -/* 0x08af leftmiddlecurlybrace ? ??? */ -/* 0x08b0 rightmiddlecurlybrace ? ??? */ -/* 0x08b1 topleftsummation ? ??? */ -/* 0x08b2 botleftsummation ? ??? */ -/* 0x08b3 topvertsummationconnector ? ??? */ -/* 0x08b4 botvertsummationconnector ? ??? */ -/* 0x08b5 toprightsummation ? ??? */ -/* 0x08b6 botrightsummation ? ??? */ -/* 0x08b7 rightmiddlesummation ? ??? */ - { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ - { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ - { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ - { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ - { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ - { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ - { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ - { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ - { 0x08c8, 0x2245 }, /* approximate ≅ APPROXIMATELY EQUAL TO */ -/* 0x08c9 similarequal ? ??? */ - { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ - { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ - { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ - { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ - { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ - { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ - { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ - { 0x08dd, 0x222a }, /* union ∪ UNION */ - { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ - { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ - { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ - { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ - { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ - { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ - { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ - { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ - { 0x09df, 0x2422 }, /* blank ␢ BLANK SYMBOL */ - { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ - { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ - { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ - { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ - { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ - { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ - { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ - { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ - { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ - { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ - { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ - { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ - { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ -/* 0x09ef horizlinescan1 ? ??? */ -/* 0x09f0 horizlinescan3 ? ??? */ - { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ -/* 0x09f2 horizlinescan7 ? ??? */ -/* 0x09f3 horizlinescan9 ? ??? */ - { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ - { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ - { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ - { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ - { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ - { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ - { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ - { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ - { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ - { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ - { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ - { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ - { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ - { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ - { 0x0aaa, 0x2013 }, /* endash – EN DASH */ -/* 0x0aac signifblank ? ??? */ - { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ -/* 0x0aaf doubbaselinedot ? ??? */ - { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ - { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ - { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ - { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ - { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ - { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ - { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ - { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ - { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ - { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ - { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ - { 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */ - { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ -/* 0x0abf marker ? ??? */ - { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ - { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ - { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ - { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ - { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ - { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ -/* 0x0acb trademarkincircle ? ??? */ - { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ - { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ - { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ - { 0x0acf, 0x25a1 }, /* emopenrectangle □ WHITE SQUARE */ - { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ - { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ - { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ - { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ - { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ - { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ - { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ - { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ -/* 0x0ada hexagram ? ??? */ - { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ - { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ - { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ - { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ - { 0x0adf, 0x25a0 }, /* emfilledrect ■ BLACK SQUARE */ - { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ - { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ - { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ - { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ - { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ - { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ - { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ - { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ - { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ - { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ - { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ - { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ - { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ - { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ - { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ - { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ - { 0x0af1, 0x2020 }, /* dagger † DAGGER */ - { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ - { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ - { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ - { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ - { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ - { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ - { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ - { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ - { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ - { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ - { 0x0afc, 0x2038 }, /* caret ‸ CARET */ - { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ - { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ -/* 0x0aff cursor ? ??? */ - { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ - { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ - { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ - { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ - { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ - { 0x0bc2, 0x22a4 }, /* downtack ⊤ DOWN TACK */ - { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ - { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ - { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ - { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ - { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */ - { 0x0bce, 0x22a5 }, /* uptack ⊥ UP TACK */ - { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ - { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ - { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ - { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ - { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ - { 0x0bdc, 0x22a3 }, /* lefttack ⊣ LEFT TACK */ - { 0x0bfc, 0x22a2 }, /* righttack ⊢ RIGHT TACK */ - { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ - { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ - { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ - { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ - { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ - { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ - { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ - { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ - { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ - { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ - { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ - { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ - { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ - { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ - { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ - { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ - { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ - { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ - { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ - { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ - { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ - { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ - { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ - { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ - { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ - { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ - { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ - { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ - { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ - { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ - { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ - { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ - { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ - { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ - { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ - { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ - { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ - { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ - { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ - { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ - { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ - { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ - { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ - { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ - { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ - { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ - { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ - { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ - { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ - { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ - { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ - { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ - { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ - { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ - { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ - { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ - { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ - { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ - { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ - { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ - { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ - { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ - { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ - { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ - { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ - { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ - { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ - { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ - { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ - { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ - { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ - { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ - { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ - { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ - { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ - { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ - { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ - { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ - { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ - { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ - { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ - { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ - { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ - { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ - { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ - { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ - { 0x0dde, 0x0e3e }, /* Thai_maihanakat_maitho ฾ ??? */ - { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ - { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ - { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ - { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ - { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ - { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ - { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ - { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ - { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ - { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ - { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ - { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ - { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ - { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ - { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ - { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ - { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ - { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ - { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ - { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ - { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ - { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ - { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ - { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ - { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ - { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ - { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ - { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ - { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ - { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ - { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ - { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ - { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ - { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ - { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ - { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ - { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ - { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ - { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ - { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ - { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ - { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ - { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ - { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ - { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ - { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ - { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ - { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ - { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ - { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ - { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ - { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ - { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ - { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ - { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ - { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ - { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ - { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ - { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ - { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ - { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ - { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ - { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ - { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ - { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ - { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ - { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ - { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ - { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ - { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ - { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ - { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ - { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ - { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ - { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ - { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ - { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ - { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ - { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ - { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ - { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ - { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ - { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ - { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ - { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ - { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ - { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ - { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ - { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ - { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ - { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ - { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ - { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ - { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ - { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ - { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ - { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ - { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ - { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ - { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ - { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ - { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ - { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ - { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ - { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ - { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ - { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ -/* 0x0ef3 Hangul_KkogjiDalrinIeung ? ??? */ - { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ - { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ - { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ - { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ - { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ -/* 0x0ef9 Hangul_J_KkogjiDalrinIeung ? ??? */ - { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ - { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ - { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ - { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ - { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ - { 0x20a0, 0x20a0 }, /* EcuSign ₠ EURO-CURRENCY SIGN */ - { 0x20a1, 0x20a1 }, /* ColonSign ₡ COLON SIGN */ - { 0x20a2, 0x20a2 }, /* CruzeiroSign ₢ CRUZEIRO SIGN */ - { 0x20a3, 0x20a3 }, /* FFrancSign ₣ FRENCH FRANC SIGN */ - { 0x20a4, 0x20a4 }, /* LiraSign ₤ LIRA SIGN */ - { 0x20a5, 0x20a5 }, /* MillSign ₥ MILL SIGN */ - { 0x20a6, 0x20a6 }, /* NairaSign ₦ NAIRA SIGN */ - { 0x20a7, 0x20a7 }, /* PesetaSign ₧ PESETA SIGN */ - { 0x20a8, 0x20a8 }, /* RupeeSign ₨ RUPEE SIGN */ - { 0x20a9, 0x20a9 }, /* WonSign ₩ WON SIGN */ - { 0x20aa, 0x20aa }, /* NewSheqelSign ₪ NEW SHEQEL SIGN */ - { 0x20ab, 0x20ab }, /* DongSign ₫ DONG SIGN */ - { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ - - - /* Following items added to GTK, not in the xterm table */ - - /* Numeric keypad */ - - { 0xFF80 /* Space */, ' ' }, - { 0xFFAA /* Multiply */, '*' }, - { 0xFFAB /* Add */, '+' }, - { 0xFFAC /* Separator */, ',' }, - { 0xFFAD /* Subtract */, '-' }, - { 0xFFAE /* Decimal */, '.' }, - { 0xFFAF /* Divide */, '/' }, - { 0xFFB0 /* 0 */, '0' }, - { 0xFFB1 /* 1 */, '1' }, - { 0xFFB2 /* 2 */, '2' }, - { 0xFFB3 /* 3 */, '3' }, - { 0xFFB4 /* 4 */, '4' }, - { 0xFFB5 /* 5 */, '5' }, - { 0xFFB6 /* 6 */, '6' }, - { 0xFFB7 /* 7 */, '7' }, - { 0xFFB8 /* 8 */, '8' }, - { 0xFFB9 /* 9 */, '9' }, - { 0xFFBD /* Equal */, '=' }, - - /* End numeric keypad */ -}; - /** * clutter_keysym_to_unicode: * @keyval: a clutter key symbol @@ -1062,6 +287,20 @@ clutter_keysym_to_unicode (guint keyval) return 0; } +GType +clutter_event_get_type (void) +{ + static GType our_type = 0; + + if (!our_type) + our_type = g_boxed_type_register_static ("ClutterEvent", + (GBoxedCopyFunc) clutter_event_copy, + (GBoxedFreeFunc) clutter_event_free); + return our_type; +} + +static GHashTable *event_hash = NULL; + /** * clutter_event_new: * @type: The type of event. @@ -1075,8 +314,15 @@ clutter_event_new (ClutterEventType type) { ClutterEvent *new_event; - new_event = g_new0 (ClutterEvent, 1); - new_event->any.type = type; + if (!event_hash) + event_hash = g_hash_table_new (g_direct_hash, NULL); + + new_event = g_slice_new0 (ClutterEvent); + + new_event->type = new_event->any.type = type; + new_event->flags = CLUTTER_EVENT_NONE; + + g_hash_table_insert (event_hash, new_event, GUINT_TO_POINTER (1)); return new_event; } @@ -1096,7 +342,7 @@ clutter_event_copy (ClutterEvent *event) g_return_val_if_fail (event != NULL, NULL); - new_event = g_new (ClutterEvent, 1); + new_event = clutter_event_new (CLUTTER_NOTHING); *new_event = *event; return new_event; @@ -1111,20 +357,182 @@ clutter_event_copy (ClutterEvent *event) void clutter_event_free (ClutterEvent *event) { - if (!event) - return; - - g_free (event); + if (G_LIKELY (event)) + { + g_hash_table_remove (event_hash, event); + g_slice_free (ClutterEvent, event); + } } -GType -clutter_event_get_type (void) +/** + * clutter_event_get: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +ClutterEvent * +clutter_event_get (void) { - static GType our_type = 0; + ClutterMainContext *context = clutter_context_get_default (); + ClutterBackend *backend = context->backend; - if (!our_type) - our_type = g_boxed_type_register_static ("ClutterEvent", - (GBoxedCopyFunc) clutter_event_copy, - (GBoxedFreeFunc) clutter_event_free); - return our_type; + _clutter_events_queue (backend); + return _clutter_event_queue_pop (backend); +} + +/** + * clutter_event_peek: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +ClutterEvent * +clutter_event_peek (void) +{ + ClutterMainContext *context = clutter_context_get_default (); + + return _clutter_event_queue_peek (context->backend); +} + +/** + * clutter_event_put: + * @event: a #ClutterEvent + * + * FIXME + * + * Since: 0.4 + */ +void +clutter_event_put (ClutterEvent *event) +{ + ClutterMainContext *context = clutter_context_get_default (); + ClutterBackend *backend = context->backend; + + _clutter_event_queue_push (backend, clutter_event_copy (event)); +} + +void +_clutter_event_queue_push (ClutterBackend *backend, + ClutterEvent *event) +{ + if (!backend->events_queue) + backend->events_queue = g_queue_new (); + + g_queue_push_head (backend->events_queue, event); +} + +ClutterEvent * +_clutter_event_queue_pop (ClutterBackend *backend) +{ + if (!backend->events_queue) + return NULL; + + return g_queue_pop_head (backend->events_queue); +} + +ClutterEvent * +_clutter_event_queue_peek (ClutterBackend *backend) +{ + if (!backend->events_queue) + return NULL; + + return g_queue_peek_head (backend->events_queue); +} + +gboolean +_clutter_event_queue_check_pending (ClutterBackend *backend) +{ + if (!backend->events_queue) + return FALSE; + + return g_queue_is_empty (backend->events_queue) == FALSE; +} + +void +_clutter_set_events_handler (ClutterEventFunc func, + gpointer data, + GDestroyNotify destroy) +{ + if (_clutter_event_destroy) + (* _clutter_event_destroy) (_clutter_event_data); + + _clutter_event_func = func; + _clutter_event_data = data; + _clutter_event_destroy = destroy; +} + +void +_clutter_synthetise_stage_state (ClutterBackend *backend, + ClutterEvent *event, + ClutterStageState set_flags, + ClutterStageState unset_flags) +{ + +} + +void +_clutter_synthesize_click (ClutterBackend *backend, + ClutterEvent *event, + gint n_clicks) +{ + ClutterEvent temp_event; + + temp_event = *event; + temp_event.type = (n_clicks == 2) ? CLUTTER_2BUTTON_PRESS + : CLUTTER_3BUTTON_PRESS; + + clutter_backend_put_event (backend, &temp_event); +} + +void +_clutter_event_button_generate (ClutterBackend *backend, + ClutterEvent *event) +{ + if ((event->button.time < (backend->button_click_time[1] + 2 * backend->double_click_time)) && + (event->button.button == backend->button_number[1]) && + (ABS (event->button.x - backend->button_x[1]) <= backend->double_click_distance) && + (ABS (event->button.y - backend->button_y[1]) <= backend->double_click_distance)) + { + _clutter_synthesize_click (backend, event, 3); + + backend->button_click_time[1] = 0; + backend->button_click_time[0] = 0; + backend->button_number[1] = -1; + backend->button_number[0] = -1; + backend->button_x[0] = backend->button_x[1] = 0; + backend->button_y[0] = backend->button_y[1] = 0; + } + else if ((event->button.time < (backend->button_click_time[0] + backend->double_click_time)) && + (event->button.button == backend->button_number[0]) && + (ABS (event->button.x - backend->button_x[0]) <= backend->double_click_distance) && + (ABS (event->button.y - backend->button_y[0]) <= backend->double_click_distance)) + { + _clutter_synthesize_click (backend, event, 2); + + backend->button_click_time[1] = backend->button_click_time[0]; + backend->button_click_time[0] = event->button.time; + backend->button_number[1] = backend->button_number[0]; + backend->button_number[0] = event->button.button; + backend->button_x[1] = backend->button_x[0]; + backend->button_x[0] = event->button.x; + backend->button_y[1] = backend->button_y[0]; + backend->button_y[0] = event->button.y; + } + else + { + backend->button_click_time[1] = 0; + backend->button_click_time[0] = event->button.time; + backend->button_number[1] = -1; + backend->button_number[0] = event->button.button; + backend->button_x[1] = 0; + backend->button_x[0] = event->button.x; + backend->button_y[1] = 0; + backend->button_y[0] = event->button.y; + } } diff --git a/clutter/clutter-event.h b/clutter/clutter-event.h index 59f29e56f..1418b7dca 100644 --- a/clutter/clutter-event.h +++ b/clutter/clutter-event.h @@ -28,8 +28,11 @@ #include -G_BEGIN_DECLS +#define CLUTTER_TYPE_EVENT (clutter_event_get_type ()) +#define CLUTTER_PRIORITY_EVENTS (G_PRIORITY_DEFAULT) +#define CLUTTER_CURRENT_TIME 0L +G_BEGIN_DECLS enum { @@ -43,27 +46,62 @@ enum typedef enum { - CLUTTER_NOTHING, + CLUTTER_NOTHING = 0, CLUTTER_KEY_PRESS, CLUTTER_KEY_RELEASE, CLUTTER_MOTION, CLUTTER_BUTTON_PRESS, CLUTTER_2BUTTON_PRESS, /* Double click */ - CLUTTER_BUTTON_RELEASE + CLUTTER_3BUTTON_PRESS, /* Triple click */ + CLUTTER_BUTTON_RELEASE, + CLUTTER_SCROLL, + CLUTTER_STAGE_STATE, + CLUTTER_DESTROY_NOTIFY } ClutterEventType; -#define CLUTTER_TYPE_EVENT (clutter_event_get_type ()) +typedef enum +{ + CLUTTER_EVENT_NONE = 0, + CLUTTER_EVENT_PENDING = 1 << 0 +} ClutterEventFlags; + +typedef enum +{ + CLUTTER_SCROLL_UP, + CLUTTER_SCROLL_DOWN, + CLUTTER_SCROLL_LEFT, + CLUTTER_SCROLL_RIGHT +} ClutterScrollDirection; + +typedef enum +{ + CLUTTER_STAGE_STATE_FULLSCREEN, + CLUTTER_STAGE_STATE_MAXIMIZED, + CLUTTER_STAGE_STATE_MINIMIZED, + CLUTTER_STAGE_STATE_OFFSCREEN +} ClutterStageState; + +typedef enum +{ + CLUTTER_FILTER_CONTINUE, + CLUTTER_FILTER_REMOVE +} ClutterFilterResponse; typedef union _ClutterEvent ClutterEvent; -typedef struct _ClutterAnyEvent ClutterAnyEvent; -typedef struct _ClutterKeyEvent ClutterKeyEvent; -typedef struct _ClutterButtonEvent ClutterButtonEvent; -typedef struct _ClutterMotionEvent ClutterMotionEvent; +typedef struct _ClutterAnyEvent ClutterAnyEvent; +typedef struct _ClutterButtonEvent ClutterButtonEvent; +typedef struct _ClutterKeyEvent ClutterKeyEvent; +typedef struct _ClutterMotionEvent ClutterMotionEvent; +typedef struct _ClutterScrollEvent ClutterScrollEvent; +typedef struct _ClutterStageStateEvent ClutterStageStateEvent; typedef struct _ClutterInputDevice ClutterInputDevice; + +typedef ClutterFilterResponse (* ClutterFilterFunc) (ClutterEvent *event, gpointer data); + struct _ClutterAnyEvent { ClutterEventType type; @@ -72,61 +110,88 @@ struct _ClutterAnyEvent struct _ClutterKeyEvent { ClutterEventType type; - guint32 time; - guint modifier_state; - guint keyval; - guint16 hardware_keycode; + guint32 time; + guint modifier_state; + guint keyval; + guint16 hardware_keycode; }; struct _ClutterButtonEvent { - ClutterEventType type; - guint32 time; - gint x; - gint y; - guint32 modifier_state; - guint32 button; - gdouble *axes; /* Future use */ - ClutterInputDevice *device; /* Future use */ + ClutterEventType type; + guint32 time; + gint x; + gint y; + guint32 modifier_state; + guint32 button; + gdouble *axes; /* Future use */ + ClutterInputDevice *device; /* Future use */ }; struct _ClutterMotionEvent { - ClutterEventType type; - guint32 time; - gint x; - gint y; - guint32 modifier_state; - gdouble *axes; /* Future use */ - ClutterInputDevice *device; /* Future use */ + ClutterEventType type; + guint32 time; + gint x; + gint y; + guint32 modifier_state; + gdouble *axes; /* Future use */ + ClutterInputDevice *device; /* Future use */ +}; + +struct _ClutterScrollEvent +{ + ClutterEventType type; + guint32 time; + gint x; + gint y; + ClutterScrollDirection direction; + guint32 modifier_state; + gdouble *axes; /* future use */ + ClutterInputDevice *device; /* future use */ +}; + +struct _ClutterStageStateEvent +{ + ClutterEventType type; + ClutterStageState changed_mask; + ClutterStageState new_state; }; union _ClutterEvent { - ClutterEventType type; + ClutterEventType type; + ClutterEventFlags flags; - ClutterAnyEvent any; - ClutterKeyEvent key; + ClutterAnyEvent any; ClutterButtonEvent button; + ClutterKeyEvent key; ClutterMotionEvent motion; + ClutterScrollEvent scroll; + ClutterStageStateEvent stage_state; }; GType clutter_event_get_type (void) G_GNUC_CONST; -ClutterEvent *clutter_event_new (ClutterEventType type); -ClutterEvent *clutter_event_copy (ClutterEvent *event); -void clutter_event_free (ClutterEvent *event); -ClutterEventType clutter_event_type (ClutterEvent *event); +gboolean clutter_events_pending (void); +ClutterEvent * clutter_event_get (void); +ClutterEvent * clutter_event_peek (void); +void clutter_event_put (ClutterEvent *event); +ClutterEvent * clutter_event_new (ClutterEventType type); +ClutterEvent * clutter_event_copy (ClutterEvent *event); +void clutter_event_free (ClutterEvent *event); +ClutterEventType clutter_event_type (ClutterEvent *event); +guint32 clutter_event_get_time (ClutterEvent *event); +guint clutter_event_get_state (ClutterEvent *event); +void clutter_event_get_coords (ClutterEvent *event, + gint *x, + gint *y); -guint32 clutter_key_event_time (ClutterKeyEvent *keyev); -guint clutter_key_event_state (ClutterKeyEvent *keyev); guint clutter_key_event_symbol (ClutterKeyEvent *keyev); guint16 clutter_key_event_code (ClutterKeyEvent *keyev); guint32 clutter_key_event_unicode (ClutterKeyEvent *keyev); -guint32 clutter_button_event_time (ClutterButtonEvent *buttev); -gint clutter_button_event_x (ClutterButtonEvent *buttev); -gint clutter_button_event_y (ClutterButtonEvent *buttev); +guint32 clutter_button_event_button (ClutterButtonEvent *buttev); guint32 clutter_keysym_to_unicode (guint keyval); diff --git a/clutter/clutter-feature.c b/clutter/clutter-feature.c index 656e97345..180eb793b 100644 --- a/clutter/clutter-feature.c +++ b/clutter/clutter-feature.c @@ -50,6 +50,10 @@ #include "clutter-private.h" #include "clutter-debug.h" +#ifdef HAVE_CLUTTER_GLX +#include "glx/clutter-glx.h" +#endif + typedef void (*FuncPtr) (void); typedef int (*GLXGetVideoSyncProc) (unsigned int *count); typedef int (*GLXWaitVideoSyncProc) (int divisor, @@ -199,10 +203,7 @@ check_vblank_env (const char *name) { const char *val; -#if 0 - val = getenv("CLUTTER_VBLANK"); -#endif - val = clutter_vblank_method (); + val = clutter_get_vblank_method (); if (val && !strcasecmp(val, name)) return TRUE; @@ -245,35 +246,42 @@ clutter_feature_init (void) CLUTTER_NOTE (MISC, "allocating features data"); __features = g_new0 (ClutterFeatures, 1); - memset(&__features->funcs, 0, sizeof(ClutterFeatureFuncs)); + memset(&__features->funcs, 0, sizeof (ClutterFeatureFuncs)); __features->features_set = FALSE; /* don't rely on zero-ing */ } - if (!clutter_glx_display ()) +#ifdef HAVE_CLUTTER_GLX + if (!clutter_glx_get_default_display ()) return; +#endif if (__features->features_set) return; +#ifdef HAVE_CLUTTER_GLX gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS); - glx_extensions = glXQueryExtensionsString (clutter_glx_display (), - clutter_glx_screen ()); + glx_extensions = glXQueryExtensionsString (clutter_glx_get_default_display (), + clutter_glx_get_default_screen ()); - if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions) - || check_gl_extension ("GL_EXT_texture_rectangle", gl_extensions)) - __features->flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE; + if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions) || + check_gl_extension ("GL_EXT_texture_rectangle", gl_extensions)) + { + __features->flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE; + } +#endif /* vblank */ __features->vblank_type = CLUTTER_VBLANK_NONE; - if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env("none")) + if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env ("none")) { CLUTTER_NOTE (MISC, "vblank sync: disabled at user request"); } else { - if (!check_vblank_env("dri") && +#ifdef HAVE_CLUTTER_GLX + if (!check_vblank_env ("dri") && check_gl_extension ("GLX_SGI_video_sync", glx_extensions)) { __features->funcs.get_video_sync = @@ -291,7 +299,8 @@ clutter_feature_init (void) __features->flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; } } - +#endif + if (!(__features->flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) { __features->dri_fd = open("/dev/dri/card0", O_RDWR); diff --git a/clutter/clutter-group.c b/clutter/clutter-group.c index 9b5b154b0..8798e2489 100644 --- a/clutter/clutter-group.c +++ b/clutter/clutter-group.c @@ -40,6 +40,8 @@ #include "clutter-marshal.h" #include "clutter-enum-types.h" +#include + enum { ADD, diff --git a/clutter/clutter-keysyms-table.h b/clutter/clutter-keysyms-table.h new file mode 100644 index 000000000..44fe0297c --- /dev/null +++ b/clutter/clutter-keysyms-table.h @@ -0,0 +1,827 @@ +#ifndef __CLUTTER_KEYSYMS_H__ +#define __CLUTTER_KEYSYMS_H__ + +/* Code below from GDK, which contains following comment; + * + * Thanks to Markus G. Kuhn for the ksysym<->Unicode + * mapping functions, from the xterm sources. + */ +struct { + unsigned short keysym; + unsigned short ucs; +} clutter_keysym_to_unicode_tab[] = { + { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ + { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ + { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ + { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ + { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ + { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ + { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ + { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ + { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ + { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ + { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ + { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ + { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ + { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ + { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ + { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ + { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ + { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ + { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ + { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ + { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ + { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ + { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ + { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ + { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ + { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ + { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ + { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ + { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ + { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ + { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ + { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ + { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ + { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ + { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ + { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ + { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ + { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ + { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ + { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ + { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ + { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ + { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ + { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ + { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ + { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ + { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ + { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ + { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ + { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ + { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ + { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ + { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ + { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ + { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ + { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ + { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ + { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ + { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ + { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ + { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ + { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ + { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ + { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ + { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ + { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ + { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ + { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ + { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ + { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ + { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ + { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ + { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ + { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ + { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ + { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ + { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ + { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ + { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ + { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ + { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ + { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ + { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ + { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ + { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ + { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ + { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ + { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ + { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ + { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ + { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ + { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ + { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ + { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ + { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ + { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ + { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ + { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ + { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ + { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ + { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ + { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ + { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ + { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ + { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ + { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ + { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ + { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ + { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ + { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ + { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ + { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ + { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ + { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ + { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ + { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ + { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ + { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ + { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ + { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ + { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ + { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ + { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ + { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ + { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ + { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ + { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ + { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ + { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ + { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ + { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ + { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ + { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ + { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ + { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ + { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ + { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ + { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ + { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ + { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ + { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ + { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ + { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ + { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ + { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ + { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ + { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ + { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ + { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ + { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ + { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ + { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ + { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ + { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ + { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ + { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ + { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ + { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ + { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ + { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ + { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ + { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ + { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ + { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ + { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ + { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ + { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ + { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ + { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ + { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ + { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ + { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ + { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ + { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ + { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ + { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ + { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ + { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ + { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ + { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ + { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ + { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ + { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ + { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ + { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ + { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ + { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ + { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ + { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ + { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ + { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ + { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ + { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ + { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ + { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ + { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ + { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ + { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ + { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ + { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ + { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ + { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ + { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ + { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ + { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ + { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ + { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ + { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ + { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ + { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ + { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ + { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ + { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ + { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ + { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ + { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ + { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ + { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ + { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ + { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ + { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ + { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ + { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ + { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ + { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ + { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ + { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ + { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ + { 0x06ad, 0x0491 }, /* Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN */ + { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ + { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ + { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ + { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ + { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ + { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ + { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ + { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ + { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ + { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ + { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ + { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ + { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ + { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ + { 0x06bd, 0x0490 }, /* Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ + { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ + { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ + { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ + { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ + { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ + { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ + { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ + { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ + { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ + { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ + { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ + { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ + { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ + { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ + { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ + { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ + { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ + { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ + { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ + { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ + { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ + { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ + { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ + { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ + { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ + { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ + { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ + { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ + { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ + { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ + { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ + { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ + { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ + { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ + { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ + { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ + { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ + { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ + { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ + { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ + { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ + { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ + { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ + { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ + { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ + { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ + { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ + { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ + { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ + { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ + { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ + { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ + { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ + { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ + { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ + { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ + { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ + { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ + { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ + { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ + { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ + { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ + { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ + { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ + { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ + { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ + { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ + { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ + { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ + { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ + { 0x07a5, 0x03aa }, /* Greek_IOTAdieresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ + { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ + { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ + { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ + { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ + { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ + { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ + { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ + { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ + { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ + { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ + { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ + { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ + { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ + { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ + { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ + { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ + { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ + { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ + { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ + { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ + { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ + { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ + { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ + { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ + { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ + { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ + { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ + { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ + { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ + { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ + { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ + { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ + { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ + { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ + { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ + { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ + { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ + { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ + { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ + { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ + { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ + { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ + { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ + { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ + { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ + { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ + { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ + { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ + { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ + { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ + { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ + { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ + { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ + { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ + { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ + { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ + { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ + { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ + { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ + { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ + { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ + { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ + { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ + { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ +/* 0x08a1 leftradical ? ??? */ +/* 0x08a2 topleftradical ? ??? */ +/* 0x08a3 horizconnector ? ??? */ + { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ + { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ + { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ +/* 0x08a7 topleftsqbracket ? ??? */ +/* 0x08a8 botleftsqbracket ? ??? */ +/* 0x08a9 toprightsqbracket ? ??? */ +/* 0x08aa botrightsqbracket ? ??? */ +/* 0x08ab topleftparens ? ??? */ +/* 0x08ac botleftparens ? ??? */ +/* 0x08ad toprightparens ? ??? */ +/* 0x08ae botrightparens ? ??? */ +/* 0x08af leftmiddlecurlybrace ? ??? */ +/* 0x08b0 rightmiddlecurlybrace ? ??? */ +/* 0x08b1 topleftsummation ? ??? */ +/* 0x08b2 botleftsummation ? ??? */ +/* 0x08b3 topvertsummationconnector ? ??? */ +/* 0x08b4 botvertsummationconnector ? ??? */ +/* 0x08b5 toprightsummation ? ??? */ +/* 0x08b6 botrightsummation ? ??? */ +/* 0x08b7 rightmiddlesummation ? ??? */ + { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ + { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ + { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ + { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ + { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ + { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ + { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ + { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ + { 0x08c8, 0x2245 }, /* approximate ≅ APPROXIMATELY EQUAL TO */ +/* 0x08c9 similarequal ? ??? */ + { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ + { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ + { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ + { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ + { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ + { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ + { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ + { 0x08dd, 0x222a }, /* union ∪ UNION */ + { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ + { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ + { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ + { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ + { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ + { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ + { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ + { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ + { 0x09df, 0x2422 }, /* blank ␢ BLANK SYMBOL */ + { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ + { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ + { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ + { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ + { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ + { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ + { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ + { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ + { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ + { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ + { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ + { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ + { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ +/* 0x09ef horizlinescan1 ? ??? */ +/* 0x09f0 horizlinescan3 ? ??? */ + { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ +/* 0x09f2 horizlinescan7 ? ??? */ +/* 0x09f3 horizlinescan9 ? ??? */ + { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ + { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ + { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ + { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ + { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ + { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ + { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ + { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ + { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ + { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ + { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ + { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ + { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ + { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ + { 0x0aaa, 0x2013 }, /* endash – EN DASH */ +/* 0x0aac signifblank ? ??? */ + { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ +/* 0x0aaf doubbaselinedot ? ??? */ + { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ + { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ + { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ + { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ + { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ + { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ + { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ + { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ + { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ + { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ + { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ + { 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */ + { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ +/* 0x0abf marker ? ??? */ + { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ + { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ + { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ + { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ + { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ + { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ +/* 0x0acb trademarkincircle ? ??? */ + { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ + { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ + { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ + { 0x0acf, 0x25a1 }, /* emopenrectangle □ WHITE SQUARE */ + { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ + { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ + { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ + { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ + { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ + { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ + { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ + { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ +/* 0x0ada hexagram ? ??? */ + { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ + { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ + { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ + { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ + { 0x0adf, 0x25a0 }, /* emfilledrect ■ BLACK SQUARE */ + { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ + { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ + { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ + { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ + { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ + { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ + { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ + { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ + { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ + { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ + { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ + { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ + { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ + { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ + { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ + { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ + { 0x0af1, 0x2020 }, /* dagger † DAGGER */ + { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ + { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ + { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ + { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ + { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ + { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ + { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ + { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ + { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ + { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ + { 0x0afc, 0x2038 }, /* caret ‸ CARET */ + { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ + { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ +/* 0x0aff cursor ? ??? */ + { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ + { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ + { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ + { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ + { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ + { 0x0bc2, 0x22a4 }, /* downtack ⊤ DOWN TACK */ + { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ + { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ + { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ + { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ + { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */ + { 0x0bce, 0x22a5 }, /* uptack ⊥ UP TACK */ + { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ + { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ + { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ + { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ + { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ + { 0x0bdc, 0x22a3 }, /* lefttack ⊣ LEFT TACK */ + { 0x0bfc, 0x22a2 }, /* righttack ⊢ RIGHT TACK */ + { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ + { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ + { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ + { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ + { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ + { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ + { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ + { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ + { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ + { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ + { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ + { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ + { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ + { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ + { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ + { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ + { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ + { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ + { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ + { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ + { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ + { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ + { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ + { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ + { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ + { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ + { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ + { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ + { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ + { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ + { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ + { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ + { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ + { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ + { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ + { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ + { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ + { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ + { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ + { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ + { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ + { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ + { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ + { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ + { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ + { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ + { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ + { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ + { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ + { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ + { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ + { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ + { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ + { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ + { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ + { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ + { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ + { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ + { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ + { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ + { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ + { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ + { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ + { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ + { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ + { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ + { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ + { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ + { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ + { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ + { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ + { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ + { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ + { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ + { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ + { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ + { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ + { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ + { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ + { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ + { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ + { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ + { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ + { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ + { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ + { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ + { 0x0dde, 0x0e3e }, /* Thai_maihanakat_maitho ฾ ??? */ + { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ + { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ + { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ + { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ + { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ + { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ + { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ + { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ + { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ + { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ + { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ + { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ + { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ + { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ + { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ + { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ + { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ + { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ + { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ + { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ + { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ + { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ + { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ + { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ + { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ + { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ + { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ + { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ + { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ + { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ + { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ + { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ + { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ + { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ + { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ + { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ + { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ + { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ + { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ + { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ + { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ + { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ + { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ + { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ + { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ + { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ + { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ + { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ + { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ + { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ + { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ + { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ + { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ + { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ + { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ + { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ + { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ + { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ + { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ + { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ + { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ + { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ + { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ + { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ + { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ + { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ + { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ + { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ + { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ + { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ + { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ + { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ + { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ + { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ + { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ + { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ + { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ + { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ + { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ + { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ + { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ + { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ + { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ + { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ + { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ + { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ + { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ + { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ + { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ + { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ + { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ + { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ + { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ + { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ + { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ + { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ + { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ + { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ + { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ + { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ + { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ + { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ + { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ + { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ + { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ + { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ + { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ +/* 0x0ef3 Hangul_KkogjiDalrinIeung ? ??? */ + { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ + { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ + { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ + { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ + { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ +/* 0x0ef9 Hangul_J_KkogjiDalrinIeung ? ??? */ + { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ + { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ + { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ + { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ + { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ + { 0x20a0, 0x20a0 }, /* EcuSign ₠ EURO-CURRENCY SIGN */ + { 0x20a1, 0x20a1 }, /* ColonSign ₡ COLON SIGN */ + { 0x20a2, 0x20a2 }, /* CruzeiroSign ₢ CRUZEIRO SIGN */ + { 0x20a3, 0x20a3 }, /* FFrancSign ₣ FRENCH FRANC SIGN */ + { 0x20a4, 0x20a4 }, /* LiraSign ₤ LIRA SIGN */ + { 0x20a5, 0x20a5 }, /* MillSign ₥ MILL SIGN */ + { 0x20a6, 0x20a6 }, /* NairaSign ₦ NAIRA SIGN */ + { 0x20a7, 0x20a7 }, /* PesetaSign ₧ PESETA SIGN */ + { 0x20a8, 0x20a8 }, /* RupeeSign ₨ RUPEE SIGN */ + { 0x20a9, 0x20a9 }, /* WonSign ₩ WON SIGN */ + { 0x20aa, 0x20aa }, /* NewSheqelSign ₪ NEW SHEQEL SIGN */ + { 0x20ab, 0x20ab }, /* DongSign ₫ DONG SIGN */ + { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ + + + /* Following items added to GTK, not in the xterm table */ + + /* Numeric keypad */ + + { 0xFF80 /* Space */, ' ' }, + { 0xFFAA /* Multiply */, '*' }, + { 0xFFAB /* Add */, '+' }, + { 0xFFAC /* Separator */, ',' }, + { 0xFFAD /* Subtract */, '-' }, + { 0xFFAE /* Decimal */, '.' }, + { 0xFFAF /* Divide */, '/' }, + { 0xFFB0 /* 0 */, '0' }, + { 0xFFB1 /* 1 */, '1' }, + { 0xFFB2 /* 2 */, '2' }, + { 0xFFB3 /* 3 */, '3' }, + { 0xFFB4 /* 4 */, '4' }, + { 0xFFB5 /* 5 */, '5' }, + { 0xFFB6 /* 6 */, '6' }, + { 0xFFB7 /* 7 */, '7' }, + { 0xFFB8 /* 8 */, '8' }, + { 0xFFB9 /* 9 */, '9' }, + { 0xFFBD /* Equal */, '=' }, + + /* End numeric keypad */ +}; + +#endif /* __CLUTTER_KEYSYMS_H__ */ diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 2006accfe..ad51166c1 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -36,6 +36,8 @@ #include +#include "clutter-event.h" +#include "clutter-backend.h" #include "clutter-main.h" #include "clutter-feature.h" #include "clutter-actor.h" @@ -44,10 +46,6 @@ #include "clutter-debug.h" #include "clutter-version.h" /* For flavour define */ -#ifdef CLUTTER_FLAVOUR_GLX -#include -#endif - static ClutterMainContext *ClutterCntx = NULL; static gboolean clutter_is_initialized = FALSE; @@ -72,14 +70,32 @@ static const GDebugKey clutter_debug_keys[] = { #endif /* CLUTTER_ENABLE_DEBUG */ +/** + * clutter_get_show_fps: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ gboolean -clutter_want_fps (void) +clutter_get_show_fps (void) { return clutter_show_fps; } -const gchar * -clutter_vblank_method (void) +/** + * clutter_get_vblank_method: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +G_CONST_RETURN gchar * +clutter_get_vblank_method (void) { return clutter_vblank_name; } @@ -92,10 +108,57 @@ clutter_vblank_method (void) void clutter_redraw (void) { - ClutterMainContext *ctx = CLUTTER_CONTEXT(); - ClutterStage *stage = ctx->stage; + ClutterMainContext *ctx; + + ctx = clutter_context_get_default (); + if (ctx->backend) + clutter_actor_paint (clutter_backend_get_stage (ctx->backend)); +} - clutter_actor_paint (CLUTTER_ACTOR(stage)); +static void +clutter_main_do_event (ClutterEvent *event, + gpointer dummy) +{ + ClutterMainContext *context; + ClutterBackend *backend; + ClutterActor *stage; + + context = clutter_context_get_default (); + backend = context->backend; + stage = clutter_backend_get_stage (backend); + if (!stage) + return; + + switch (event->type) + { + case CLUTTER_NOTHING: + break; + case CLUTTER_BUTTON_PRESS: + case CLUTTER_2BUTTON_PRESS: + case CLUTTER_3BUTTON_PRESS: + g_signal_emit_by_name (stage, "button-press-event", event); + break; + case CLUTTER_BUTTON_RELEASE: + g_signal_emit_by_name (stage, "button-release-event", event); + break; + case CLUTTER_SCROLL: + g_signal_emit_by_name (stage, "scroll-event", event); + break; + case CLUTTER_KEY_PRESS: + g_signal_emit_by_name (stage, "key-press-event", event); + break; + case CLUTTER_KEY_RELEASE: + g_signal_emit_by_name (stage, "key-release-event", event); + break; + case CLUTTER_MOTION: + g_signal_emit_by_name (stage, "motion-event", event); + break; + case CLUTTER_DESTROY_NOTIFY: + g_signal_emit_by_name (stage, "delete-event"); + break; + case CLUTTER_STAGE_STATE: + break; + } } /** @@ -164,7 +227,10 @@ clutter_main (void) if (context->main_loop_level == 0) { - clutter_actor_destroy (CLUTTER_ACTOR (context->stage)); + /* this will take care of destroying the stage */ + g_object_unref (context->backend); + context->backend = NULL; + g_free (context); } } @@ -179,7 +245,8 @@ clutter_threads_enter(void) { ClutterMainContext *context = CLUTTER_CONTEXT (); - g_mutex_lock (context->gl_lock); + if (context->gl_lock) + g_mutex_lock (context->gl_lock); } /** @@ -192,21 +259,26 @@ clutter_threads_leave (void) { ClutterMainContext *context = CLUTTER_CONTEXT (); - g_mutex_unlock (context->gl_lock); + if (context->gl_lock) + g_mutex_unlock (context->gl_lock); } /** - * clutter_want_debug: + * clutter_get_debug_enabled: * * Check if clutter has debugging turned on. * * Return value: TRUE if debugging is turned on, FALSE otherwise. */ gboolean -clutter_want_debug (void) +clutter_get_debug_enabled (void) { +#ifdef CLUTTER_ENABLE_DEBUG return clutter_debug_flags != 0; +#else + return FALSE; +#endif } ClutterMainContext* @@ -217,6 +289,8 @@ clutter_context_get_default (void) ClutterMainContext *ctx; ctx = g_new0 (ClutterMainContext, 1); + ctx->backend = g_object_new (_clutter_backend_impl_get_type (), NULL); + ctx->is_initialized = FALSE; ClutterCntx = ctx; @@ -225,33 +299,6 @@ clutter_context_get_default (void) return ClutterCntx; } -static gboolean -is_gl_version_at_least_12 (void) -{ -#define NON_VENDOR_VERSION_MAX_LEN 32 - gchar non_vendor_version[NON_VENDOR_VERSION_MAX_LEN]; - const gchar *version; - gint i = 0; - - version = (const gchar*) glGetString (GL_VERSION); - - while ( ((version[i] <= '9' && version[i] >= '0') || version[i] == '.') - && i < NON_VENDOR_VERSION_MAX_LEN) - { - non_vendor_version[i] = version[i]; - i++; - } - - non_vendor_version[i] = '\0'; - - if (strstr (non_vendor_version, "1.0") == NULL - && strstr (non_vendor_version, "1.0") == NULL) - return TRUE; - - return FALSE; -} - - #ifdef CLUTTER_ENABLE_DEBUG static gboolean clutter_arg_debug_cb (const char *key, @@ -304,12 +351,24 @@ pre_parse_hook (GOptionContext *context, gpointer data, GError **error) { + ClutterMainContext *clutter_context; + ClutterBackend *backend; const char *env_string; if (clutter_is_initialized) return TRUE; - g_type_init (); + clutter_context = clutter_context_get_default (); + clutter_context->main_loops = NULL; + clutter_context->main_loop_level = 0; + + clutter_context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ()); + pango_ft2_font_map_set_resolution (clutter_context->font_map, 96.0, 96.0); + + backend = clutter_context->backend; + g_assert (CLUTTER_IS_BACKEND (backend)); + + _clutter_set_events_handler (clutter_main_do_event, NULL, NULL); #ifdef CLUTTER_ENABLE_DEBUG env_string = g_getenv ("CLUTTER_DEBUG"); @@ -334,6 +393,9 @@ pre_parse_hook (GOptionContext *context, if (env_string) clutter_show_fps = TRUE; + if (CLUTTER_BACKEND_GET_CLASS (backend)->pre_parse) + return CLUTTER_BACKEND_GET_CLASS (backend)->pre_parse (backend, error); + return TRUE; } @@ -347,10 +409,16 @@ post_parse_hook (GOptionContext *context, GError **error) { ClutterMainContext *clutter_context; + ClutterBackend *backend; + gboolean retval = FALSE; if (clutter_is_initialized) return TRUE; + clutter_context = clutter_context_get_default (); + backend = clutter_context->backend; + g_assert (CLUTTER_IS_BACKEND (backend)); + if (clutter_fatal_warnings) { GLogLevelFlags fatal_mask; @@ -360,18 +428,14 @@ post_parse_hook (GOptionContext *context, g_log_set_always_fatal (fatal_mask); } - clutter_context = clutter_context_get_default (); - clutter_context->main_loops = NULL; - clutter_context->main_loop_level = 0; + if (CLUTTER_BACKEND_GET_CLASS (backend)->post_parse) + retval = CLUTTER_BACKEND_GET_CLASS (backend)->post_parse (backend, error); + else + retval = TRUE; - clutter_context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ()); - pango_ft2_font_map_set_resolution (clutter_context->font_map, 96.0, 96.0); - - clutter_context->gl_lock = g_mutex_new (); - - clutter_is_initialized = TRUE; + clutter_is_initialized = retval; - return TRUE; + return retval; } /** @@ -390,15 +454,22 @@ post_parse_hook (GOptionContext *context, GOptionGroup * clutter_get_option_group (void) { + ClutterMainContext *context; GOptionGroup *group; + context = clutter_context_get_default (); + group = g_option_group_new ("clutter", "Clutter Options", "Show Clutter Options", NULL, NULL); + g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook); g_option_group_add_entries (group, clutter_args); + + /* add backend-specific options */ + clutter_backend_add_options (context->backend, group); return group; } @@ -409,34 +480,6 @@ clutter_init_error_quark (void) return g_quark_from_static_string ("clutter-init-error-quark"); } -static gboolean -clutter_stage_init (ClutterMainContext *context, - GError **error) -{ - context->stage = CLUTTER_STAGE (clutter_stage_get_default ()); - if (!CLUTTER_IS_STAGE (context->stage)) - { - g_set_error (error, clutter_init_error_quark (), - CLUTTER_INIT_ERROR_INTERNAL, - "Unable to create the main stage"); - return FALSE; - } - - g_object_ref_sink (context->stage); - - /* Realize to get context */ - clutter_actor_realize (CLUTTER_ACTOR (context->stage)); - if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (context->stage))) - { - g_set_error (error, clutter_init_error_quark (), - CLUTTER_INIT_ERROR_INTERNAL, - "Unable to realize the main stage"); - return FALSE; - } - - return TRUE; -} - /** * clutter_init_with_args: * @argc: a pointer to the number of command line arguments @@ -482,14 +525,11 @@ clutter_init_with_args (int *argc, if (clutter_is_initialized) return CLUTTER_INIT_SUCCESS; - if (!g_thread_supported ()) - g_thread_init (NULL); + g_type_init (); group = clutter_get_option_group (); context = g_option_context_new (parameter_string); - clutter_backend_init (context); - g_option_context_add_group (context, group); if (entries) @@ -507,12 +547,14 @@ clutter_init_with_args (int *argc, clutter_context = clutter_context_get_default (); stage_error = NULL; - if (!clutter_stage_init (clutter_context, &stage_error)) + if (!clutter_backend_init_stage (clutter_context->backend, &stage_error)) { g_propagate_error (error, stage_error); return CLUTTER_INIT_ERROR_INTERNAL; } + clutter_backend_init_events (clutter_context->backend); + return CLUTTER_INIT_SUCCESS; } @@ -533,10 +575,8 @@ clutter_parse_args (int *argc, g_option_context_set_help_enabled (option_context, FALSE); /* Initiate any command line options from the backend */ - clutter_backend_init (option_context); clutter_group = clutter_get_option_group (); - g_option_context_set_main_group (option_context, clutter_group); if (!g_option_context_parse (option_context, argc, argv, &error)) @@ -573,8 +613,7 @@ clutter_init (int *argc, if (clutter_is_initialized) return CLUTTER_INIT_SUCCESS; - if (!g_thread_supported ()) - g_thread_init (NULL); + g_type_init (); if (clutter_parse_args (argc, argv) == FALSE) return CLUTTER_INIT_ERROR_INTERNAL; @@ -582,22 +621,14 @@ clutter_init (int *argc, context = clutter_context_get_default (); stage_error = NULL; - if (!clutter_stage_init (context, &stage_error)) + if (!clutter_backend_init_stage (context->backend, &stage_error)) { g_critical (stage_error->message); g_error_free (stage_error); return CLUTTER_INIT_ERROR_INTERNAL; } -#if 0 - /* FIXME: move to backend */ - /* At least GL 1.2 is needed for CLAMP_TO_EDGE */ - if (!is_gl_version_at_least_12 ()) - { - g_critical ("Clutter needs at least version 1.2 of OpenGL"); - return CLUTTER_INIT_ERROR_OPENGL; - } -#endif + _clutter_events_init (context->backend); - return 1; + return CLUTTER_INIT_SUCCESS; } diff --git a/clutter/clutter-main.h b/clutter/clutter-main.h index 8ffc2fec9..003eecede 100644 --- a/clutter/clutter-main.h +++ b/clutter/clutter-main.h @@ -38,8 +38,7 @@ typedef enum { CLUTTER_INIT_ERROR_UNKOWN = 0, CLUTTER_INIT_ERROR_THREADS = -1, CLUTTER_INIT_ERROR_BACKEND = -2, - CLUTTER_INIT_ERROR_INTERNAL = -3, - CLUTTER_INIT_ERROR_OPENGL = -4 + CLUTTER_INIT_ERROR_INTERNAL = -3 } ClutterInitError; GQuark clutter_init_error_quark (void); @@ -58,9 +57,13 @@ GOptionGroup * clutter_get_option_group (void); void clutter_main (void); void clutter_main_quit (void); gint clutter_main_level (void); + void clutter_redraw (void); -gboolean clutter_want_debug (void); -gboolean clutter_want_fps (void); + +gboolean clutter_get_debug_enabled (void); +gboolean clutter_get_show_fps (void); +G_CONST_RETURN gchar *clutter_get_vblank_method (void); + void clutter_threads_enter (void); void clutter_threads_leave (void); diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index af6e86658..59eb36fe5 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -32,29 +32,32 @@ #include #include -#include /* Togo */ - #include #include +#include "clutter-event.h" +#include "clutter-backend.h" +#include "clutter-stage.h" + G_BEGIN_DECLS typedef struct _ClutterMainContext ClutterMainContext; struct _ClutterMainContext { + /* holds a pointer to the stage */ + ClutterBackend *backend; + PangoFT2FontMap *font_map; - GMutex *gl_lock; - guint update_idle; + GMutex *gl_lock; + guint update_idle; - guint main_loop_level; - GSList *main_loops; + guint main_loop_level; + GSList *main_loops; - ClutterStage *stage; - - guint is_initialized : 1; + guint is_initialized : 1; }; #define CLUTTER_CONTEXT() (clutter_context_get_default ()) @@ -81,6 +84,40 @@ typedef enum { #define CLUTTER_PARAM_READWRITE \ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |G_PARAM_STATIC_BLURB +GType _clutter_backend_impl_get_type (void); + +/* backend-specific private functions */ +void _clutter_events_init (ClutterBackend *backend); +void _clutter_events_uninit (ClutterBackend *backend); +void _clutter_events_queue (ClutterBackend *backend); +void _clutter_event_queue_push (ClutterBackend *backend, + ClutterEvent *event); +ClutterEvent *_clutter_event_queue_pop (ClutterBackend *backend); +ClutterEvent *_clutter_event_queue_peek (ClutterBackend *backend); +gboolean _clutter_event_queue_check_pending (ClutterBackend *backend); + +typedef void (* ClutterEventFunc) (ClutterEvent *event, + gpointer data); + +/* the event dispatcher function */ +extern ClutterEventFunc _clutter_event_func; +extern gpointer _clutter_event_data; +extern GDestroyNotify _clutter_event_destroy; + +void _clutter_set_events_handler (ClutterEventFunc func, + gpointer data, + GDestroyNotify destroy); + +void _clutter_event_button_generate (ClutterBackend *backend, + ClutterEvent *event); +void _clutter_synthetise_click (ClutterBackend *backend, + ClutterEvent *event, + gint n_clicks); +void _clutter_synthetise_stage_state (ClutterBackend *backend, + ClutterEvent *event, + ClutterStageState set_flags, + ClutterStageState unset_flags); + G_END_DECLS -#endif +#endif /* _HAVE_CLUTTER_PRIVATE_H */ diff --git a/clutter/clutter-stage-glx.c b/clutter/clutter-stage-glx.c deleted file mode 100644 index 1533f4309..000000000 --- a/clutter/clutter-stage-glx.c +++ /dev/null @@ -1,898 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Authored By Matthew Allum - * - * Copyright (C) 2006 OpenedHand - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:clutter-stage - * @short_description: Top level visual element to which actors are placed. - * - * #ClutterStage is a top level 'window' on which child actors are placed - * and manipulated. - */ - -#include "config.h" - -#include "clutter-stage.h" -#include "clutter-main.h" -#include "clutter-feature.h" -#include "clutter-color.h" -#include "clutter-util.h" -#include "clutter-marshal.h" -#include "clutter-enum-types.h" -#include "clutter-private.h" -#include "clutter-debug.h" - -#include "clutter-stage-glx.h" -#include "clutter-backend-glx.h" - -#include -#include - -#include - -struct _ClutterStageBackend -{ - XVisualInfo *xvisinfo; - Window xwin; - Pixmap xpixmap; - gint xwin_width, xwin_height; /* FIXME target_width / height */ - GLXPixmap glxpixmap; - GLXContext gl_context; - gboolean is_foreign_xwin; -}; - -typedef struct -{ - GSource source; - Display *display; - GPollFD event_poll_fd; -} -ClutterXEventSource; - -typedef void (*ClutterXEventFunc) (XEvent *xev, gpointer user_data); - -static gboolean -x_event_prepare (GSource *source, - gint *timeout) -{ - Display *display = ((ClutterXEventSource*)source)->display; - - *timeout = -1; - - return XPending (display); -} - -static gboolean -x_event_check (GSource *source) -{ - ClutterXEventSource *display_source = (ClutterXEventSource*)source; - gboolean retval; - - if (display_source->event_poll_fd.revents & G_IO_IN) - retval = XPending (display_source->display); - else - retval = FALSE; - - return retval; -} - -static gboolean -x_event_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - Display *display = ((ClutterXEventSource*)source)->display; - ClutterXEventFunc event_func = (ClutterXEventFunc) callback; - - XEvent xev; - - if (XPending (display)) - { - XNextEvent (display, &xev); - - if (event_func) - (*event_func) (&xev, user_data); - } - - return TRUE; -} - -static const GSourceFuncs x_event_funcs = { - x_event_prepare, - x_event_check, - x_event_dispatch, - NULL -}; - -static void -translate_key_event (ClutterKeyEvent *event, - XEvent *xevent) -{ - event->type = xevent->xany.type == KeyPress ? CLUTTER_KEY_PRESS - : CLUTTER_KEY_RELEASE; - event->time = xevent->xkey.time; - event->modifier_state = xevent->xkey.state; /* FIXME: handle modifiers */ - event->hardware_keycode = xevent->xkey.keycode; - event->keyval = XKeycodeToKeysym(xevent->xkey.display, - xevent->xkey.keycode, - 0 ); /* FIXME: index with modifiers */ -} - -static void -translate_button_event (ClutterButtonEvent *event, - XEvent *xevent) -{ - /* FIXME: catch double click */ - CLUTTER_NOTE (EVENT, " button event at %ix%i", - xevent->xbutton.x, - xevent->xbutton.y); - - event->type = xevent->xany.type == ButtonPress ? CLUTTER_BUTTON_PRESS - : CLUTTER_BUTTON_RELEASE; - event->time = xevent->xbutton.time; - event->x = xevent->xbutton.x; - event->y = xevent->xbutton.y; - event->modifier_state = xevent->xbutton.state; /* includes button masks */ - event->button = xevent->xbutton.button; -} - -static void -translate_motion_event (ClutterMotionEvent *event, - XEvent *xevent) -{ - event->type = CLUTTER_MOTION; - event->time = xevent->xbutton.time; - event->x = xevent->xmotion.x; - event->y = xevent->xmotion.y; - event->modifier_state = xevent->xmotion.state; -} - -static void -clutter_dispatch_x_event (XEvent *xevent, - gpointer data) -{ - ClutterMainContext *ctx = CLUTTER_CONTEXT (); - ClutterEvent event; - ClutterStage *stage = ctx->stage; - gboolean emit_input_event = FALSE; - - switch (xevent->type) - { - case Expose: - { - XEvent foo_xev; - - /* Cheap compress */ - while (XCheckTypedWindowEvent(clutter_glx_display(), - xevent->xexpose.window, - Expose, - &foo_xev)); - - /* FIXME: need to make stage an 'actor' so can que - * a paint direct from there rather than hack here... - */ - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - } - break; - case KeyPress: - translate_key_event ((ClutterKeyEvent *) &event, xevent); - g_signal_emit_by_name (stage, "key-press-event", &event); - emit_input_event = TRUE; - break; - case KeyRelease: - translate_key_event ((ClutterKeyEvent *) &event, xevent); - g_signal_emit_by_name (stage, "key-release-event", &event); - emit_input_event = TRUE; - break; - case ButtonPress: - translate_button_event ((ClutterButtonEvent *) &event, xevent); - g_signal_emit_by_name (stage, "button-press-event", &event); - emit_input_event = TRUE; - break; - case ButtonRelease: - translate_button_event ((ClutterButtonEvent *) &event, xevent); - g_signal_emit_by_name (stage, "button-release-event", &event); - emit_input_event = TRUE; - break; - case MotionNotify: - translate_motion_event ((ClutterMotionEvent *) &event, xevent); - g_signal_emit_by_name (stage, "motion-event", &event); - emit_input_event = TRUE; - break; - } - - if (emit_input_event) - g_signal_emit_by_name (stage, "input-event", &event); - -} - -static void -events_init() -{ - ClutterMainContext *clutter_context; - GMainContext *gmain_context; - int connection_number; - GSource *source; - ClutterXEventSource *display_source; - - clutter_context = clutter_context_get_default (); - gmain_context = g_main_context_default (); - - g_main_context_ref (gmain_context); - - connection_number = ConnectionNumber (clutter_glx_display()); - - source = g_source_new ((GSourceFuncs *)&x_event_funcs, - sizeof (ClutterXEventSource)); - - display_source = (ClutterXEventSource *)source; - - display_source->event_poll_fd.fd = connection_number; - display_source->event_poll_fd.events = G_IO_IN; - display_source->display = clutter_glx_display(); - - g_source_add_poll (source, &display_source->event_poll_fd); - g_source_set_can_recurse (source, TRUE); - - g_source_set_callback (source, - (GSourceFunc) clutter_dispatch_x_event, - NULL /* no userdata */, NULL); - - g_source_attach (source, gmain_context); - g_source_unref (source); -} - -static void -sync_fullscreen (ClutterStage *stage) -{ - Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN; - gboolean want_fullscreen; - - atom_WINDOW_STATE - = XInternAtom(clutter_glx_display(), "_NET_WM_STATE", False); - atom_WINDOW_STATE_FULLSCREEN - = XInternAtom(clutter_glx_display(), "_NET_WM_STATE_FULLSCREEN",False); - - g_object_get (stage, "fullscreen", &want_fullscreen, NULL); - - if (want_fullscreen) - { - clutter_actor_set_size (CLUTTER_ACTOR(stage), - DisplayWidth(clutter_glx_display(), - clutter_glx_screen()), - DisplayHeight(clutter_glx_display(), - clutter_glx_screen())); - - if (stage->backend->xwin != None) - XChangeProperty(clutter_glx_display(), stage->backend->xwin, - atom_WINDOW_STATE, XA_ATOM, 32, - PropModeReplace, - (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1); - } - else - { - if (stage->backend->xwin != None) - XDeleteProperty(clutter_glx_display(), - stage->backend->xwin, atom_WINDOW_STATE); - } -} - -static void -sync_cursor (ClutterStage *stage) -{ - gboolean hide_cursor; - - if (stage->backend->xwin == None) - return; - - g_object_get (stage, "hide-cursor", &hide_cursor, NULL); - - /* FIXME: Use XFixesHideCursor */ - - if (hide_cursor) - { - XColor col; - Pixmap pix; - Cursor curs; - - pix = XCreatePixmap (clutter_glx_display(), - stage->backend->xwin, 1, 1, 1); - memset (&col, 0, sizeof (col)); - curs = XCreatePixmapCursor (clutter_glx_display(), - pix, pix, &col, &col, 1, 1); - XFreePixmap (clutter_glx_display(), pix); - XDefineCursor(clutter_glx_display(), stage->backend->xwin, curs); - } - else - { - XUndefineCursor(clutter_glx_display(), stage->backend->xwin); - } -} - -/* FIXME -> CGL */ -static void -frustum (GLfloat left, - GLfloat right, - GLfloat bottom, - GLfloat top, - GLfloat nearval, - GLfloat farval) -{ - GLfloat x, y, a, b, c, d; - GLfloat m[16]; - - x = (2.0 * nearval) / (right - left); - y = (2.0 * nearval) / (top - bottom); - a = (right + left) / (right - left); - b = (top + bottom) / (top - bottom); - c = -(farval + nearval) / ( farval - nearval); - d = -(2.0 * farval * nearval) / (farval - nearval); - -#define M(row,col) m[col*4+row] - M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F; - M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F; - M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d; - M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F; -#undef M - - glMultMatrixf (m); -} - -static void -perspective (GLfloat fovy, - GLfloat aspect, - GLfloat zNear, - GLfloat zFar) -{ - GLfloat xmin, xmax, ymin, ymax; - - ymax = zNear * tan (fovy * M_PI / 360.0); - ymin = -ymax; - xmin = ymin * aspect; - xmax = ymax * aspect; - - frustum (xmin, xmax, ymin, ymax, zNear, zFar); -} - - -static void -sync_viewport (ClutterStage *stage) -{ - glViewport (0, 0, stage->backend->xwin_width, stage->backend->xwin_height); - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - perspective (60.0f, 1.0f, 0.1f, 100.0f); - glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); - - /* Then for 2D like transform */ - - /* camera distance from screen, 0.5 * tan (FOV) */ -#define DEFAULT_Z_CAMERA 0.866025404f - - glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA); - glScalef (1.0f / stage->backend->xwin_width, - -1.0f / stage->backend->xwin_height, - 1.0f / stage->backend->xwin_width); - glTranslatef (0.0f, -stage->backend->xwin_height, 0.0f); -} - -static void -clutter_stage_glx_show (ClutterActor *self) -{ - if (clutter_stage_glx_window (CLUTTER_STAGE(self))) - XMapWindow (clutter_glx_display(), - clutter_stage_glx_window (CLUTTER_STAGE(self))); -} - -static void -clutter_stage_glx_hide (ClutterActor *self) -{ - if (clutter_stage_glx_window (CLUTTER_STAGE(self))) - XUnmapWindow (clutter_glx_display(), - clutter_stage_glx_window (CLUTTER_STAGE(self))); -} - -static void -clutter_stage_glx_unrealize (ClutterActor *actor) -{ - ClutterStage *stage; - ClutterStagePrivate *priv; - ClutterStageBackend *backend; - gboolean want_offscreen; - - stage = CLUTTER_STAGE(actor); - priv = stage->priv; - backend = stage->backend; - - CLUTTER_MARK(); - - g_object_get (stage, "offscreen", &want_offscreen, NULL); - - if (want_offscreen) - { - if (backend->glxpixmap) - { - glXDestroyGLXPixmap (clutter_glx_display(), backend->glxpixmap); - backend->glxpixmap = None; - } - - if (backend->xpixmap) - { - XFreePixmap (clutter_glx_display(), backend->xpixmap); - backend->xpixmap = None; - } - } - else - { - if (!backend->is_foreign_xwin && backend->xwin != None) - { - XDestroyWindow (clutter_glx_display(), backend->xwin); - backend->xwin = None; - } - else - backend->xwin = None; - } - - glXMakeCurrent(clutter_glx_display(), None, NULL); - if (backend->gl_context != None) - { - glXDestroyContext (clutter_glx_display(), backend->gl_context); - backend->gl_context = None; - } -} - -static void -clutter_stage_glx_realize (ClutterActor *actor) -{ - ClutterStage *stage; - ClutterStagePrivate *priv; - ClutterStageBackend *backend; - gboolean want_offscreen; - - stage = CLUTTER_STAGE(actor); - - priv = stage->priv; - backend = stage->backend; - - CLUTTER_MARK(); - - g_object_get (stage, "offscreen", &want_offscreen, NULL); - - if (want_offscreen) - { - int gl_attributes[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - 0 - }; - - if (backend->xvisinfo) - XFree(backend->xvisinfo); - - backend->xvisinfo = glXChooseVisual (clutter_glx_display(), - clutter_glx_screen(), - gl_attributes); - if (!backend->xvisinfo) - { - g_critical ("Unable to find suitable GL visual."); - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); - return; - } - - if (backend->gl_context) - glXDestroyContext (clutter_glx_display(), backend->gl_context); - - backend->xpixmap = XCreatePixmap (clutter_glx_display(), - clutter_glx_root_window(), - backend->xwin_width, - backend->xwin_height, - backend->xvisinfo->depth); - - backend->glxpixmap = glXCreateGLXPixmap(clutter_glx_display(), - backend->xvisinfo, - backend->xpixmap); - sync_fullscreen (stage); - - /* indirect */ - backend->gl_context = glXCreateContext (clutter_glx_display(), - backend->xvisinfo, - 0, - False); - - glXMakeCurrent(clutter_glx_display(), - backend->glxpixmap, backend->gl_context); - -#if 0 - /* Debug code for monitoring a off screen pixmap via window */ - { - Colormap cmap; - XSetWindowAttributes swa; - - cmap = XCreateColormap(clutter_glx_display(), - clutter_glx_root_window(), - backend->xvisinfo->visual, AllocNone); - - /* create a window */ - swa.colormap = cmap; - - foo_win = XCreateWindow(clutter_glx_display(), - clutter_glx_root_window(), - 0, 0, - backend->xwin_width, backend->xwin_height, - 0, - backend->xvisinfo->depth, - InputOutput, - backend->xvisinfo->visual, - CWColormap, &swa); - - XMapWindow(clutter_glx_display(), foo_win); - } -#endif - } - else - { - int gl_attributes[] = - { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_STENCIL_SIZE, 1, - 0 - }; - - if (backend->xvisinfo) - XFree(backend->xvisinfo); - - if (backend->xvisinfo == None) - backend->xvisinfo = glXChooseVisual (clutter_glx_display(), - clutter_glx_screen(), - gl_attributes); - if (!backend->xvisinfo) - { - g_critical ("Unable to find suitable GL visual."); - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); - return; - } - - if (backend->xwin == None) - backend->xwin = XCreateSimpleWindow(clutter_glx_display(), - clutter_glx_root_window(), - 0, 0, - backend->xwin_width, backend->xwin_height, - 0, 0, - WhitePixel(clutter_glx_display(), - clutter_glx_screen())); - XSelectInput(clutter_glx_display(), - backend->xwin, - StructureNotifyMask - |ExposureMask - /* FIXME: we may want to eplicity enable MotionMask */ - |PointerMotionMask - |KeyPressMask - |KeyReleaseMask - |ButtonPressMask - |ButtonReleaseMask - |PropertyChangeMask); - - sync_fullscreen (stage); - sync_cursor (stage); - - if (backend->gl_context) - glXDestroyContext (clutter_glx_display(), backend->gl_context); - - backend->gl_context = glXCreateContext (clutter_glx_display(), - backend->xvisinfo, - 0, - True); - - if (backend->gl_context == None) - { - g_critical ("Unable to create suitable GL context."); - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); - return; - } - - glXMakeCurrent(clutter_glx_display(), backend->xwin, backend->gl_context); - } - - CLUTTER_NOTE (GL, - "\n" - "===========================================\n" - "GL_VENDOR: %s\n" - "GL_RENDERER: %s\n" - "GL_VERSION: %s\n" - "GL_EXTENSIONS: %s\n" - "Is direct: %s\n" - "===========================================\n", - glGetString (GL_VENDOR), - glGetString (GL_RENDERER), - glGetString (GL_VERSION), - glGetString (GL_EXTENSIONS), - glXIsDirect(clutter_glx_display(), backend->gl_context) ? "yes" : "no" - ); - - sync_viewport (stage); -} - -static void -clutter_stage_glx_paint (ClutterActor *self) -{ - ClutterStage *stage = CLUTTER_STAGE(self); - ClutterColor stage_color; - static GTimer *timer = NULL; - static guint timer_n_frames = 0; - - static ClutterActorClass *parent_class = NULL; - - CLUTTER_NOTE (PAINT, " Redraw enter"); - - if (parent_class == NULL) - parent_class = g_type_class_peek_parent (CLUTTER_STAGE_GET_CLASS(stage)); - - if (clutter_want_fps ()) - { - if (!timer) - timer = g_timer_new (); - } - - clutter_stage_get_color (stage, &stage_color); - - glClearColor(((float) stage_color.red / 0xff * 1.0), - ((float) stage_color.green / 0xff * 1.0), - ((float) stage_color.blue / 0xff * 1.0), - 0.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - - parent_class->paint (self); - - if (clutter_stage_glx_window (stage)) - { - clutter_feature_wait_for_vblank (); - glXSwapBuffers(clutter_glx_display(), clutter_stage_glx_window (stage)); - } - else - { - glXWaitGL(); - CLUTTER_GLERR(); - } - - if (clutter_want_fps ()) - { - timer_n_frames++; - - if (g_timer_elapsed (timer, NULL) >= 1.0) - { - g_print ("*** FPS: %i ***\n", timer_n_frames); - timer_n_frames = 0; - g_timer_start (timer); - } - } - - CLUTTER_NOTE (PAINT, " Redraw leave"); -} - -static void -clutter_stage_glx_allocate_coords (ClutterActor *self, - ClutterActorBox *box) -{ - /* Do nothing, just stop group_allocate getting called */ - - /* TODO: sync up with any configure events from WM ?? */ - return; -} - -static void -clutter_stage_glx_request_coords (ClutterActor *self, - ClutterActorBox *box) -{ - ClutterStage *stage; - ClutterStageBackend *backend; - gint new_width, new_height; - - stage = CLUTTER_STAGE (self); - backend = stage->backend; - - /* FIXME: some how have X configure_notfiys call this ? - */ - - new_width = ABS(box->x2 - box->x1); - new_height = ABS(box->y2 - box->y1); - - if (new_width != backend->xwin_width || new_height != backend->xwin_height) - { - backend->xwin_width = new_width; - backend->xwin_height = new_height; - - if (backend->xwin != None) - XResizeWindow (clutter_glx_display(), - backend->xwin, - backend->xwin_width, - backend->xwin_height); - - if (backend->xpixmap != None) - { - /* Need to recreate to resize */ - clutter_actor_unrealize(self); - clutter_actor_realize(self); - } - - sync_viewport (stage); - } - - if (backend->xwin != None) /* Do we want to bother ? */ - XMoveWindow (clutter_glx_display(), - backend->xwin, - box->x1, - box->y1); -} - -static void -clutter_stage_glx_dispose (GObject *object) -{ -#if 0 - ClutterStage *self = CLUTTER_STAGE (object); - - if (self->backend->xwin) - clutter_actor_unrealize (CLUTTER_ACTOR (self)); - - G_OBJECT_CLASS (clutter_stage_parent_class)->dispose (object); -#endif -} - -static void -clutter_stage_glx_finalize (GObject *object) -{ -#if 0 - G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object); -#endif -} - -void -clutter_stage_backend_init_vtable (ClutterStageVTable *vtable) -{ - vtable->show = clutter_stage_glx_show; - vtable->hide = clutter_stage_glx_hide; - vtable->realize = clutter_stage_glx_realize; - vtable->unrealize = clutter_stage_glx_unrealize; - vtable->paint = clutter_stage_glx_paint; - vtable->request_coords = clutter_stage_glx_request_coords; - vtable->allocate_coords = clutter_stage_glx_allocate_coords; - - vtable->sync_fullscreen = sync_fullscreen; - vtable->sync_cursor = sync_cursor; - vtable->sync_viewport = sync_viewport; - -} - -ClutterStageBackend* -clutter_stage_backend_init (ClutterStage *stage) -{ - ClutterStageBackend *backend; - - backend = g_new0(ClutterStageBackend, 1); - - backend->xwin_width = 100; - backend->xwin_height = 100; - - /* Maybe better somewhere else */ - events_init (); - - return backend; -} - -/** - * clutter_stage_glx_get_xwindow - * @stage: A #ClutterStage - * - * Get the stage's underlying x window ID. - * - * Return Value: Stage X Window XID - * - * Since: 0.3 - **/ -Window -clutter_stage_glx_window (ClutterStage *stage) -{ - return stage->backend->xwin; -} - -/** - * clutter_stage_set_xwindow_foreign - * @stage: A #ClutterStage - * @xid: A preexisting X Window ID - * - * Target the #ClutterStage to use an existing external X Window. - * - * Return Value: TRUE if foreign window valid, FALSE otherwise - * - * Since: 0.3 - **/ -gboolean -clutter_stage_glx_set_window_foreign (ClutterStage *stage, - Window xid) -{ - /* For screensavers via XSCREENSAVER_WINDOW env var. - * Also for toolkit binding. - */ - gint x,y; - guint width, height, border, depth; - Window root_return; - Status status; - ClutterGeometry geom; - - clutter_glx_trap_x_errors(); - - status = XGetGeometry (clutter_glx_display(), - xid, - &root_return, - &x, - &y, - &width, - &height, - &border, - &depth); - - if (clutter_glx_untrap_x_errors() || !status - || width == 0 || height == 0 || depth != stage->backend->xvisinfo->depth) - return FALSE; - - clutter_actor_unrealize (CLUTTER_ACTOR(stage)); - - stage->backend->xwin = xid; - - geom.x = x; - geom.y = y; - - geom.width = stage->backend->xwin_width = width; - geom.height = stage->backend->xwin_height = height; - - clutter_actor_set_geometry (CLUTTER_ACTOR(stage), &geom); - - clutter_actor_realize (CLUTTER_ACTOR(stage)); - - return TRUE; -} - -/** - * clutter_stage_glx_get_xvisual - * @stage: A #ClutterStage - * - * Get the stage's XVisualInfo. - * - * Return Value: The stage's XVisualInfo - * - * Since: 0.3 - **/ -const XVisualInfo* -clutter_stage_glx_get_visual (ClutterStage *stage) -{ - return stage->backend->xvisinfo; -} diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 7dc3a85ca..52d20dc0f 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -33,6 +33,7 @@ #include "config.h" +#include "clutter-backend.h" #include "clutter-stage.h" #include "clutter-main.h" #include "clutter-color.h" @@ -43,34 +44,20 @@ #include "clutter-debug.h" #include "clutter-version.h" /* For flavour */ -#ifdef CLUTTER_FLAVOUR_GLX -#include -#endif - -#ifdef CLUTTER_FLAVOUR_EGL -#include -#endif - #include -/* the stage is a singleton instance */ -static ClutterStage *stage_singleton = NULL; - -/* Backend hooks */ -static ClutterStageVTable _vtable; - -G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP); +G_DEFINE_ABSTRACT_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP); #define CLUTTER_STAGE_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_STAGE, ClutterStagePrivate)) struct _ClutterStagePrivate { - ClutterColor color; - - guint want_fullscreen : 1; - guint want_offscreen : 1; - guint hide_cursor : 1; + ClutterColor color; + + guint is_fullscreen : 1; + guint is_offscreen : 1; + guint is_cursor_visible : 1; }; enum @@ -80,7 +67,7 @@ enum PROP_COLOR, PROP_FULLSCREEN, PROP_OFFSCREEN, - PROP_HIDE_CURSOR + PROP_CURSOR_VISIBLE }; enum @@ -88,16 +75,26 @@ enum INPUT_EVENT, BUTTON_PRESS_EVENT, BUTTON_RELEASE_EVENT, + SCROLL_EVENT, KEY_PRESS_EVENT, KEY_RELEASE_EVENT, MOTION_EVENT, + STAGE_STATE_EVENT, + DELETE_EVENT, LAST_SIGNAL }; static guint stage_signals[LAST_SIGNAL] = { 0 }; -static ClutterActorClass *parent_class = NULL; +static void +clutter_stage_delete_event (ClutterStage *stage) +{ + /* FIXME - destroy the main stage, probably attaching a weak ref + * to it from the backend, so that it gets destroyed too. + */ + CLUTTER_NOTE (EVENT, "Received a destroy notification"); +} static void clutter_stage_set_property (GObject *object, @@ -105,10 +102,12 @@ clutter_stage_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - ClutterStage *stage; + ClutterStage *stage; ClutterStagePrivate *priv; + ClutterActor *actor; - stage = CLUTTER_STAGE(object); + stage = CLUTTER_STAGE (object); + actor = CLUTTER_ACTOR (stage); priv = stage->priv; switch (prop_id) @@ -117,32 +116,26 @@ clutter_stage_set_property (GObject *object, clutter_stage_set_color (stage, g_value_get_boxed (value)); break; case PROP_OFFSCREEN: - if (priv->want_offscreen != g_value_get_boolean (value)) - { - clutter_actor_unrealize (CLUTTER_ACTOR(stage)); - /* NOTE: as we are changing GL contexts here. so - * all textures will need unreleasing as they will - * likely have set up ( i.e labels ) in the old - * context. We should probably somehow do this - * automatically - */ - priv->want_offscreen = g_value_get_boolean (value); - clutter_actor_realize (CLUTTER_ACTOR(stage)); - } + if (CLUTTER_ACTOR_IS_REALIZED (actor)) + { + clutter_actor_unrealize (actor); + priv->is_offscreen = g_value_get_boolean (value); + clutter_actor_realize (actor); + } + else + priv->is_offscreen = g_value_get_boolean (value); break; case PROP_FULLSCREEN: - if (priv->want_fullscreen != g_value_get_boolean (value)) - { - priv->want_fullscreen = g_value_get_boolean (value); - _vtable.sync_fullscreen (stage); - } + if (g_value_get_boolean (value)) + clutter_stage_fullscreen (stage); + else + clutter_stage_unfullscreen (stage); break; - case PROP_HIDE_CURSOR: - if (priv->hide_cursor != g_value_get_boolean (value)) - { - priv->hide_cursor = g_value_get_boolean (value); - _vtable.sync_cursor (stage); - } + case PROP_CURSOR_VISIBLE: + if (g_value_get_boolean (value)) + clutter_stage_show_cursor (stage); + else + clutter_stage_hide_cursor (stage); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -170,13 +163,13 @@ clutter_stage_get_property (GObject *object, g_value_set_boxed (value, &color); break; case PROP_OFFSCREEN: - g_value_set_boolean (value, priv->want_offscreen); + g_value_set_boolean (value, priv->is_offscreen); break; case PROP_FULLSCREEN: - g_value_set_boolean (value, priv->want_fullscreen); + g_value_set_boolean (value, priv->is_fullscreen); break; - case PROP_HIDE_CURSOR: - g_value_set_boolean (value, priv->hide_cursor); + case PROP_CURSOR_VISIBLE: + g_value_set_boolean (value, priv->is_cursor_visible); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -187,30 +180,14 @@ clutter_stage_get_property (GObject *object, static void clutter_stage_class_init (ClutterStageClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - clutter_stage_backend_init_vtable (&_vtable); - - actor_class->realize = _vtable.realize; - actor_class->unrealize = _vtable.unrealize; - actor_class->show = _vtable.show; - actor_class->hide = _vtable.hide; - actor_class->paint = _vtable.paint; - - actor_class->request_coords = _vtable.request_coords; - actor_class->allocate_coords = _vtable.allocate_coords; - - /* - gobject_class->dispose = _vtable.stage_dispose; - gobject_class->finalize = _vtable.stage_finalize; - */ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass); gobject_class->set_property = clutter_stage_set_property; gobject_class->get_property = clutter_stage_get_property; - + + stage_class->delete_event = clutter_stage_delete_event; + /** * ClutterStage:fullscreen * @@ -220,7 +197,7 @@ clutter_stage_class_init (ClutterStageClass *klass) (gobject_class, PROP_FULLSCREEN, g_param_spec_boolean ("fullscreen", "Fullscreen", - "Make Clutter stage fullscreen", + "Whether the main stage is fullscreen", FALSE, G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE)); @@ -228,16 +205,16 @@ clutter_stage_class_init (ClutterStageClass *klass) (gobject_class, PROP_OFFSCREEN, g_param_spec_boolean ("offscreen", "Offscreen", - "Make Clutter stage offscreen", + "Whether the main stage is renderer offscreen", FALSE, G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE)); g_object_class_install_property - (gobject_class, PROP_HIDE_CURSOR, - g_param_spec_boolean ("hide-cursor", - "Hide Cursor", - "Make Clutter stage cursor-less", + (gobject_class, PROP_CURSOR_VISIBLE, + g_param_spec_boolean ("cursor-visible", + "Cursor Visible", + "Whether the mouse pointer is visible on the main stage ", FALSE, G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE)); @@ -245,7 +222,7 @@ clutter_stage_class_init (ClutterStageClass *klass) (gobject_class, PROP_COLOR, g_param_spec_boxed ("color", "Color", - "The color of the stage", + "The color of the main stage", CLUTTER_TYPE_COLOR, CLUTTER_PARAM_READWRITE)); @@ -272,7 +249,7 @@ clutter_stage_class_init (ClutterStageClass *klass) * @stage: the actor which received the event * @event: a #ClutterButtonEvent * - * The ::button-press-event is emitted each time a mouse button + * The ::button-press-event signal is emitted each time a mouse button * is pressed on @stage. */ stage_signals[BUTTON_PRESS_EVENT] = @@ -289,7 +266,7 @@ clutter_stage_class_init (ClutterStageClass *klass) * @stage: the actor which received the event * @event: a #ClutterButtonEvent * - * The ::button-release-event is emitted each time a mouse button + * The ::button-release-event signal is emitted each time a mouse button * is released on @stage. */ stage_signals[BUTTON_RELEASE_EVENT] = @@ -301,12 +278,31 @@ clutter_stage_class_init (ClutterStageClass *klass) clutter_marshal_VOID__BOXED, G_TYPE_NONE, 1, CLUTTER_TYPE_EVENT); + /** + * ClutterStage::scroll-event: + * @stage: the actor which received the event + * @event: a #ClutterScrollEvent + * + * The ::scroll-event signal is emitted each time a the mouse is + * scrolled on @stage + * + * Since: 0.4 + */ + stage_signals[SCROLL_EVENT] = + g_signal_new ("scroll-event", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStageClass, scroll_event), + NULL, NULL, + clutter_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + CLUTTER_TYPE_EVENT); /** * ClutterStage::key-press-event: * @stage: the actor which received the event * @event: a #ClutterKeyEvent * - * The ::key-press-event is emitted each time a keyboard button + * The ::key-press-event signal is emitted each time a keyboard button * is pressed on @stage. */ stage_signals[KEY_PRESS_EVENT] = @@ -323,7 +319,7 @@ clutter_stage_class_init (ClutterStageClass *klass) * @stage: the actor which received the event * @event: a #ClutterKeyEvent * - * The ::key-release-event is emitted each time a keyboard button + * The ::key-release-event signal is emitted each time a keyboard button * is released on @stage. */ stage_signals[KEY_RELEASE_EVENT] = @@ -340,7 +336,7 @@ clutter_stage_class_init (ClutterStageClass *klass) * @stage: the actor which received the event * @event: a #ClutterMotionEvent * - * The ::motion-event is emitted each time the mouse pointer is + * The ::motion-event signal is emitted each time the mouse pointer is * moved on @stage. */ stage_signals[MOTION_EVENT] = @@ -353,6 +349,15 @@ clutter_stage_class_init (ClutterStageClass *klass) G_TYPE_NONE, 1, CLUTTER_TYPE_EVENT); + stage_signals[DELETE_EVENT] = + g_signal_new ("delete-event", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStageClass, delete_event), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + g_type_class_add_private (gobject_class, sizeof (ClutterStagePrivate)); } @@ -366,11 +371,9 @@ clutter_stage_init (ClutterStage *self) self->priv = priv = CLUTTER_STAGE_GET_PRIVATE (self); - self->backend = clutter_stage_backend_init (self); - - priv->want_offscreen = FALSE; - priv->want_fullscreen = FALSE; - priv->hide_cursor = FALSE; + priv->is_offscreen = FALSE; + priv->is_fullscreen = FALSE; + priv->is_cursor_visible = FALSE; priv->color.red = 0xff; priv->color.green = 0xff; @@ -387,39 +390,20 @@ clutter_stage_init (ClutterStage *self) * the stage will be created the first time this function is * called (typically, inside clutter_init()); all the subsequent * calls to clutter_stage_get_default() will return the same - * instance, with its reference count increased. + * instance. * * Return value: the main #ClutterStage. You should never - * destroy the returned actor. + * destroy or unref the returned actor. */ ClutterActor * clutter_stage_get_default (void) { - ClutterActor *retval = NULL; - - if (!stage_singleton) - { - stage_singleton = g_object_new (CLUTTER_TYPE_STAGE, NULL); - - retval = CLUTTER_ACTOR (stage_singleton); - } - else - { - retval = CLUTTER_ACTOR (stage_singleton); + ClutterMainContext *context; - /* We dont ref for now as its assumed there will always be - * a stage and no real support for multiple stages. Non - * reffing makes API slightly simpler and allows for things - * like CLUTTER_STAGE_WIDTH() work nicely. - * - * In future if multiple stage support is added probably - * add a clutter-stage-manager class that would manage - * multiple instances. - * g_object_ref (retval); - */ - } + context = clutter_context_get_default (); + g_assert (context != NULL); - return retval; + return clutter_backend_get_stage (context->backend); } /** @@ -474,14 +458,129 @@ clutter_stage_get_color (ClutterStage *stage, color->alpha = priv->color.alpha; } -#if 0 -static void -snapshot_pixbuf_free (guchar *pixels, - gpointer data) +/** + * clutter_stage_fullscreen: + * @stage: a #ClutterStage + * + * Asks to place the stage window in the fullscreen state. Note that you + * shouldn't assume the window is definitely full screen afterward, because + * other entities (e.g. the user or window manager) could unfullscreen it + * again, and not all window managers honor requests to fullscreen windows. + */ +void +clutter_stage_fullscreen (ClutterStage *stage) { - g_free(pixels); + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + if (!priv->is_fullscreen) + { + priv->is_fullscreen = TRUE; + + if (CLUTTER_STAGE_GET_CLASS (stage)->set_fullscreen) + CLUTTER_STAGE_GET_CLASS (stage)->set_fullscreen (stage, TRUE); + + g_object_notify (G_OBJECT (stage), "fullscreen"); + } +} + +/** + * clutter_stage_unfullscreen: + * @stage: a #ClutterStage + * + * Asks to toggle off the fullscreen state for the stage window. Note that + * you shouldn't assume the window is definitely not full screen afterward, + * because other entities (e.g. the user or window manager) could fullscreen + * it again, and not all window managers honor requests to unfullscreen + * windows. + */ +void +clutter_stage_unfullscreen (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + if (priv->is_fullscreen) + { + priv->is_fullscreen = FALSE; + + if (CLUTTER_STAGE_GET_CLASS (stage)->set_fullscreen) + CLUTTER_STAGE_GET_CLASS (stage)->set_fullscreen (stage, FALSE); + + g_object_notify (G_OBJECT (stage), "fullscreen"); + } +} + +/** + * clutter_stage_show_cursor: + * @stage: a #ClutterStage + * + * Shows the cursor on the stage window + */ +void +clutter_stage_show_cursor (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + if (!priv->is_cursor_visible) + { + priv->is_cursor_visible = TRUE; + + if (CLUTTER_STAGE_GET_CLASS (stage)->set_cursor_visible) + CLUTTER_STAGE_GET_CLASS (stage)->set_cursor_visible (stage, TRUE); + + g_object_notify (G_OBJECT (stage), "cursor-visible"); + } +} + +/** + * clutter_stage_hide_cursor: + * @stage: + * + * Hides the cursor as invisible on the stage window + */ +void +clutter_stage_hide_cursor (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + if (priv->is_cursor_visible) + { + priv->is_cursor_visible = FALSE; + + if (CLUTTER_STAGE_GET_CLASS (stage)->set_cursor_visible) + CLUTTER_STAGE_GET_CLASS (stage)->set_cursor_visible (stage, FALSE); + + g_object_notify (G_OBJECT (stage), "cursor-visible"); + } +} + +/** + * clutter_stage_flush: + * @stage: a #ClutterStage + * + * Flushes the stage. This function is only useful for stage + * implementations inside backends or for actors; you should never + * need to call this function directly. + */ +void +clutter_stage_flush (ClutterStage *stage) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + if (CLUTTER_STAGE_GET_CLASS (stage)->flush) + CLUTTER_STAGE_GET_CLASS (stage)->flush (stage); } -#endif /** * clutter_stage_snapshot @@ -497,183 +596,42 @@ snapshot_pixbuf_free (guchar *pixels, * * Return value: pixel representation as a #GdkPixbuf **/ -GdkPixbuf* +GdkPixbuf * clutter_stage_snapshot (ClutterStage *stage, gint x, gint y, gint width, gint height) { -#if 0 - guchar *data; - GdkPixbuf *pixb, *fpixb; - ClutterActor *actor; - ClutterStagePrivate *priv; + ClutterStageClass *klass; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); g_return_val_if_fail (x >= 0 && y >= 0, NULL); - priv = stage->priv; - - actor = CLUTTER_ACTOR (stage); - - if (width < 0) - width = clutter_actor_get_width (actor); - - if (height < 0) - height = clutter_actor_get_height (actor); - - - if (priv->want_offscreen) + klass = CLUTTER_STAGE_GET_CLASS (stage); + if (klass->draw_to_pixbuf) { - gdk_pixbuf_xlib_init (clutter_xdisplay(), clutter_xscreen()); + GdkPixbuf *retval = NULL; - pixb = gdk_pixbuf_xlib_get_from_drawable - (NULL, - (Drawable)priv->xpixmap, - DefaultColormap(clutter_xdisplay(), - clutter_xscreen()), - priv->xvisinfo->visual, - x, y, 0, 0, width, height); - return pixb; - } - else - { - data = g_malloc0 (sizeof (guchar) * width * height * 4); - - glReadPixels (x, - clutter_actor_get_height (actor) - - y - height, - width, - height, GL_RGBA, GL_UNSIGNED_BYTE, data); + klass->draw_to_pixbuf (stage, retval, x, y, width, height); - pixb = gdk_pixbuf_new_from_data (data, - GDK_COLORSPACE_RGB, - TRUE, - 8, - width, - height, - width * 4, - snapshot_pixbuf_free, - NULL); - - fpixb = gdk_pixbuf_flip (pixb, TRUE); - - g_object_unref (pixb); - - return fpixb; + return retval; } -#endif - return 0; + + return NULL; } -/* FIXME -> CGL */ -static void -frustum (GLfloat left, - GLfloat right, - GLfloat bottom, - GLfloat top, - GLfloat nearval, - GLfloat farval) -{ - GLfloat x, y, a, b, c, d; - GLfloat m[16]; - - x = (2.0 * nearval) / (right - left); - y = (2.0 * nearval) / (top - bottom); - a = (right + left) / (right - left); - b = (top + bottom) / (top - bottom); - c = -(farval + nearval) / ( farval - nearval); - d = -(2.0 * farval * nearval) / (farval - nearval); - -#define M(row,col) m[col*4+row] - M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F; - M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F; - M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d; - M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F; -#undef M - - glMultMatrixf (m); -} - -static void -perspective (GLfloat fovy, - GLfloat aspect, - GLfloat zNear, - GLfloat zFar) -{ - GLfloat xmin, xmax, ymin, ymax; - - ymax = zNear * tan (fovy * M_PI / 360.0); - ymin = -ymax; - xmin = ymin * aspect; - xmax = ymax * aspect; - - frustum (xmin, xmax, ymin, ymax, zNear, zFar); -} - - -/** - * clutter_stage_get_actor_at_pos: - * @stage: a #ClutterStage - * @x: the x coordinate - * @y: the y coordinate - * - * If found, retrieves the actor that the (x, y) coordinates. - * - * Return value: the #ClutterActor at the desired coordinates, - * or %NULL if no actor was found. - */ -ClutterActor* +ClutterActor * clutter_stage_get_actor_at_pos (ClutterStage *stage, - gint x, - gint y) + gint x, + gint y) { - ClutterActor *found = NULL; - GLuint buff[64] = {0}; - GLint hits, view[4]; - - glSelectBuffer(64, buff); - glGetIntegerv(GL_VIEWPORT, view); - glRenderMode(GL_SELECT); + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); - glInitNames(); - - glPushName(0); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - /* This is gluPickMatrix(x, y, 1.0, 1.0, view); */ - glTranslatef((view[2] - 2 * (x - view[0])), - (view[3] - 2 * (y - view[1])), 0); - glScalef(view[2], -view[3], 1.0); - - perspective (60.0f, 1.0f, 0.1f, 100.0f); - - glMatrixMode(GL_MODELVIEW); - - clutter_actor_paint (CLUTTER_ACTOR (stage)); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - hits = glRenderMode(GL_RENDER); - - if (hits != 0) + if (CLUTTER_STAGE_GET_CLASS (stage)->get_actor_at_pos) { -#if 0 - gint i - for (i = 0; i < hits; i++) - g_print ("Hit at %i\n", buff[i * 4 + 3]); -#endif - - found = clutter_group_find_child_by_id (CLUTTER_GROUP (stage), - buff[(hits-1) * 4 + 3]); + return CLUTTER_STAGE_GET_CLASS (stage)->get_actor_at_pos (stage, x, y); } - - _vtable.sync_viewport (stage); - return found; + return NULL; } diff --git a/clutter/clutter-stage.h b/clutter/clutter-stage.h index 6eed1ea53..7dd68a617 100644 --- a/clutter/clutter-stage.h +++ b/clutter/clutter-stage.h @@ -23,28 +23,18 @@ * Boston, MA 02111-1307, USA. */ -#ifndef _HAVE_CLUTTER_STAGE_H -#define _HAVE_CLUTTER_STAGE_H - -#include +#ifndef __CLUTTER_STAGE_H__ +#define __CLUTTER_STAGE_H__ #include #include #include - #include G_BEGIN_DECLS #define CLUTTER_TYPE_STAGE (clutter_stage_get_type()) -#define CLUTTER_STAGE_WIDTH() \ - clutter_actor_get_width(CLUTTER_ACTOR(clutter_stage_get_default())) - -#define CLUTTER_STAGE_HEIGHT() \ - clutter_actor_get_height(CLUTTER_ACTOR(clutter_stage_get_default())) - - #define CLUTTER_STAGE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ CLUTTER_TYPE_STAGE, ClutterStage)) @@ -65,17 +55,19 @@ G_BEGIN_DECLS (G_TYPE_INSTANCE_GET_CLASS ((obj), \ CLUTTER_TYPE_STAGE, ClutterStageClass)) -typedef struct _ClutterStagePrivate ClutterStagePrivate; +#define CLUTTER_STAGE_WIDTH() \ + clutter_actor_get_width (clutter_stage_get_default ()) + +#define CLUTTER_STAGE_HEIGHT() \ + clutter_actor_get_height (clutter_stage_get_default ()) + typedef struct _ClutterStage ClutterStage; typedef struct _ClutterStageClass ClutterStageClass; -typedef struct _ClutterStageBackend ClutterStageBackend; -typedef struct _ClutterStageVTable ClutterStageVTable; - +typedef struct _ClutterStagePrivate ClutterStagePrivate; struct _ClutterStage { - ClutterGroup parent; - ClutterStageBackend *backend; + ClutterGroup parent_instance; /*< private >*/ ClutterStagePrivate *priv; @@ -85,18 +77,42 @@ struct _ClutterStageClass { ClutterGroupClass parent_class; - void (*input_event) (ClutterStage *stage, - ClutterEvent *event); - void (*button_press_event) (ClutterStage *stage, - ClutterButtonEvent *event); - void (*button_release_event) (ClutterStage *stage, - ClutterButtonEvent *event); - void (*key_press_event) (ClutterStage *stage, - ClutterKeyEvent *event); - void (*key_release_event) (ClutterStage *stage, - ClutterKeyEvent *event); - void (*motion_event) (ClutterStage *stage, - ClutterMotionEvent *event); + /* vfuncs, not signals */ + void (* set_fullscreen) (ClutterStage *stage, + gboolean fullscreen); + void (* set_cursor_visible) (ClutterStage *stage, + gboolean visible); + void (* set_offscreen) (ClutterStage *stage, + gboolean offscreen); + ClutterActor *(* get_actor_at_pos) (ClutterStage *stage, + gint x, + gint y); + void (* draw_to_pixbuf) (ClutterStage *stage, + GdkPixbuf *dest, + gint x, + gint y, + gint width, + gint height); + void (* flush) (ClutterStage *stage); + + /* signals */ + void (* input_event) (ClutterStage *stage, + ClutterEvent *event); + void (* button_press_event) (ClutterStage *stage, + ClutterButtonEvent *event); + void (* button_release_event) (ClutterStage *stage, + ClutterButtonEvent *event); + void (* scroll_event) (ClutterStage *stage, + ClutterScrollEvent *event); + void (* key_press_event) (ClutterStage *stage, + ClutterKeyEvent *event); + void (* key_release_event) (ClutterStage *stage, + ClutterKeyEvent *event); + void (* motion_event) (ClutterStage *stage, + ClutterMotionEvent *event); + void (* stage_state_event) (ClutterStage *stage, + ClutterStageStateEvent *event); + void (* delete_event) (ClutterStage *stage); /* padding for future expansion */ void (*_clutter_stage1) (void); @@ -105,42 +121,31 @@ struct _ClutterStageClass void (*_clutter_stage4) (void); void (*_clutter_stage5) (void); void (*_clutter_stage6) (void); -}; - -struct _ClutterStageVTable -{ - void (* show) (ClutterActor *actor); - void (* hide) (ClutterActor *actor); - void (* realize) (ClutterActor *actor); - void (* unrealize) (ClutterActor *actor); - void (* paint) (ClutterActor *actor); - void (* request_coords) (ClutterActor *actor, - ClutterActorBox *box); - void (* allocate_coords) (ClutterActor *actor, - ClutterActorBox *box); - - void (* sync_fullscreen) (ClutterStage *stage); - void (* sync_cursor) (ClutterStage *stage); - void (* sync_viewport) (ClutterStage *stage); - }; +GType clutter_stage_get_type (void) G_GNUC_CONST; -GType clutter_stage_get_type (void) G_GNUC_CONST; -ClutterActor *clutter_stage_get_default (void); -void clutter_stage_set_color (ClutterStage *stage, - const ClutterColor *color); -void clutter_stage_get_color (ClutterStage *stage, - ClutterColor *color); -ClutterActor *clutter_stage_get_actor_at_pos (ClutterStage *stage, - gint x, - gint y); -GdkPixbuf * clutter_stage_snapshot (ClutterStage *stage, - gint x, - gint y, - gint width, - gint height); +ClutterActor *clutter_stage_get_default (void); + +void clutter_stage_set_color (ClutterStage *stage, + const ClutterColor *color); +void clutter_stage_get_color (ClutterStage *stage, + ClutterColor *color); +void clutter_stage_fullscreen (ClutterStage *stage); +void clutter_stage_unfullscreen (ClutterStage *stage); +void clutter_stage_show_cursor (ClutterStage *stage); +void clutter_stage_hide_cursor (ClutterStage *stage); + +ClutterActor *clutter_stage_get_actor_at_pos (ClutterStage *stage, + gint x, + gint y); +GdkPixbuf * clutter_stage_snapshot (ClutterStage *stage, + gint x, + gint y, + gint width, + gint height); +void clutter_stage_flush (ClutterStage *stage); G_END_DECLS -#endif +#endif /* __CLUTTER_STAGE_H__ */ diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index 993597ff0..42c503883 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -46,7 +46,6 @@ #include "clutter-private.h" #include "clutter-debug.h" -#include #include G_DEFINE_TYPE (ClutterTexture, clutter_texture, CLUTTER_TYPE_ACTOR); diff --git a/clutter/clutter-version.h.in b/clutter/clutter-version.h.in index 9eba853aa..24237ca43 100644 --- a/clutter/clutter-version.h.in +++ b/clutter/clutter-version.h.in @@ -41,6 +41,6 @@ (CLUTTER_MAJOR_VERSION == (major) && CLUTTER_MINOR_VERSION > (minor)) || \ (CLUTTER_MAJOR_VERSION == (major) && CLUTTER_MINOR_VERSION == (minor) && CLUTTER_MICRO_VERSION > (micro))) -#define @CLUTTER_FLAVOUR_DEFINE@ +#define CLUTTER_FLAVOUR "@CLUTTER_FLAVOUR@" #endif /* __CLUTTER_VERSION_H__ */ diff --git a/clutter/egl/Makefile.am b/clutter/egl/Makefile.am new file mode 100644 index 000000000..547911fee --- /dev/null +++ b/clutter/egl/Makefile.am @@ -0,0 +1,19 @@ +libclutterincludedir = $(includedir)/clutter-@CLUTTER_MAJORMINOR@/clutter + +INCLUDES = \ + -DG_LOG_DOMAIN=\"ClutterEGL\" \ + -I$(top_srcdir) \ + $(CLUTTER_CFLAGS) \ + $(CLUTTER_DEBUG_CFLAGS) \ + $(GCC_FLAGS) + +LDADD = $(CLUTTER_LIBS) + +noinst_LTLIBRARIES = libclutter-egl.la + +libclutter_egl_la_SOURCES = \ + clutter-backend-egl.h \ + clutter-backend-egl.c \ + clutter-event-egl.c \ + clutter-stage-egl.h \ + clutter-stage-egl.c diff --git a/clutter/egl/clutter-backend-egl.c b/clutter/egl/clutter-backend-egl.c new file mode 100644 index 000000000..4398da0a0 --- /dev/null +++ b/clutter/egl/clutter-backend-egl.c @@ -0,0 +1,75 @@ +#include "config.h" + +#include "clutter-backend-egl.h" +#include "clutter-stage-egl.h" +#include "../clutter-private.h" +#include "../clutter-main.h" + +static ClutterBackendEgl *backend_singleton = NULL; + +G_DEFINE_TYPE (ClutterBackendEgl, clutter_backend_egl, CLUTTER_TYPE_BACKEND); + +static gboolean +clutter_backend_egl_pre_parse (ClutterBackend *backend, + GError **error) +{ + return TRUE; +} + +static gboolean +clutter_backend_egl_post_parse (ClutterBackend *backend, + GError **error) +{ + return TRUE; +} + +static gboolean +clutter_backend_egl_init_stage (ClutterBackend *backend, + GError **error) +{ + return TRUE; +} + +static void +clutter_backend_egl_init_events (ClutterBackend *backend) +{ + +} + +static void +clutter_backend_egl_add_options (ClutterBackend *backend, + GOptionGroup *group) +{ + +} + +static ClutterActor * +clutter_backend_egl_get_stage (ClutterBackend *backend) +{ + return NULL; +} + +static void +clutter_backend_egl_class_init (ClutterBackendEglClass *klass) +{ + ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); + + backend_class->pre_parse = clutter_backend_egl_pre_parse; + backend_class->post_parse = clutter_backend_egl_post_parse; + backend_class->init_stage = clutter_backend_egl_init_stage; + backend_class->init_events = clutter_backend_egl_init_events; + backend_class->get_stage = clutter_backend_egl_get_stage; + backend_class->add_options = clutter_backend_egl_add_options; +} + +static void +clutter_backend_egl_init (ClutterBackendEgl *backend) +{ + +} + +GType +_clutter_backend_impl_get_type (void) +{ + return clutter_backend_egl_get_type (); +} diff --git a/clutter/egl/clutter-backend-egl.h b/clutter/egl/clutter-backend-egl.h new file mode 100644 index 000000000..e4d501562 --- /dev/null +++ b/clutter/egl/clutter-backend-egl.h @@ -0,0 +1,56 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_BACKEND_EGL_H__ +#define __CLUTTER_BACKEND_EGL_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_EGL (clutter_backend_egl_get_type ()) +#define CLUTTER_BACKEND_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEgl)) +#define CLUTTER_IS_BACKEND_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_EGL)) +#define CLUTTER_BACKEND_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEglClass)) +#define CLUTTER_IS_BACKEND_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_EGL)) +#define CLUTTER_BACKEND_EGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEglClass)) + +typedef struct _ClutterBackendEgl ClutterBackendEgl; +typedef struct _ClutterBackendEglClass ClutterBackendEglClass; + +struct _ClutterBackendEgl +{ + ClutterBackend parent_instance; + + /*< private >*/ +}; + +struct _ClutterBackendEglClass +{ + ClutterBackendClass parent_class; +}; + +GType clutter_backend_egl_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_EGL_H__ */ diff --git a/clutter/egl/clutter-event-egl.c b/clutter/egl/clutter-event-egl.c new file mode 100644 index 000000000..e69de29bb diff --git a/clutter/egl/clutter-stage-egl.c b/clutter/egl/clutter-stage-egl.c new file mode 100644 index 000000000..b6ce84442 --- /dev/null +++ b/clutter/egl/clutter-stage-egl.c @@ -0,0 +1,19 @@ +#include "config.h" + +#include "clutter-stage-egl.h" +#include "../clutter-private.h" +#include "../clutter-event.h" + +G_DEFINE_TYPE (ClutterStageEgl, clutter_stage_egl, CLUTTER_TYPE_STAGE); + +static void +clutter_stage_egl_class_init (ClutterStageEglClass *klass) +{ + +} + +static void +clutter_stage_egl_init (ClutterStageEgl *stage) +{ + +} diff --git a/clutter/egl/clutter-stage-egl.h b/clutter/egl/clutter-stage-egl.h new file mode 100644 index 000000000..19c29aa28 --- /dev/null +++ b/clutter/egl/clutter-stage-egl.h @@ -0,0 +1,28 @@ +#ifndef __CLUTTER_STAGE_EGL_H__ +#define __CLUTTER_STAGE_EGL_H__ + +#include + +#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)) +#define CLUTTER_IS_STAGE_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_EGL)) +#define CLUTTER_STAGE_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_EGL, ClutterStageEglClass)) +#define CLUTTER_IS_STAGE_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_EGL)) +#define CLUTTER_STAGE_EGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_EGL, ClutterStageEglClass)) + +typedef struct _ClutterStageEgl ClutterStageEgl; +typedef struct _ClutterStageEglClass ClutterStageEglClass; + +struct _ClutterStageEgl +{ + ClutterStage parent_instance; +}; + +struct _ClutterStageEglClass +{ + ClutterStageClass parent_class; +}; + +GType clutter_stage_egl_get_type (void) G_GNUC_CONST; + +#endif /* __CLUTTER_STAGE_EGL_H__ */ diff --git a/clutter/glx/clutter-backend-glx.c b/clutter/glx/clutter-backend-glx.c new file mode 100644 index 000000000..6943987bf --- /dev/null +++ b/clutter/glx/clutter-backend-glx.c @@ -0,0 +1,437 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "clutter-backend-glx.h" +#include "clutter-stage-glx.h" + +#include "../clutter-event.h" +#include "../clutter-main.h" +#include "../clutter-debug.h" +#include "../clutter-private.h" + +G_DEFINE_TYPE (ClutterBackendGlx, clutter_backend_glx, CLUTTER_TYPE_BACKEND); + +/* singleton object */ +static ClutterBackendGlx *backend_singleton = NULL; + +/* options */ +static gchar *clutter_display_name = NULL; +static gint clutter_screen = 0; + +/* X error trap */ +static int TrappedErrorCode = 0; +static int (*old_error_handler) (Display *, XErrorEvent *); + +static gboolean +clutter_backend_glx_pre_parse (ClutterBackend *backend, + GError **error) +{ + const gchar *env_string; + + /* we don't fail here if DISPLAY is not set, as the user + * might pass the --display command line switch + */ + env_string = g_getenv ("DISPLAY"); + if (env_string) + { + clutter_display_name = g_strdup (env_string); + env_string = NULL; + } + + return TRUE; +} + +static gboolean +clutter_backend_glx_post_parse (ClutterBackend *backend, + GError **error) +{ + ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (backend); + + if (clutter_display_name) + { + CLUTTER_NOTE (MISC, "XOpenDisplay on `%s'", clutter_display_name); + backend_glx->xdpy = XOpenDisplay (clutter_display_name); + } + else + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Unable to open display. You have to set the DISPLAY " + "environment variable, or use the --display command " + "line argument"); + return FALSE; + } + + if (backend_glx->xdpy) + { + CLUTTER_NOTE (MISC, "Getting the X screen"); + + if (clutter_screen == 0) + backend_glx->xscreen = DefaultScreen (backend_glx->xdpy); + else + { + Screen *xscreen; + + xscreen = ScreenOfDisplay (backend_glx->xdpy, clutter_screen); + backend_glx->xscreen = XScreenNumberOfScreen (xscreen); + } + + backend_glx->xwin_root = RootWindow (backend_glx->xdpy, + backend_glx->xscreen); + + backend_glx->display_name = g_strdup (clutter_display_name); + } + + g_free (clutter_display_name); + + CLUTTER_NOTE (MISC, "X Display `%s' [%p] opened (screen:%d, root:%u)", + backend_glx->display_name, + backend_glx->xdpy, + backend_glx->xscreen, + (unsigned int) backend_glx->xwin_root); + + return TRUE; +} + +static gboolean +is_gl_version_at_least_12 (void) +{ +#define NON_VENDOR_VERSION_MAX_LEN 32 + gchar non_vendor_version[NON_VENDOR_VERSION_MAX_LEN]; + const gchar *version; + gint i = 0; + + version = (const gchar*) glGetString (GL_VERSION); + + while ( ((version[i] <= '9' && version[i] >= '0') || version[i] == '.') + && i < NON_VENDOR_VERSION_MAX_LEN) + { + non_vendor_version[i] = version[i]; + i++; + } + + non_vendor_version[i] = '\0'; + + if (strstr (non_vendor_version, "1.0") == NULL && + strstr (non_vendor_version, "1.0") == NULL) + return TRUE; + + return FALSE; +} + + +static gboolean +clutter_backend_glx_init_stage (ClutterBackend *backend, + GError **error) +{ + ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (backend); + + if (!backend_glx->stage) + { + ClutterStageGlx *stage_glx; + ClutterActor *stage; + + stage = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL); + + /* copy backend data into the stage */ + stage_glx = CLUTTER_STAGE_GLX (stage); + stage_glx->xdpy = backend_glx->xdpy; + stage_glx->xwin_root = backend_glx->xwin_root; + stage_glx->xscreen = backend_glx->xscreen; + + CLUTTER_NOTE (MISC, "GLX stage created (display:%p, screen:%d, root:%u)", + stage_glx->xdpy, + stage_glx->xscreen, + (unsigned int) stage_glx->xwin_root); + + g_object_set_data (G_OBJECT (stage), "clutter-backend", backend); + + backend_glx->stage = g_object_ref_sink (stage); + } + + clutter_actor_realize (backend_glx->stage); + if (!CLUTTER_ACTOR_IS_REALIZED (backend_glx->stage)) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_INTERNAL, + "Unable to realize the main stage"); + return FALSE; + } + + /* At least GL 1.2 is needed for CLAMP_TO_EDGE */ + if (!is_gl_version_at_least_12 ()) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Clutter needs at least version 1.2 of OpenGL"); + return FALSE; + } + + return TRUE; +} + +static void +clutter_backend_glx_init_events (ClutterBackend *backend) +{ + CLUTTER_NOTE (EVENT, "initialising the event loop"); + _clutter_events_init (backend); +} + +static ClutterActor * +clutter_backend_glx_get_stage (ClutterBackend *backend) +{ + ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (backend); + + return backend_glx->stage; +} + +static const GOptionEntry entries[] = +{ + { + "display", 0, + G_OPTION_FLAG_IN_MAIN, + G_OPTION_ARG_STRING, &clutter_display_name, + "X display to use", "DISPLAY" + }, + { + "screen", 0, + G_OPTION_FLAG_IN_MAIN, + G_OPTION_ARG_INT, &clutter_screen, + "X screen to use", "SCREEN" + }, + { NULL } +}; + +static void +clutter_backend_glx_add_options (ClutterBackend *backend, + GOptionGroup *group) +{ + g_option_group_add_entries (group, entries); +} + +static void +clutter_backend_glx_finalize (GObject *gobject) +{ + ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (gobject); + + g_free (backend_glx->display_name); + + XCloseDisplay (backend_glx->xdpy); + + if (backend_singleton) + backend_singleton = NULL; + + G_OBJECT_CLASS (clutter_backend_glx_parent_class)->finalize (gobject); +} + +static void +clutter_backend_glx_dispose (GObject *gobject) +{ + ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (gobject); + + _clutter_events_uninit (CLUTTER_BACKEND (backend_glx)); + + if (backend_glx->stage) + { + g_object_unref (backend_glx->stage); + backend_glx->stage = NULL; + } + + G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject); +} + +static GObject * +clutter_backend_glx_constructor (GType gtype, + guint n_params, + GObjectConstructParam *params) +{ + GObjectClass *parent_class; + GObject *retval; + + if (!backend_singleton) + { + parent_class = G_OBJECT_CLASS (clutter_backend_glx_parent_class); + retval = parent_class->constructor (gtype, n_params, params); + + backend_singleton = CLUTTER_BACKEND_GLX (retval); + + return retval; + } + + g_warning ("Attempting to create a new backend object. This should " + "never happen, so we return the singleton instance."); + + return g_object_ref (backend_singleton); +} + +static void +clutter_backend_glx_class_init (ClutterBackendGlxClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); + + gobject_class->constructor = clutter_backend_glx_constructor; + gobject_class->dispose = clutter_backend_glx_dispose; + gobject_class->finalize = clutter_backend_glx_finalize; + + backend_class->pre_parse = clutter_backend_glx_pre_parse; + backend_class->post_parse = clutter_backend_glx_post_parse; + backend_class->init_stage = clutter_backend_glx_init_stage; + backend_class->init_events = clutter_backend_glx_init_events; + backend_class->get_stage = clutter_backend_glx_get_stage; + backend_class->add_options = clutter_backend_glx_add_options; +} + +static void +clutter_backend_glx_init (ClutterBackendGlx *backend_glx) +{ + ClutterBackend *backend = CLUTTER_BACKEND (backend_glx); + + backend->button_click_time[0] = backend->button_click_time[1] = 0; + backend->button_number[0] = backend->button_number[1] = -1; + backend->button_x[0] = backend->button_x[1] = 0; + backend->button_y[0] = backend->button_y[1] = 0; + + /* FIXME - find a way to set this stuff from XSettings */ + backend->double_click_time = 250; + backend->double_click_distance = 5; +} + +/* every backend must implement this function */ +GType +_clutter_backend_impl_get_type (void) +{ + return clutter_backend_glx_get_type (); +} + +static int +error_handler(Display *xdpy, + XErrorEvent *error) +{ + TrappedErrorCode = error->error_code; + return 0; +} + +/** + * clutter_glx_trap_x_errors: + * + * FIXME + * + * Since: 0.4 + */ +void +clutter_glx_trap_x_errors (void) +{ + TrappedErrorCode = 0; + old_error_handler = XSetErrorHandler (error_handler); +} + +/** + * clutter_glx_untrap_x_errors: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +gint +clutter_glx_untrap_x_errors (void) +{ + XSetErrorHandler (old_error_handler); + + return TrappedErrorCode; +} + +/** + * clutter_glx_get_default_display: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +Display * +clutter_glx_get_default_display (void) +{ + if (!backend_singleton) + { + g_critical ("GLX backend has not been initialised"); + return NULL; + } + + return backend_singleton->xdpy; +} + +/** + * clutter_glx_get_default_screen: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +gint +clutter_glx_get_default_screen (void) +{ + if (!backend_singleton) + { + g_critical ("GLX backend has not been initialised"); + return -1; + } + + return backend_singleton->xscreen; +} + +/** + * clutter_glx_get_root_window: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +Window +clutter_glx_get_root_window (void) +{ + if (!backend_singleton) + { + g_critical ("GLX backend has not been initialised"); + return None; + } + + return backend_singleton->xwin_root; +} + + diff --git a/clutter/glx/clutter-backend-glx.h b/clutter/glx/clutter-backend-glx.h new file mode 100644 index 000000000..f05ad6aba --- /dev/null +++ b/clutter/glx/clutter-backend-glx.h @@ -0,0 +1,70 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_BACKEND_GLX_H__ +#define __CLUTTER_BACKEND_GLX_H__ + +#include +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_GLX (clutter_backend_glx_get_type ()) +#define CLUTTER_BACKEND_GLX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_GLX, ClutterBackendGlx)) +#define CLUTTER_IS_BACKEND_GLX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_GLX)) +#define CLUTTER_BACKEND_GLX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_GLX, ClutterBackendGlxClass)) +#define CLUTTER_IS_BACKEND_GLX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_GLX)) +#define CLUTTER_BACKEND_GLX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_GLX, ClutterBackendGlxClass)) + +typedef struct _ClutterBackendGlx ClutterBackendGlx; +typedef struct _ClutterBackendGlxClass ClutterBackendGlxClass; + +struct _ClutterBackendGlx +{ + ClutterBackend parent_instance; + + Display *xdpy; + Window xwin_root; + int xscreen; + gchar *display_name; + + /* main stage singleton */ + ClutterActor *stage; + + /* event source */ + GSource *event_source; +}; + +struct _ClutterBackendGlxClass +{ + ClutterBackendClass parent_class; +}; + +GType clutter_backend_glx_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_GLX_H__ */ diff --git a/clutter/glx/clutter-event-glx.c b/clutter/glx/clutter-event-glx.c new file mode 100644 index 000000000..b3b247cf7 --- /dev/null +++ b/clutter/glx/clutter-event-glx.c @@ -0,0 +1,413 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "clutter-stage-glx.h" +#include "clutter-backend-glx.h" +#include "clutter-glx.h" + +#include "../clutter-backend.h" +#include "../clutter-event.h" +#include "../clutter-private.h" +#include "../clutter-debug.h" +#include "../clutter-main.h" + +#include + +#include + +#ifdef HAVE_XFIXES +#include +#endif + +#include + +typedef struct _ClutterEventSource ClutterEventSource; + +struct _ClutterEventSource +{ + GSource source; + + ClutterBackend *backend; + GPollFD event_poll_fd; +}; + +static gboolean clutter_event_prepare (GSource *source, + gint *timeout); +static gboolean clutter_event_check (GSource *source); +static gboolean clutter_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data); + +static GList *event_sources = NULL; + +static GSourceFuncs event_funcs = { + clutter_event_prepare, + clutter_event_check, + clutter_event_dispatch, + NULL +}; + +static GSource * +clutter_event_source_new (ClutterBackend *backend) +{ + GSource *source = g_source_new (&event_funcs, sizeof (ClutterEventSource)); + ClutterEventSource *event_source = (ClutterEventSource *) source; + + event_source->backend = backend; + + return source; +} + +static gboolean +clutter_check_xpending (ClutterBackend *backend) +{ + return XPending (CLUTTER_BACKEND_GLX (backend)->xdpy); +} + + +void +_clutter_events_init (ClutterBackend *backend) +{ + GSource *source; + ClutterEventSource *event_source; + ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (backend); + int connection_number; + + connection_number = ConnectionNumber (backend_glx->xdpy); + CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number); + + source = backend_glx->event_source = clutter_event_source_new (backend); + event_source = (ClutterEventSource *) source; + g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); + + event_source->event_poll_fd.fd = connection_number; + event_source->event_poll_fd.events = G_IO_IN; + + event_sources = g_list_prepend (event_sources, event_source); + + g_source_add_poll (source, &event_source->event_poll_fd); + g_source_set_can_recurse (source, TRUE); + g_source_attach (source, NULL); +} + +void +_clutter_events_uninit (ClutterBackend *backend) +{ + ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (backend); + + if (backend_glx->event_source) + { + CLUTTER_NOTE (EVENT, "Destroying the event source"); + + event_sources = g_list_remove (event_sources, + backend_glx->event_source); + + g_source_destroy (backend_glx->event_source); + g_source_unref (backend_glx->event_source); + backend_glx->event_source = NULL; + } +} + +static void +set_user_time (Display *display, + Window *xwindow, + ClutterEvent *event) +{ + if (clutter_event_get_time (event) != CLUTTER_CURRENT_TIME) + { + Atom atom_WM_USER_TIME; + long timestamp = clutter_event_get_time (event); + + atom_WM_USER_TIME = XInternAtom (display, "_NET_WM_USER_TIME", False); + + XChangeProperty (display, *xwindow, + atom_WM_USER_TIME, + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) ×tamp, 1); + } +} + +/** + * clutter_events_pending: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +gboolean +clutter_events_pending (void) +{ + GList *i; + + for (i = event_sources; i != NULL; i = i->next) + { + ClutterEventSource *source = i->data; + ClutterBackend *backend = source->backend; + + if (_clutter_event_queue_check_pending (backend)) + return TRUE; + } + + for (i = event_sources; i != NULL; i = i->next) + { + ClutterEventSource *source = i->data; + ClutterBackend *backend = source->backend; + + if (clutter_check_xpending (backend)) + return TRUE; + } + + return FALSE; +} + +static void +translate_key_event (ClutterBackend *backend, + ClutterEvent *event, + XEvent *xevent) +{ + CLUTTER_NOTE (EVENT, "Translating key %s event", + xevent->xany.type == KeyPress ? "press" : "release"); + + event->key.type = (xevent->xany.type == KeyPress) ? CLUTTER_KEY_PRESS + : CLUTTER_KEY_RELEASE; + event->key.time = xevent->xkey.time; + event->key.modifier_state = xevent->xkey.state; /* FIXME: handle modifiers */ + event->key.hardware_keycode = xevent->xkey.keycode; + event->key.keyval = XKeycodeToKeysym (xevent->xkey.display, + xevent->xkey.keycode, + 0); /* FIXME: index with modifiers */ +} + +static gboolean +clutter_event_translate (ClutterBackend *backend, + ClutterEvent *event, + XEvent *xevent) +{ + ClutterBackendGlx *backend_glx; + ClutterStage *stage; + gboolean res; + Window xwindow, stage_xwindow; + + backend_glx = CLUTTER_BACKEND_GLX (backend); + stage = CLUTTER_STAGE (clutter_backend_get_stage (backend)); + stage_xwindow = clutter_glx_get_stage_window (stage); + + xwindow = xevent->xany.window; + if (xwindow == None) + xwindow = stage_xwindow; + + res = TRUE; + + switch (xevent->type) + { + case Expose: + { + XEvent foo_xev; + + /* Cheap compress */ + while (XCheckTypedWindowEvent (backend_glx->xdpy, + xevent->xexpose.window, + Expose, + &foo_xev)); + + /* FIXME: need to make stage an 'actor' so can que + * a paint direct from there rather than hack here... + */ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + res = FALSE; + } + break; + case KeyPress: + event->type = CLUTTER_KEY_PRESS; + translate_key_event (backend, event, xevent); + set_user_time (backend_glx->xdpy, &xwindow, event); + break; + case KeyRelease: + event->type = CLUTTER_KEY_RELEASE; + translate_key_event (backend, event, xevent); + break; + 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; + + 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; + + _clutter_event_button_generate (backend, event); + break; + } + + set_user_time (backend_glx->xdpy, &xwindow, event); + 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; + 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; + 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; + break; + case DestroyNotify: + event->type = event->any.type = CLUTTER_DESTROY_NOTIFY; + break; + default: + /* ignore every other event */ + res = FALSE; + break; + } + + return res; +} + +void +_clutter_events_queue (ClutterBackend *backend) +{ + ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (backend); + ClutterEvent *event; + XEvent xevent; + Display *xdisplay = backend_glx->xdpy; + + while (!_clutter_event_queue_check_pending (backend) && XPending (xdisplay)) + { + XNextEvent (xdisplay, &xevent); + + switch (xevent.type) + { + case KeyPress: + case KeyRelease: + break; + default: + if (XFilterEvent (&xevent, None)) + continue; + } + + event = clutter_event_new (CLUTTER_NOTHING); + if (clutter_event_translate (backend, event, &xevent)) + { + _clutter_event_queue_push (backend, event); + } + else + { + clutter_event_free (event); + } + } +} + +static gboolean +clutter_event_prepare (GSource *source, + gint *timeout) +{ + ClutterBackend *backend = ((ClutterEventSource *) source)->backend; + gboolean retval; + + *timeout = -1; + retval = (_clutter_event_queue_check_pending (backend) || + clutter_check_xpending (backend)); + + return retval; +} + +static gboolean +clutter_event_check (GSource *source) +{ + ClutterEventSource *event_source = (ClutterEventSource *) source; + ClutterBackend *backend = event_source->backend; + gboolean retval; + + if (event_source->event_poll_fd.revents & G_IO_IN) + retval = (_clutter_event_queue_check_pending (backend) || + clutter_check_xpending (backend)); + else + retval = FALSE; + + return retval; +} + +static gboolean +clutter_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterBackend *backend = ((ClutterEventSource *) source)->backend; + ClutterEvent *event; + + _clutter_events_queue (backend); + event = _clutter_event_queue_pop (backend); + + if (event) + { + if (_clutter_event_func) + { + CLUTTER_NOTE (EVENT, "Dispatching _clutter_event_func"); + (* _clutter_event_func) (event, _clutter_event_data); + } + + clutter_event_free (event); + } + + return TRUE; +} diff --git a/clutter/clutter-stage-glx.h b/clutter/glx/clutter-glx.h similarity index 62% rename from clutter/clutter-stage-glx.h rename to clutter/glx/clutter-glx.h index 5287cca4f..ef4e90bb3 100644 --- a/clutter/clutter-stage-glx.h +++ b/clutter/glx/clutter-glx.h @@ -23,36 +23,29 @@ * Boston, MA 02111-1307, USA. */ -#ifndef _HAVE_CLUTTER_STAGE_GLX_H -#define _HAVE_CLUTTER_STAGE_GLX_H +#ifndef __CLUTTER_GLX_H__ +#define __CLUTTER_GLX_H__ + +#include +#include +#include +#include G_BEGIN_DECLS -#include -#include +void clutter_glx_trap_x_errors (void); +gint clutter_glx_untrap_x_errors (void); -#include -#include +Display *clutter_glx_get_default_display (void); +gint clutter_glx_get_default_screen (void); +Window clutter_glx_get_root_window (void); -#include - -void -clutter_stage_backend_init_vtable (ClutterStageVTable *vtable) G_GNUC_INTERNAL; - -ClutterStageBackend* -clutter_stage_backend_init (ClutterStage *stage) G_GNUC_INTERNAL; - -Window -clutter_stage_glx_window (ClutterStage *stage); - -gboolean -clutter_stage_glx_set_window_foreign (ClutterStage *stage, - Window xid); - -const XVisualInfo* -clutter_stage_glx_get_xvisual (ClutterStage *stage); +Window clutter_glx_get_stage_window (ClutterStage *stage); +XVisualInfo *clutter_glx_get_stage_visual (ClutterStage *stage); +void clutter_glx_set_stage_foreign (ClutterStage *stage, + Window window); G_END_DECLS -#endif +#endif /* __CLUTTER_GLX_H__ */ diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c new file mode 100644 index 000000000..37ee629d7 --- /dev/null +++ b/clutter/glx/clutter-stage-glx.c @@ -0,0 +1,776 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-backend-glx.h" +#include "clutter-stage-glx.h" +#include "clutter-glx.h" + +#include "../clutter-main.h" +#include "../clutter-feature.h" +#include "../clutter-color.h" +#include "../clutter-util.h" +#include "../clutter-event.h" +#include "../clutter-enum-types.h" +#include "../clutter-private.h" +#include "../clutter-debug.h" + +#include + +#include +#include + +#include + +G_DEFINE_TYPE (ClutterStageGlx, clutter_stage_glx, CLUTTER_TYPE_STAGE); + +static inline void +frustum (GLfloat left, + GLfloat right, + GLfloat bottom, + GLfloat top, + GLfloat nearval, + GLfloat farval) +{ + GLfloat x, y, a, b, c, d; + GLfloat m[16]; + + x = (2.0 * nearval) / (right - left); + y = (2.0 * nearval) / (top - bottom); + a = (right + left) / (right - left); + b = (top + bottom) / (top - bottom); + c = -(farval + nearval) / ( farval - nearval); + d = -(2.0 * farval * nearval) / (farval - nearval); + +#define M(row,col) m[col*4+row] + M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F; + M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F; + M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d; + M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F; +#undef M + + glMultMatrixf (m); +} + +static inline void +perspective (GLfloat fovy, + GLfloat aspect, + GLfloat zNear, + GLfloat zFar) +{ + GLfloat xmin, xmax, ymin, ymax; + + ymax = zNear * tan (fovy * M_PI / 360.0); + ymin = -ymax; + xmin = ymin * aspect; + xmax = ymax * aspect; + + frustum (xmin, xmax, ymin, ymax, zNear, zFar); +} + +static void +sync_viewport (ClutterStageGlx *stage_glx) +{ + glViewport (0, 0, stage_glx->xwin_width, stage_glx->xwin_height); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + + perspective (60.0f, 1.0f, 0.1f, 100.0f); + + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + /* Then for 2D like transform */ + + /* camera distance from screen, 0.5 * tan (FOV) */ +#define DEFAULT_Z_CAMERA 0.866025404f + + glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA); + glScalef ( 1.0f / stage_glx->xwin_width, + -1.0f / stage_glx->xwin_height, + 1.0f / stage_glx->xwin_width); + glTranslatef (0.0f, -1.0 * stage_glx->xwin_height, 0.0f); +} + +static void +clutter_stage_glx_show (ClutterActor *actor) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (actor); + + if (stage_glx->xwin) + XMapWindow (stage_glx->xdpy, stage_glx->xwin); +} + +static void +clutter_stage_glx_hide (ClutterActor *actor) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (actor); + + if (stage_glx->xwin) + XUnmapWindow (stage_glx->xdpy, stage_glx->xwin); +} + +static void +clutter_stage_glx_unrealize (ClutterActor *actor) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (actor); + gboolean was_offscreen; + + CLUTTER_MARK(); + + g_object_get (actor, "offscreen", &was_offscreen, NULL); + + if (G_UNLIKELY (was_offscreen)) + { + if (stage_glx->glxpixmap) + { + glXDestroyGLXPixmap (stage_glx->xdpy, stage_glx->glxpixmap); + stage_glx->glxpixmap = None; + } + + if (stage_glx->xpixmap) + { + XFreePixmap (stage_glx->xdpy, stage_glx->xpixmap); + stage_glx->xpixmap = None; + } + } + else + { + if (!stage_glx->is_foreign_xwin && stage_glx->xwin != None) + { + XDestroyWindow (stage_glx->xdpy, stage_glx->xwin); + stage_glx->xwin = None; + } + else + stage_glx->xwin = None; + } + + glXMakeCurrent (stage_glx->xdpy, None, NULL); + if (stage_glx->gl_context != None) + { + glXDestroyContext (stage_glx->xdpy, stage_glx->gl_context); + stage_glx->gl_context = None; + } +} + +static void +clutter_stage_glx_realize (ClutterActor *actor) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (actor); + gboolean is_offscreen; + + CLUTTER_NOTE (MISC, "Realizing main stage"); + + g_object_get (actor, "offscreen", &is_offscreen, NULL); + + if (G_LIKELY (!is_offscreen)) + { + int gl_attributes[] = + { + GLX_RGBA, + GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_STENCIL_SIZE, 1, + 0 + }; + + if (stage_glx->xvisinfo) + XFree (stage_glx->xvisinfo); + + if (stage_glx->xvisinfo == None) + stage_glx->xvisinfo = glXChooseVisual (stage_glx->xdpy, + stage_glx->xscreen, + gl_attributes); + if (!stage_glx->xvisinfo) + { + g_critical ("Unable to find suitable GL visual."); + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); + return; + } + + if (stage_glx->xwin == None) + { + CLUTTER_NOTE (MISC, "XCreateSimpleWindow"); + stage_glx->xwin = XCreateSimpleWindow (stage_glx->xdpy, + stage_glx->xwin_root, + 0, 0, + stage_glx->xwin_width, + stage_glx->xwin_height, + 0, 0, + WhitePixel (stage_glx->xdpy, + stage_glx->xscreen)); + } + + CLUTTER_NOTE (MISC, "XSelectInput"); + XSelectInput (stage_glx->xdpy, stage_glx->xwin, + StructureNotifyMask | + ExposureMask | + /* FIXME: we may want to eplicity enable MotionMask */ + PointerMotionMask | + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + PropertyChangeMask); + + if (stage_glx->gl_context) + glXDestroyContext (stage_glx->xdpy, stage_glx->gl_context); + + CLUTTER_NOTE (GL, "glXCreateContext"); + stage_glx->gl_context = glXCreateContext (stage_glx->xdpy, + stage_glx->xvisinfo, + 0, + True); + + if (stage_glx->gl_context == None) + { + g_critical ("Unable to create suitable GL context."); + + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); + + return; + } + + CLUTTER_NOTE (GL, "glXMakeCurrent"); + glXMakeCurrent (stage_glx->xdpy, stage_glx->xwin, stage_glx->gl_context); + } + else + { + int gl_attributes[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + 0 + }; + + if (stage_glx->xvisinfo) + XFree (stage_glx->xvisinfo); + + CLUTTER_NOTE (GL, "glXChooseVisual"); + stage_glx->xvisinfo = glXChooseVisual (stage_glx->xdpy, + stage_glx->xscreen, + gl_attributes); + if (!stage_glx->xvisinfo) + { + g_critical ("Unable to find suitable GL visual."); + + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); + + return; + } + + if (stage_glx->gl_context) + glXDestroyContext (stage_glx->xdpy, stage_glx->gl_context); + + stage_glx->xpixmap = XCreatePixmap (stage_glx->xdpy, + stage_glx->xwin_root, + stage_glx->xwin_width, + stage_glx->xwin_height, + stage_glx->xvisinfo->depth); + + stage_glx->glxpixmap = glXCreateGLXPixmap (stage_glx->xdpy, + stage_glx->xvisinfo, + stage_glx->xpixmap); + + /* indirect */ + stage_glx->gl_context = glXCreateContext (stage_glx->xdpy, + stage_glx->xvisinfo, + 0, + False); + + glXMakeCurrent (stage_glx->xdpy, + stage_glx->glxpixmap, + stage_glx->gl_context); + +#if 0 + /* Debug code for monitoring a off screen pixmap via window */ + { + Colormap cmap; + XSetWindowAttributes swa; + + cmap = XCreateColormap(clutter_glx_display(), + clutter_glx_root_window(), + backend->xvisinfo->visual, AllocNone); + + /* create a window */ + swa.colormap = cmap; + + foo_win = XCreateWindow(clutter_glx_display(), + clutter_glx_root_window(), + 0, 0, + backend->xwin_width, backend->xwin_height, + 0, + backend->xvisinfo->depth, + InputOutput, + backend->xvisinfo->visual, + CWColormap, &swa); + + XMapWindow(clutter_glx_display(), foo_win); + } +#endif + } + + CLUTTER_NOTE (GL, + "\n" + "===========================================\n" + "GL_VENDOR: %s\n" + "GL_RENDERER: %s\n" + "GL_VERSION: %s\n" + "GL_EXTENSIONS: %s\n" + "Direct Rendering: %s\n" + "===========================================\n", + glGetString (GL_VENDOR), + glGetString (GL_RENDERER), + glGetString (GL_VERSION), + glGetString (GL_EXTENSIONS), + glXIsDirect (stage_glx->xdpy, stage_glx->gl_context) ? "yes" + : "no"); + + sync_viewport (stage_glx); +} + +static void +clutter_stage_glx_paint (ClutterActor *self) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (self); + ClutterStage *stage = CLUTTER_STAGE (self); + ClutterColor stage_color; + static GTimer *timer = NULL; + static guint timer_n_frames = 0; + static ClutterActorClass *parent_class = NULL; + + CLUTTER_NOTE (PAINT, " Redraw enter"); + + if (!parent_class) + parent_class = g_type_class_peek_parent (CLUTTER_STAGE_GET_CLASS (stage)); + + if (clutter_get_show_fps ()) + { + if (!timer) + timer = g_timer_new (); + } + + clutter_stage_get_color (stage, &stage_color); + + glClearColor (((float) stage_color.red / 0xff * 1.0), + ((float) stage_color.green / 0xff * 1.0), + ((float) stage_color.blue / 0xff * 1.0), + 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glDisable (GL_LIGHTING); + glDisable (GL_DEPTH_TEST); + + parent_class->paint (self); + + if (stage_glx->xwin) + { + clutter_feature_wait_for_vblank (); + glXSwapBuffers (stage_glx->xdpy, stage_glx->xwin); + } + else + { + glXWaitGL (); + CLUTTER_GLERR (); + } + + if (clutter_get_show_fps ()) + { + timer_n_frames++; + + if (g_timer_elapsed (timer, NULL) >= 1.0) + { + g_print ("*** FPS: %i ***\n", timer_n_frames); + timer_n_frames = 0; + g_timer_start (timer); + } + } + + CLUTTER_NOTE (PAINT, " Redraw leave"); +} + +static void +clutter_stage_glx_allocate_coords (ClutterActor *self, + ClutterActorBox *box) +{ + /* Do nothing, just stop group_allocate getting called */ + + /* TODO: sync up with any configure events from WM ?? */ + return; +} + +static void +clutter_stage_glx_request_coords (ClutterActor *self, + ClutterActorBox *box) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (self); + gint new_width, new_height; + + /* FIXME: some how have X configure_notfiys call this ? */ + new_width = ABS (box->x2 - box->x1); + new_height = ABS (box->y2 - box->y1); + + if (new_width != stage_glx->xwin_width || + new_height != stage_glx->xwin_height) + { + stage_glx->xwin_width = new_width; + stage_glx->xwin_height = new_height; + + if (stage_glx->xwin != None) + XResizeWindow (stage_glx->xdpy, + stage_glx->xwin, + stage_glx->xwin_width, + stage_glx->xwin_height); + + if (stage_glx->xpixmap != None) + { + /* Need to recreate to resize */ + clutter_actor_unrealize (self); + clutter_actor_realize (self); + } + + sync_viewport (stage_glx); + } + + if (stage_glx->xwin != None) /* Do we want to bother ? */ + XMoveWindow (stage_glx->xdpy, + stage_glx->xwin, + box->x1, + box->y1); +} + +static void +clutter_stage_glx_set_fullscreen (ClutterStage *stage, + gboolean fullscreen) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (stage); + Atom atom_WM_STATE, atom_WM_STATE_FULLSCREEN; + + atom_WM_STATE = XInternAtom (stage_glx->xdpy, "_NET_WM_STATE", False); + atom_WM_STATE_FULLSCREEN = XInternAtom (stage_glx->xdpy, + "_NET_WM_STATE_FULLSCREEN", + False); + + if (fullscreen) + { + gint width, height; + + width = DisplayWidth (stage_glx->xdpy, stage_glx->xscreen); + height = DisplayHeight (stage_glx->xdpy, stage_glx->xscreen); + + clutter_actor_set_size (CLUTTER_ACTOR (stage_glx), width, height); + + if (stage_glx->xwin != None) + XChangeProperty (stage_glx->xdpy, + stage_glx->xwin, + atom_WM_STATE, XA_ATOM, 32, + PropModeReplace, + (unsigned char *) &atom_WM_STATE_FULLSCREEN, 1); + } + else + { + if (stage_glx->xwin != None) + XDeleteProperty (stage_glx->xdpy, stage_glx->xwin, atom_WM_STATE); + } + + sync_viewport (stage_glx); +} + +static void +clutter_stage_glx_set_cursor_visible (ClutterStage *stage, + gboolean show_cursor) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (stage); + + if (stage_glx->xwin == None) + return; + + CLUTTER_NOTE (MISC, "setting cursor state (%s) over stage window (%u)", + show_cursor ? "visible" : "invisible", + (unsigned int) stage_glx->xwin); + + if (show_cursor) + { +#ifdef HAVE_XFIXES + XFixesShowCursor (stage_glx->xdpy, stage_glx->xwin); +#else + XUndefineCursor (stage_glx->xdpy, stage_glx->xwin); +#endif + } + else + { +#ifdef HAVE_XFIXES + XFixesHideCursor (stage_glx->xdpy, stage_glx->xwin); +#else + XColor col; + Pixmap pix; + Cursor curs; + + pix = XCreatePixmap (stage_glx->xdpy, stage_glx->xwin, 1, 1, 1); + memset (&col, 0, sizeof (col)); + curs = XCreatePixmapCursor (stage_glx->xdpy, + pix, pix, + &col, &col, + 1, 1); + XFreePixmap (stage_glx->xdpy, pix); + XDefineCursor (stage_glx->xdpy, stage_glx->xwin, curs); +#endif + } + + sync_viewport (stage_glx); +} + +static void +clutter_stage_glx_set_offscreen (ClutterStage *stage, + gboolean offscreen) +{ + +} + +static ClutterActor * +clutter_stage_glx_get_actor_at_pos (ClutterStage *stage, + gint x, + gint y) +{ + ClutterActor *found = NULL; + GLuint buff[64] = { 0 }; + GLint hits; + GLint view[4]; + + glSelectBuffer (sizeof (buff), buff); + glGetIntegerv (GL_VIEWPORT, view); + glRenderMode (GL_SELECT); + + glInitNames (); + + glPushName (0); + + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + glLoadIdentity (); + + /* This is gluPickMatrix(x, y, 1.0, 1.0, view); */ + glTranslatef ((view[2] - 2 * (x - view[0])), + (view[3] - 2 * (y - view[1])), 0); + glScalef (view[2], -view[3], 1.0); + + perspective (60.0f, 1.0f, 0.1f, 100.0f); + + glMatrixMode (GL_MODELVIEW); + + clutter_actor_paint (CLUTTER_ACTOR (stage)); + + glMatrixMode (GL_PROJECTION); + glPopMatrix (); + + hits = glRenderMode(GL_RENDER); + + if (hits != 0) + { +#if 0 + gint i + for (i = 0; i < hits; i++) + g_print ("Hit at %i\n", buff[i * 4 + 3]); +#endif + + found = clutter_group_find_child_by_id (CLUTTER_GROUP (stage), + buff[(hits-1) * 4 + 3]); + } + + clutter_stage_flush (stage); + + return found; +} + +static void +snapshot_pixbuf_free (guchar *pixels, + gpointer data) +{ + g_free (pixels); +} + +static void +clutter_stage_glx_draw_to_pixbuf (ClutterStage *stage, + GdkPixbuf *dest, + gint x, + gint y, + gint width, + gint height) +{ + guchar *data; + GdkPixbuf *pixb; + ClutterActor *actor; + ClutterStageGlx *stage_glx; + gboolean is_offscreen = FALSE; + + stage_glx = CLUTTER_STAGE_GLX (stage); + actor = CLUTTER_ACTOR (stage); + + if (width < 0) + width = clutter_actor_get_width (actor); + + if (height < 0) + height = clutter_actor_get_height (actor); + + g_object_get (stage, "offscreen", &is_offscreen, NULL); + + if (G_UNLIKELY (is_offscreen)) + { + gdk_pixbuf_xlib_init (stage_glx->xdpy, stage_glx->xscreen); + + dest = gdk_pixbuf_xlib_get_from_drawable (NULL, + (Drawable) stage_glx->xpixmap, + DefaultColormap (stage_glx->xdpy, + stage_glx->xscreen), + stage_glx->xvisinfo->visual, + x, y, + 0, 0, + width, height); + } + else + { + data = g_malloc0 (sizeof (guchar) * width * height * 4); + + glReadPixels (x, + clutter_actor_get_height (actor) - y - height, + width, + height, GL_RGBA, GL_UNSIGNED_BYTE, data); + + pixb = gdk_pixbuf_new_from_data (data, + GDK_COLORSPACE_RGB, + TRUE, + 8, + width, height, + width * 4, + snapshot_pixbuf_free, + NULL); + + dest = gdk_pixbuf_flip (pixb, TRUE); + + g_object_unref (pixb); + } +} + +static void +clutter_stage_glx_flush (ClutterStage *stage) +{ + sync_viewport (CLUTTER_STAGE_GLX (stage)); +} + +static void +clutter_stage_glx_dispose (GObject *gobject) +{ + ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (gobject); + + if (stage_glx->xwin) + clutter_actor_unrealize (CLUTTER_ACTOR (stage_glx)); + + G_OBJECT_CLASS (clutter_stage_glx_parent_class)->dispose (gobject); +} + +static void +clutter_stage_glx_class_init (ClutterStageGlxClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass); + + gobject_class->dispose = clutter_stage_glx_dispose; + + actor_class->show = clutter_stage_glx_show; + actor_class->hide = clutter_stage_glx_hide; + actor_class->realize = clutter_stage_glx_realize; + actor_class->unrealize = clutter_stage_glx_unrealize; + actor_class->paint = clutter_stage_glx_paint; + actor_class->request_coords = clutter_stage_glx_request_coords; + actor_class->allocate_coords = clutter_stage_glx_allocate_coords; + + stage_class->set_fullscreen = clutter_stage_glx_set_fullscreen; + stage_class->set_cursor_visible = clutter_stage_glx_set_cursor_visible; + stage_class->set_offscreen = clutter_stage_glx_set_offscreen; + stage_class->get_actor_at_pos = clutter_stage_glx_get_actor_at_pos; + stage_class->draw_to_pixbuf = clutter_stage_glx_draw_to_pixbuf; + stage_class->flush = clutter_stage_glx_flush; +} + +static void +clutter_stage_glx_init (ClutterStageGlx *stage) +{ + stage->xdpy = NULL; + stage->xwin_root = None; + stage->xscreen = 0; + + stage->xwin = None; + stage->xwin_width = 640; + stage->xwin_height = 480; + stage->xvisinfo = None; + + stage->is_foreign_xwin = FALSE; +} + +/** + * clutter_glx_get_stage_window: + * @stage: a #ClutterStage + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +Window +clutter_glx_get_stage_window (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE_GLX (stage), None); + + return CLUTTER_STAGE_GLX (stage)->xwin; +} + +/** + * clutter_glx_get_stage_visual: + * @stage: a #ClutterStage + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +XVisualInfo * +clutter_glx_get_stage_visual (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE_GLX (stage), NULL); + + return CLUTTER_STAGE_GLX (stage)->xvisinfo; +} + +void +clutter_glx_set_stage_foreign (ClutterStage *stage, + Window window) +{ + g_return_if_fail (CLUTTER_IS_STAGE_GLX (stage)); + + /* FIXME */ +} diff --git a/clutter/glx/clutter-stage-glx.h b/clutter/glx/clutter-stage-glx.h new file mode 100644 index 000000000..44a1feafd --- /dev/null +++ b/clutter/glx/clutter-stage-glx.h @@ -0,0 +1,74 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_STAGE_GLX_H__ +#define __CLUTTER_STAGE_GLX_H__ + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_STAGE_GLX (clutter_stage_glx_get_type ()) +#define CLUTTER_STAGE_GLX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_GLX, ClutterStageGlx)) +#define CLUTTER_IS_STAGE_GLX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_GLX)) +#define CLUTTER_STAGE_GLX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_GLX, ClutterStageGlxClass)) +#define CLUTTER_IS_STAGE_GLX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_GLX)) +#define CLUTTER_STAGE_GLX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_GLX, ClutterStageGlxClass)) + +typedef struct _ClutterStageGlx ClutterStageGlx; +typedef struct _ClutterStageGlxClass ClutterStageGlxClass; + +struct _ClutterStageGlx +{ + ClutterStage parent_instance; + + /* from the backend */ + Display *xdpy; + Window xwin_root; + int xscreen; + + XVisualInfo *xvisinfo; + Window xwin; + gint xwin_width; + gint xwin_height; /* FIXME target_width / height */ + Pixmap xpixmap; + + GLXPixmap glxpixmap; + GLXContext gl_context; + + guint is_foreign_xwin : 1; +}; + +struct _ClutterStageGlxClass +{ + ClutterStageClass parent_class; +}; + +GType clutter_stage_glx_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_H__ */ diff --git a/clutter/pango/pangoclutter.h b/clutter/pango/pangoclutter.h index 9f58c9274..e07210a51 100644 --- a/clutter/pango/pangoclutter.h +++ b/clutter/pango/pangoclutter.h @@ -27,9 +27,9 @@ #define G_DISABLE_CAST_CHECKS #include -#include #include #include +#include G_BEGIN_DECLS diff --git a/configure.ac b/configure.ac index 10a423bd1..5e4302af1 100644 --- a/configure.ac +++ b/configure.ac @@ -84,6 +84,12 @@ then fi fi +if $PKG_CONFIG --exists xfixes ; then + AC_DEFINE(HAVE_XFIXES, 1, Have the XFIXES X extension) + + X11_LIBS="$X11_LIBS -lXfixes" +fi + AC_CHECK_HEADERS([GL/gl.h GL/glx.h],, [AC_MSG_ERROR([Unable to locate required GL headers])]) @@ -97,10 +103,30 @@ fi GLX_CFLAGS="$X11_CFLAGS" -CLUTTER_FLAVOUR="glx" -CLUTTER_FLAVOUR_DEFINE="CLUTTER_FLAVOUR_GLX" +clutterbackend=glx +AC_ARG_WITH([flavour], + AC_HELP_STRING([--with-flavour=@<:@glx/egl@:>@], + [Select the Clutter backend]), + clutterbackend=$with_flavour) + +AC_SUBST([clutterbackend]) +case $clutterbackend in + glx) + CLUTTER_FLAVOUR="glx" + AC_DEFINE([HAVE_CLUTTER_GLX], 1, [Have the GLX backend]) + ;; + egl) + CLUTTER_FLAVOUR="egl" + AC_DEFINE([HAVE_CLUTTER_EGL], 1, [Have the EGL backend]) + ;; + *) AC_MSG_ERROR([Invalid backend for Clutter: use glx or egl]) + ;; +esac + AC_SUBST(CLUTTER_FLAVOUR) -AC_SUBST(CLUTTER_FLAVOUR_DEFINE) + +clutterbackendlib=libclutter-$clutterbackend-$CLUTTER_MAJORMINOR.la +AC_SUBST([clutterbackendlib]) dnl ======================================================================== @@ -164,6 +190,8 @@ AC_CONFIG_FILES([ clutter/pango/Makefile clutter/Makefile clutter/clutter-version.h + clutter/glx/Makefile + clutter/egl/Makefile examples/Makefile doc/Makefile doc/reference/Makefile @@ -181,6 +209,7 @@ echo " ===================" echo "" echo " prefix: ${prefix}" echo "" +echo " Flavour: ${clutterbackend}" echo " Debug level: ${enable_debug}" echo " Documentation: ${enable_gtk_doc}" echo " FPU: ${with_fpu}" diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am index 439f96f46..4eaccb4ff 100644 --- a/doc/reference/Makefile.am +++ b/doc/reference/Makefile.am @@ -77,7 +77,7 @@ expand_content_files= # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) INCLUDES=-I$(top_srcdir) $(CLUTTER_CFLAGS) -GTKDOC_LIBS=$(top_builddir)/clutter/libclutter-@CLUTTER_MAJORMINOR@.la $(CLUTTER_LIBS) +GTKDOC_LIBS=$(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la $(CLUTTER_LIBS) # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make diff --git a/doc/reference/tmpl/clutter-event.sgml b/doc/reference/tmpl/clutter-event.sgml index 0447456af..cfc64e47a 100644 --- a/doc/reference/tmpl/clutter-event.sgml +++ b/doc/reference/tmpl/clutter-event.sgml @@ -29,6 +29,7 @@ Windowing events handled by Clutter. @CLUTTER_BUTTON_PRESS: @CLUTTER_2BUTTON_PRESS: @CLUTTER_BUTTON_RELEASE: +@CLUTTER_STAGE_STATE: @@ -122,51 +123,6 @@ Windowing events handled by Clutter. @Returns: - - - - - -@buttev: -@Returns: - - - - - - - -@buttev: -@Returns: - - - - - - - -@buttev: -@Returns: - - - - - - - -@keyev: -@Returns: - - - - - - - -@keyev: -@Returns: - - diff --git a/doc/reference/tmpl/clutter-main.sgml b/doc/reference/tmpl/clutter-main.sgml index 8788ffd5f..f8047517f 100644 --- a/doc/reference/tmpl/clutter-main.sgml +++ b/doc/reference/tmpl/clutter-main.sgml @@ -32,9 +32,8 @@ Error codes for the Clutter initialisation process. @CLUTTER_INIT_SUCCESS: Clutter was successfully initialised @CLUTTER_INIT_ERROR_UNKOWN: Unknown error while initialising Clutter @CLUTTER_INIT_ERROR_THREADS: Unable to initialise threading -@CLUTTER_INIT_ERROR_DISPLAY: Unable to open the X display +@CLUTTER_INIT_ERROR_BACKEND: @CLUTTER_INIT_ERROR_INTERNAL: Internal Clutter error -@CLUTTER_INIT_ERROR_OPENGL: Unable to initialise OpenGL @@ -97,38 +96,6 @@ Error codes for the Clutter initialisation process. - - - - - -@Returns: - - - - - - - -@Returns: - - - - - - - -@Returns: - - - - - - - -@Returns: - - diff --git a/doc/reference/tmpl/clutter-media.sgml b/doc/reference/tmpl/clutter-media.sgml index 5330021ec..3d85887af 100644 --- a/doc/reference/tmpl/clutter-media.sgml +++ b/doc/reference/tmpl/clutter-media.sgml @@ -23,6 +23,21 @@ clutter-media + + + + + +@cluttermedia: the object which received the signal. + + + + + + +@cluttermedia: the object which received the signal. +@arg1: + diff --git a/doc/reference/tmpl/clutter-stage.sgml b/doc/reference/tmpl/clutter-stage.sgml index 979a5e68e..268eec0f0 100644 --- a/doc/reference/tmpl/clutter-stage.sgml +++ b/doc/reference/tmpl/clutter-stage.sgml @@ -90,12 +90,12 @@ Macro evaluating to the height of the #ClutterStage - + - + @@ -111,12 +111,19 @@ Macro evaluating to the height of the #ClutterStage @parent_class: +@set_fullscreen: +@set_cursor_visible: +@set_offscreen: +@get_actor_at_pos: +@draw_to_pixbuf: +@flush: @input_event: @button_press_event: @button_release_event: @key_press_event: @key_release_event: @motion_event: +@stage_state_event: @_clutter_stage1: @_clutter_stage2: @_clutter_stage3: @@ -132,25 +139,6 @@ Macro evaluating to the height of the #ClutterStage @Returns: - - - - - -@stage: -@Returns: - - - - - - - -@stage: -@xid: -@Returns: - - @@ -193,12 +181,3 @@ Macro evaluating to the height of the #ClutterStage @Returns: - - - - - -@stage: -@Returns: - - diff --git a/doc/reference/tmpl/clutter-util.sgml b/doc/reference/tmpl/clutter-util.sgml index a92d0f194..2c8f149ad 100644 --- a/doc/reference/tmpl/clutter-util.sgml +++ b/doc/reference/tmpl/clutter-util.sgml @@ -17,21 +17,6 @@ clutter-util - - - - - - - - - - - - -@Returns: - - diff --git a/examples/behave.c b/examples/behave.c index bcc6485ad..0f16cd882 100644 --- a/examples/behave.c +++ b/examples/behave.c @@ -1,5 +1,38 @@ #include +static void +button_press_cb (ClutterStage *stage, + ClutterButtonEvent *event, + gpointer data) +{ + const gchar *click_type; + + switch (event->type) + { + case CLUTTER_2BUTTON_PRESS: + click_type = "double"; + break; + case CLUTTER_3BUTTON_PRESS: + click_type = "triple"; + break; + default: + click_type = "single"; + break; + } + + g_print ("%s button press event\n", click_type); +} + +static void +scroll_event_cb (ClutterStage *stage, + ClutterScrollEvent *event, + gpointer data) +{ + g_print ("scroll direction: %s\n", + event->direction == CLUTTER_SCROLL_UP ? "up" + : "down"); +} + int main (int argc, char *argv[]) { @@ -19,6 +52,14 @@ main (int argc, char *argv[]) clutter_init (&argc, &argv); stage = clutter_stage_get_default (); + clutter_stage_hide_cursor (CLUTTER_STAGE (stage)); + + g_signal_connect (stage, "button-press-event", + G_CALLBACK (button_press_cb), + NULL); + g_signal_connect (stage, "scroll-event", + G_CALLBACK (scroll_event_cb), + NULL); g_signal_connect (stage, "key-press-event", G_CALLBACK (clutter_main_quit), NULL); @@ -61,7 +102,7 @@ main (int argc, char *argv[]) /* Set an alpha func to power behaviour - ramp is constant rise/fall */ alpha = clutter_alpha_new_full (timeline, - CLUTTER_ALPHA_RAMP, + CLUTTER_ALPHA_SINE, NULL, NULL); /* Create a behaviour for that alpha */ diff --git a/examples/super-oh.c b/examples/super-oh.c index aa601b8a3..8dbde9c2a 100644 --- a/examples/super-oh.c +++ b/examples/super-oh.c @@ -1,6 +1,6 @@ #include #ifdef CLUTTER_FLAVOUR_GLX -#include +#include #endif #include #include @@ -41,28 +41,31 @@ void screensaver_setup (void) { #ifdef CLUTTER_FLAVOUR_GLX - Window remote_xwindow; - const char *preview_xid; - gboolean foreign_success = FALSE; + const gchar *preview_xid; + gboolean foreign_success = FALSE; + ClutterActor *stage; + + stage = clutter_stage_get_default (); preview_xid = g_getenv ("XSCREENSAVER_WINDOW"); - if (preview_xid != NULL) + if (preview_xid && *preview_xid) { char *end; - remote_xwindow = (Window) strtoul (preview_xid, &end, 0); + Window remote_xwin = (Window) strtoul (preview_xid, &end, 0); - if ((remote_xwindow != 0) && (end != NULL) && + if ((remote_xwin != None) && (end != NULL) && ((*end == ' ') || (*end == '\0')) && - ((remote_xwindow < G_MAXULONG) || (errno != ERANGE))) + ((remote_xwin < G_MAXULONG) || (errno != ERANGE))) { - foreign_success = clutter_stage_glx_set_window_foreign - (CLUTTER_STAGE(clutter_stage_get_default()), remote_xwindow); + + foreign_success = + clutter_glx_stage_set_foreign (CLUTTER_STAGE (stage), remote_xwin); } } if (!foreign_success) - clutter_actor_set_size (clutter_stage_get_default(), 800, 600); + clutter_actor_set_size (stage, 800, 600); #endif } @@ -76,18 +79,20 @@ input_cb (ClutterStage *stage, if (event->type == CLUTTER_BUTTON_PRESS) { - ClutterButtonEvent *bev = (ClutterButtonEvent *) event; + ClutterButtonEvent *button_event; ClutterActor *e; + gint x, y; + clutter_event_get_coords (event, &x, &y); + + button_event = (ClutterButtonEvent *) event; g_print ("*** button press event (button:%d) ***\n", - bev->button); + button_event->button); - e = clutter_stage_get_actor_at_pos (stage, - clutter_button_event_x (bev), - clutter_button_event_y (bev)); + e = clutter_stage_get_actor_at_pos (stage, x, y); if (e) - clutter_actor_hide(e); + clutter_actor_hide (e); } else if (event->type == CLUTTER_KEY_RELEASE) { diff --git a/examples/test.c b/examples/test.c index 9c83e0c7d..c4874e8ba 100644 --- a/examples/test.c +++ b/examples/test.c @@ -63,6 +63,22 @@ para_cb (ClutterTimeline *timeline, } +static void +key_press_cb (ClutterStage *stage, + ClutterKeyEvent *event, + gpointer data) +{ + g_print ("key-press-event\n"); +} + +static void +key_release_cb (ClutterStage *stage, + ClutterKeyEvent *event, + gpointer data) +{ + g_print ("key-release-event\n"); +} + int main (int argc, char *argv[]) { @@ -75,6 +91,10 @@ main (int argc, char *argv[]) clutter_init (&argc, &argv); stage = clutter_stage_get_default (); + g_signal_connect (stage, "key-press-event", + G_CALLBACK (key_press_cb), NULL); + g_signal_connect (stage, "key-release-event", + G_CALLBACK (key_release_cb), NULL); g_signal_connect (stage, "button-press-event", G_CALLBACK (clutter_main_quit), NULL);