2007-11-15 Matthew Allum <mallum@openedhand.com>
* clutter/Makefile.am: * clutter/eglx/Makefile.am: * clutter/eglx/clutter-backend-egl.c: * clutter/eglx/clutter-backend-egl.h: * clutter/eglx/clutter-eglx.h: * clutter/eglx/clutter-event-egl.c: * clutter/eglx/clutter-stage-egl.c: * clutter/eglx/clutter-stage-egl.h: * clutter/glx/Makefile.am: * clutter/glx/clutter-backend-glx.c: * clutter/glx/clutter-backend-glx.h: * clutter/glx/clutter-event-glx.c: * clutter/glx/clutter-glx.h: * clutter/glx/clutter-stage-glx.c: * clutter/glx/clutter-stage-glx.h: * clutter/x11/Makefile.am: * clutter/x11/clutter-backend-x11-private.h: * clutter/x11/clutter-backend-x11.c: * clutter/x11/clutter-backend-x11.h: * clutter/x11/clutter-event-x11.c: * clutter/x11/clutter-stage-x11.c: * clutter/x11/clutter-stage-x11.h: * clutter/x11/clutter-x11.h: Create a new X11 backend class of which EGL and GLX 'real' backends then subclass. Effectively shares all X11 code between both backends avoids code duplication and brings many missing features to EGL X backend. Requires some cleanup and testing. (#518) * clutter/cogl/gles/cogl.c: (cogl_color): Add define to use color4ub only if configure finds it. If not fall back to old code. * configure.ac: Drop support for vincent checks. Drop sdles backend. Specifically check for color4ub call.
This commit is contained in:
parent
a9efed235e
commit
3607a470aa
31
ChangeLog
31
ChangeLog
@ -1,3 +1,34 @@
|
|||||||
|
2007-11-15 Matthew Allum <mallum@openedhand.com>
|
||||||
|
|
||||||
|
reviewed by: <delete if not using a buddy>
|
||||||
|
|
||||||
|
* clutter/Makefile.am:
|
||||||
|
* clutter/cogl/gles/cogl.c: (cogl_color):
|
||||||
|
* clutter/eglx/Makefile.am:
|
||||||
|
* clutter/eglx/clutter-backend-egl.c:
|
||||||
|
* clutter/eglx/clutter-backend-egl.h:
|
||||||
|
* clutter/eglx/clutter-eglx.h:
|
||||||
|
* clutter/eglx/clutter-event-egl.c:
|
||||||
|
* clutter/eglx/clutter-stage-egl.c: (clutter_stage_egl_realize):
|
||||||
|
* clutter/eglx/clutter-stage-egl.h:
|
||||||
|
* clutter/glx/Makefile.am:
|
||||||
|
* clutter/glx/clutter-backend-glx.c:
|
||||||
|
(clutter_backend_glx_pre_parse):
|
||||||
|
* clutter/glx/clutter-backend-glx.h:
|
||||||
|
* clutter/glx/clutter-event-glx.c:
|
||||||
|
* clutter/glx/clutter-glx.h:
|
||||||
|
* clutter/glx/clutter-stage-glx.c: (clutter_stage_glx_realize):
|
||||||
|
* clutter/glx/clutter-stage-glx.h:
|
||||||
|
* clutter/x11/Makefile.am:
|
||||||
|
* clutter/x11/clutter-backend-x11-private.h:
|
||||||
|
* clutter/x11/clutter-backend-x11.c:
|
||||||
|
* clutter/x11/clutter-backend-x11.h:
|
||||||
|
* clutter/x11/clutter-event-x11.c:
|
||||||
|
* clutter/x11/clutter-stage-x11.c:
|
||||||
|
* clutter/x11/clutter-stage-x11.h:
|
||||||
|
* clutter/x11/clutter-x11.h:
|
||||||
|
* configure.ac:
|
||||||
|
|
||||||
2007-11-15 Neil J. Patel <njp@o-hand.com>
|
2007-11-15 Neil J. Patel <njp@o-hand.com>
|
||||||
|
|
||||||
* clutter/Makefile.am:
|
* clutter/Makefile.am:
|
||||||
|
6
README
6
README
@ -129,6 +129,12 @@ RELEASE NOTES
|
|||||||
Relevant information for developers with existing Clutter applications
|
Relevant information for developers with existing Clutter applications
|
||||||
wanting to port to newer releases (See NEWS for general new feature info).
|
wanting to port to newer releases (See NEWS for general new feature info).
|
||||||
|
|
||||||
|
Release Notes for Clutter 0.6.0
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
* X11 related called for glx and eglx backends are now shared and moved into
|
||||||
|
a clutter_x11 prefix.
|
||||||
|
|
||||||
Release Notes for Clutter 0.4.0
|
Release Notes for Clutter 0.4.0
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
NULL =
|
NULL =
|
||||||
|
|
||||||
SUBDIRS = cogl pango json $(clutterbackend)
|
SUBDIRS = cogl pango json $(clutterbackend) $(backendextra)
|
||||||
|
|
||||||
DIST_SUBDIRS = pango glx eglx eglnative cogl sdl json osx
|
DIST_SUBDIRS = pango glx eglx eglnative cogl sdl json osx x11
|
||||||
|
|
||||||
target = $(clutterbackend)
|
target = $(clutterbackend)
|
||||||
|
|
||||||
@ -181,7 +181,8 @@ libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_API_VERSION@_la_LIBADD = \
|
|||||||
pango/libpangoclutter.la \
|
pango/libpangoclutter.la \
|
||||||
@CLUTTER_FLAVOUR@/libclutter-@CLUTTER_FLAVOUR@.la \
|
@CLUTTER_FLAVOUR@/libclutter-@CLUTTER_FLAVOUR@.la \
|
||||||
cogl/@CLUTTER_COGL@/libclutter-cogl.la \
|
cogl/@CLUTTER_COGL@/libclutter-cogl.la \
|
||||||
json/libclutter-json.la
|
json/libclutter-json.la \
|
||||||
|
$(backendextralib)
|
||||||
|
|
||||||
libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_API_VERSION@_la_SOURCES = \
|
libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_API_VERSION@_la_SOURCES = \
|
||||||
$(source_c) $(source_h) $(source_h_priv)
|
$(source_c) $(source_h) $(source_h_priv)
|
||||||
|
@ -239,9 +239,10 @@ cogl_enable (gulong flags)
|
|||||||
void
|
void
|
||||||
cogl_color (const ClutterColor *color)
|
cogl_color (const ClutterColor *color)
|
||||||
{
|
{
|
||||||
|
#if HAVE_GLES_COLOR4UB
|
||||||
/*
|
/*
|
||||||
* GLES 1.1 does actually have this function, it's in the header file but
|
* GLES 1.1 does actually have this function, it's in the header file but
|
||||||
* missing in the reference manual:
|
* missing in the reference manual (and SDK):
|
||||||
*
|
*
|
||||||
* http://www.khronos.org/egl/headers/1_1/gl.h
|
* http://www.khronos.org/egl/headers/1_1/gl.h
|
||||||
*/
|
*/
|
||||||
@ -249,6 +250,13 @@ cogl_color (const ClutterColor *color)
|
|||||||
color->green,
|
color->green,
|
||||||
color->blue,
|
color->blue,
|
||||||
color->alpha) );
|
color->alpha) );
|
||||||
|
#else
|
||||||
|
/* conversion can cause issues with picking on some gles implementations */
|
||||||
|
GE( glColor4x ((color->red << 16) / 0xff,
|
||||||
|
(color->green << 16) / 0xff,
|
||||||
|
(color->blue << 16) / 0xff,
|
||||||
|
(color->alpha << 16) / 0xff));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -8,14 +8,14 @@ INCLUDES = \
|
|||||||
$(CLUTTER_DEBUG_CFLAGS) \
|
$(CLUTTER_DEBUG_CFLAGS) \
|
||||||
$(GCC_FLAGS)
|
$(GCC_FLAGS)
|
||||||
|
|
||||||
LDADD = $(CLUTTER_LIBS)
|
LDADD = $(CLUTTER_LIBS) \
|
||||||
|
$(top_srcdir)/clutter/x11/libclutter-x11.la
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libclutter-eglx.la
|
noinst_LTLIBRARIES = libclutter-eglx.la
|
||||||
|
|
||||||
libclutter_eglx_la_SOURCES = \
|
libclutter_eglx_la_SOURCES = \
|
||||||
clutter-backend-egl.h \
|
clutter-backend-egl.h \
|
||||||
clutter-backend-egl.c \
|
clutter-backend-egl.c \
|
||||||
clutter-event-egl.c \
|
|
||||||
clutter-stage-egl.h \
|
clutter-stage-egl.h \
|
||||||
clutter-stage-egl.c \
|
clutter-stage-egl.c \
|
||||||
clutter-eglx.h
|
clutter-eglx.h
|
||||||
|
@ -10,79 +10,20 @@
|
|||||||
|
|
||||||
static ClutterBackendEGL *backend_singleton = NULL;
|
static ClutterBackendEGL *backend_singleton = NULL;
|
||||||
|
|
||||||
/* options */
|
G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND_X11);
|
||||||
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 *);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND);
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_backend_egl_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
|
static gboolean
|
||||||
clutter_backend_egl_post_parse (ClutterBackend *backend,
|
clutter_backend_egl_post_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
if (clutter_display_name)
|
if (clutter_backend_x11_post_parse (backend, error))
|
||||||
{
|
|
||||||
backend_egl->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_egl->xdpy)
|
|
||||||
{
|
{
|
||||||
EGLBoolean status;
|
EGLBoolean status;
|
||||||
double dpi;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "Getting the X screen");
|
backend_egl->edpy = eglGetDisplay((NativeDisplayType)backend_x11->xdpy);
|
||||||
|
|
||||||
if (clutter_screen == 0)
|
|
||||||
backend_egl->xscreen = DefaultScreenOfDisplay (backend_egl->xdpy);
|
|
||||||
else
|
|
||||||
backend_egl->xscreen = ScreenOfDisplay (backend_egl->xdpy,
|
|
||||||
clutter_screen);
|
|
||||||
|
|
||||||
backend_egl->xscreen_num = XScreenNumberOfScreen (backend_egl->xscreen);
|
|
||||||
backend_egl->xwin_root = RootWindow (backend_egl->xdpy,
|
|
||||||
backend_egl->xscreen_num);
|
|
||||||
|
|
||||||
backend_egl->display_name = g_strdup (clutter_display_name);
|
|
||||||
|
|
||||||
backend_egl->edpy = eglGetDisplay((NativeDisplayType)backend_egl->xdpy);
|
|
||||||
|
|
||||||
dpi = (((double) DisplayHeight (backend_egl->xdpy, backend_egl->xscreen_num) * 25.4)
|
|
||||||
/ (double) DisplayHeightMM (backend_egl->xdpy, backend_egl->xscreen_num));
|
|
||||||
clutter_backend_set_resolution (backend, dpi);
|
|
||||||
|
|
||||||
status = eglInitialize(backend_egl->edpy,
|
status = eglInitialize(backend_egl->edpy,
|
||||||
&backend_egl->egl_version_major,
|
&backend_egl->egl_version_major,
|
||||||
@ -98,14 +39,6 @@ clutter_backend_egl_post_parse (ClutterBackend *backend,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (clutter_display_name);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "X Display `%s' [%p] opened (screen:%d, root:%u)",
|
|
||||||
backend_egl->display_name,
|
|
||||||
backend_egl->xdpy,
|
|
||||||
backend_egl->xscreen_num,
|
|
||||||
(unsigned int) backend_egl->xwin_root);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "EGL Reports version %i.%i",
|
CLUTTER_NOTE (BACKEND, "EGL Reports version %i.%i",
|
||||||
backend_egl->egl_version_major,
|
backend_egl->egl_version_major,
|
||||||
backend_egl->egl_version_minor);
|
backend_egl->egl_version_minor);
|
||||||
@ -113,80 +46,23 @@ clutter_backend_egl_post_parse (ClutterBackend *backend,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_backend_egl_init_stage (ClutterBackend *backend,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
|
|
||||||
if (!backend_egl->stage)
|
|
||||||
{
|
|
||||||
ClutterStageEGL *stage_egl;
|
|
||||||
ClutterActor *stage;
|
|
||||||
|
|
||||||
stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
|
|
||||||
|
|
||||||
/* copy backend data into the stage */
|
|
||||||
stage_egl = CLUTTER_STAGE_EGL (stage);
|
|
||||||
stage_egl->xdpy = backend_egl->xdpy;
|
|
||||||
stage_egl->xwin_root = backend_egl->xwin_root;
|
|
||||||
stage_egl->xscreen = backend_egl->xscreen_num;
|
|
||||||
|
|
||||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
|
||||||
|
|
||||||
backend_egl->stage = g_object_ref_sink (stage);
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_actor_realize (backend_egl->stage);
|
|
||||||
if (!CLUTTER_ACTOR_IS_REALIZED (backend_egl->stage))
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_INTERNAL,
|
|
||||||
"Unable to realize the main stage");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_backend_egl_init_events (ClutterBackend *backend)
|
|
||||||
{
|
|
||||||
_clutter_events_init (backend);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
static void
|
||||||
clutter_backend_egl_redraw (ClutterBackend *backend)
|
clutter_backend_egl_redraw (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
ClutterStageEGL *stage_egl;
|
ClutterStageEGL *stage_egl;
|
||||||
|
ClutterStageX11 *stage_x11;
|
||||||
|
|
||||||
stage_egl = CLUTTER_STAGE_EGL(backend_egl->stage);
|
stage_x11 = CLUTTER_STAGE_X11(backend_x11->stage);
|
||||||
|
stage_egl = CLUTTER_STAGE_EGL(backend_x11->stage);
|
||||||
|
|
||||||
clutter_actor_paint (CLUTTER_ACTOR(stage_egl));
|
clutter_actor_paint (CLUTTER_ACTOR(stage_egl));
|
||||||
|
|
||||||
/* Why this paint is done in backend as likely GL windowing system
|
/* Why this paint is done in backend as likely GL windowing system
|
||||||
* specific calls, like swapping buffers.
|
* specific calls, like swapping buffers.
|
||||||
*/
|
*/
|
||||||
if (stage_egl->xwin)
|
if (stage_x11->xwin)
|
||||||
{
|
{
|
||||||
/* clutter_feature_wait_for_vblank (); */
|
/* clutter_feature_wait_for_vblank (); */
|
||||||
eglSwapBuffers (backend_egl->edpy, stage_egl->egl_surface);
|
eglSwapBuffers (backend_egl->edpy, stage_egl->egl_surface);
|
||||||
@ -198,30 +74,9 @@ clutter_backend_egl_redraw (ClutterBackend *backend)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_backend_egl_add_options (ClutterBackend *backend,
|
|
||||||
GOptionGroup *group)
|
|
||||||
{
|
|
||||||
g_option_group_add_entries (group, entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClutterActor *
|
|
||||||
clutter_backend_egl_get_stage (ClutterBackend *backend)
|
|
||||||
{
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
|
|
||||||
return backend_egl->stage;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_egl_finalize (GObject *gobject)
|
clutter_backend_egl_finalize (GObject *gobject)
|
||||||
{
|
{
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
|
|
||||||
|
|
||||||
g_free (backend_egl->display_name);
|
|
||||||
|
|
||||||
XCloseDisplay (backend_egl->xdpy);
|
|
||||||
|
|
||||||
if (backend_singleton)
|
if (backend_singleton)
|
||||||
backend_singleton = NULL;
|
backend_singleton = NULL;
|
||||||
|
|
||||||
@ -231,16 +86,6 @@ clutter_backend_egl_finalize (GObject *gobject)
|
|||||||
static void
|
static void
|
||||||
clutter_backend_egl_dispose (GObject *gobject)
|
clutter_backend_egl_dispose (GObject *gobject)
|
||||||
{
|
{
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
|
|
||||||
|
|
||||||
_clutter_events_uninit (CLUTTER_BACKEND (backend_egl));
|
|
||||||
|
|
||||||
if (backend_egl->stage)
|
|
||||||
{
|
|
||||||
clutter_actor_destroy (backend_egl->stage);
|
|
||||||
backend_egl->stage = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_backend_egl_parent_class)->dispose (gobject);
|
G_OBJECT_CLASS (clutter_backend_egl_parent_class)->dispose (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,6 +120,49 @@ clutter_backend_egl_get_features (ClutterBackend *backend)
|
|||||||
return CLUTTER_FEATURE_STAGE_CURSOR;
|
return CLUTTER_FEATURE_STAGE_CURSOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_backend_egl_init_stage (ClutterBackend *backend,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
|
if (!backend_x11->stage)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11;
|
||||||
|
ClutterActor *stage;
|
||||||
|
|
||||||
|
stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
|
||||||
|
|
||||||
|
/* copy backend data into the stage */
|
||||||
|
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
|
stage_x11->xdpy = backend_x11->xdpy;
|
||||||
|
stage_x11->xwin_root = backend_x11->xwin_root;
|
||||||
|
stage_x11->xscreen = backend_x11->xscreen_num;
|
||||||
|
stage_x11->backend = backend_x11;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (MISC, "X11 stage created (display:%p, screen:%d, root:%u)",
|
||||||
|
stage_x11->xdpy,
|
||||||
|
stage_x11->xscreen,
|
||||||
|
(unsigned int) stage_x11->xwin_root);
|
||||||
|
|
||||||
|
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||||
|
|
||||||
|
backend_x11->stage = g_object_ref_sink (stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_actor_realize (backend_x11->stage);
|
||||||
|
|
||||||
|
if (!CLUTTER_ACTOR_IS_REALIZED (backend_x11->stage))
|
||||||
|
{
|
||||||
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
|
CLUTTER_INIT_ERROR_INTERNAL,
|
||||||
|
"Unable to realize the main stage");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
||||||
{
|
{
|
||||||
@ -285,25 +173,16 @@ clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
|||||||
gobject_class->dispose = clutter_backend_egl_dispose;
|
gobject_class->dispose = clutter_backend_egl_dispose;
|
||||||
gobject_class->finalize = clutter_backend_egl_finalize;
|
gobject_class->finalize = clutter_backend_egl_finalize;
|
||||||
|
|
||||||
backend_class->pre_parse = clutter_backend_egl_pre_parse;
|
|
||||||
backend_class->post_parse = clutter_backend_egl_post_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;
|
|
||||||
backend_class->redraw = clutter_backend_egl_redraw;
|
backend_class->redraw = clutter_backend_egl_redraw;
|
||||||
backend_class->get_features = clutter_backend_egl_get_features;
|
backend_class->get_features = clutter_backend_egl_get_features;
|
||||||
|
backend_class->init_stage = clutter_backend_egl_init_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
|
clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
|
||||||
{
|
{
|
||||||
ClutterBackend *backend = CLUTTER_BACKEND (backend_egl);
|
;
|
||||||
|
|
||||||
/* FIXME: get from xsettings */
|
|
||||||
clutter_backend_set_resolution (backend, 96.0);
|
|
||||||
clutter_backend_set_double_click_time (backend, 250);
|
|
||||||
clutter_backend_set_double_click_distance (backend, 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
@ -312,108 +191,6 @@ _clutter_backend_impl_get_type (void)
|
|||||||
return clutter_backend_egl_get_type ();
|
return clutter_backend_egl_get_type ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
error_handler(Display *xdpy,
|
|
||||||
XErrorEvent *error)
|
|
||||||
{
|
|
||||||
TrappedErrorCode = error->error_code;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_eglx_trap_x_errors:
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
clutter_eglx_trap_x_errors (void)
|
|
||||||
{
|
|
||||||
TrappedErrorCode = 0;
|
|
||||||
old_error_handler = XSetErrorHandler (error_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_eglx_untrap_x_errors:
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Return value: FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
gint
|
|
||||||
clutter_eglx_untrap_x_errors (void)
|
|
||||||
{
|
|
||||||
XSetErrorHandler (old_error_handler);
|
|
||||||
|
|
||||||
return TrappedErrorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_eglx_get_default_xdisplay:
|
|
||||||
*
|
|
||||||
* Returns the default X Display
|
|
||||||
*
|
|
||||||
* Return value: A Display pointer
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
Display *
|
|
||||||
clutter_eglx_get_default_xdisplay (void)
|
|
||||||
{
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
|
||||||
g_critical ("EGL backend has not been initialised");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return backend_singleton->xdpy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_eglx_get_default_screen:
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Return value: FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
gint
|
|
||||||
clutter_eglx_get_default_screen (void)
|
|
||||||
{
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
|
||||||
g_critical ("EGL backend has not been initialised");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return backend_singleton->xscreen_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_eglx_get_default_root_window:
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Return value: FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
Window
|
|
||||||
clutter_eglx_get_default_root_window (void)
|
|
||||||
{
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
|
||||||
g_critical ("EGL backend has not been initialised");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
return backend_singleton->xwin_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_egl_display
|
* clutter_egl_display
|
||||||
*
|
*
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define __CLUTTER_BACKEND_EGL_H__
|
#define __CLUTTER_BACKEND_EGL_H__
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-event.h>
|
||||||
#include <clutter/clutter-backend.h>
|
#include <clutter/clutter-backend.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
@ -30,6 +31,9 @@
|
|||||||
#include <GLES/gl.h>
|
#include <GLES/gl.h>
|
||||||
#include <GLES/egl.h>
|
#include <GLES/egl.h>
|
||||||
|
|
||||||
|
#include "../x11/clutter-backend-x11.h"
|
||||||
|
#include "clutter-eglx.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define CLUTTER_TYPE_BACKEND_EGL (clutter_backend_egl_get_type ())
|
#define CLUTTER_TYPE_BACKEND_EGL (clutter_backend_egl_get_type ())
|
||||||
@ -44,37 +48,21 @@ typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
|
|||||||
|
|
||||||
struct _ClutterBackendEGL
|
struct _ClutterBackendEGL
|
||||||
{
|
{
|
||||||
ClutterBackend parent_instance;
|
ClutterBackendX11 parent_instance;
|
||||||
|
|
||||||
Display *xdpy;
|
|
||||||
gchar *display_name;
|
|
||||||
Window xwin_root;
|
|
||||||
int xscreen_num;
|
|
||||||
Screen *xscreen;
|
|
||||||
|
|
||||||
/* EGL Specific */
|
/* EGL Specific */
|
||||||
EGLDisplay edpy;
|
EGLDisplay edpy;
|
||||||
gint egl_version_major, egl_version_minor;
|
gint egl_version_major, egl_version_minor;
|
||||||
|
|
||||||
/* main stage singleton */
|
|
||||||
ClutterActor *stage;
|
|
||||||
|
|
||||||
/* event source */
|
|
||||||
GSource *event_source;
|
|
||||||
|
|
||||||
/*< private >*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendEGLClass
|
struct _ClutterBackendEGLClass
|
||||||
{
|
{
|
||||||
ClutterBackendClass parent_class;
|
ClutterBackendX11Class parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType clutter_backend_egl_get_type (void) G_GNUC_CONST;
|
GType clutter_backend_egl_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
void _clutter_events_init (ClutterBackend *backend);
|
|
||||||
void _clutter_events_uninit (ClutterBackend *backend);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_BACKEND_EGL_H__ */
|
#endif /* __CLUTTER_BACKEND_EGL_H__ */
|
||||||
|
@ -39,19 +39,6 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void clutter_eglx_trap_x_errors (void);
|
|
||||||
gint clutter_eglx_untrap_x_errors (void);
|
|
||||||
|
|
||||||
Display *clutter_eglx_get_default_xdisplay (void);
|
|
||||||
gint clutter_eglx_get_default_screen (void);
|
|
||||||
Window clutter_eglx_get_default_root_window (void);
|
|
||||||
|
|
||||||
Window clutter_eglx_get_stage_window (ClutterStage *stage);
|
|
||||||
XVisualInfo *clutter_eglx_get_stage_visual (ClutterStage *stage);
|
|
||||||
|
|
||||||
void clutter_eglx_set_stage_foreign (ClutterStage *stage,
|
|
||||||
Window window);
|
|
||||||
|
|
||||||
EGLDisplay
|
EGLDisplay
|
||||||
clutter_eglx_display (void);
|
clutter_eglx_display (void);
|
||||||
|
|
||||||
|
@ -1,382 +0,0 @@
|
|||||||
/* Clutter.
|
|
||||||
* An OpenGL based 'interactive canvas' library.
|
|
||||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
|
||||||
* Copyright (C) 2006-2007 OpenedHand
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, 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-stage-egl.h"
|
|
||||||
#include "clutter-backend-egl.h"
|
|
||||||
#include "clutter-eglx.h"
|
|
||||||
|
|
||||||
#include "../clutter-backend.h"
|
|
||||||
#include "../clutter-event.h"
|
|
||||||
#include "../clutter-private.h"
|
|
||||||
#include "../clutter-debug.h"
|
|
||||||
#include "../clutter-main.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_XFIXES
|
|
||||||
#include <X11/extensions/Xfixes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <X11/Xatom.h>
|
|
||||||
|
|
||||||
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_EGL (backend)->xdpy);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_events_init (ClutterBackend *backend)
|
|
||||||
{
|
|
||||||
GSource *source;
|
|
||||||
ClutterEventSource *event_source;
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
int connection_number;
|
|
||||||
|
|
||||||
connection_number = ConnectionNumber (backend_egl->xdpy);
|
|
||||||
CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number);
|
|
||||||
|
|
||||||
source = backend_egl->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)
|
|
||||||
{
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
|
|
||||||
if (backend_egl->event_source)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (EVENT, "Destroying the event source");
|
|
||||||
|
|
||||||
event_sources = g_list_remove (event_sources,
|
|
||||||
backend_egl->event_source);
|
|
||||||
|
|
||||||
g_source_destroy (backend_egl->event_source);
|
|
||||||
g_source_unref (backend_egl->event_source);
|
|
||||||
backend_egl->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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
ClutterBackendEGL *backend_egl;
|
|
||||||
ClutterStage *stage;
|
|
||||||
gboolean res;
|
|
||||||
Window xwindow, stage_xwindow;
|
|
||||||
|
|
||||||
backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend));
|
|
||||||
stage_xwindow = clutter_eglx_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_egl->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_egl->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;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_user_time (backend_egl->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:
|
|
||||||
CLUTTER_NOTE (EVENT, "destroy notify:\twindow: %ld",
|
|
||||||
xevent->xdestroywindow.window);
|
|
||||||
event->type = event->any.type = CLUTTER_DESTROY_NOTIFY;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* ignore every other event */
|
|
||||||
res = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
events_queue (ClutterBackend *backend)
|
|
||||||
{
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
ClutterEvent *event;
|
|
||||||
XEvent xevent;
|
|
||||||
ClutterMainContext *clutter_context;
|
|
||||||
|
|
||||||
clutter_context = clutter_context_get_default ();
|
|
||||||
|
|
||||||
Display *xdisplay = backend_egl->xdpy;
|
|
||||||
|
|
||||||
while (!clutter_events_pending () && XPending (xdisplay))
|
|
||||||
{
|
|
||||||
XNextEvent (xdisplay, &xevent);
|
|
||||||
|
|
||||||
event = clutter_event_new (CLUTTER_NOTHING);
|
|
||||||
if (clutter_event_translate (backend, event, &xevent))
|
|
||||||
{
|
|
||||||
g_queue_push_head (clutter_context->events_queue, event);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clutter_event_free (event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_event_prepare (GSource *source,
|
|
||||||
gint *timeout)
|
|
||||||
{
|
|
||||||
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
clutter_threads_enter ();
|
|
||||||
|
|
||||||
*timeout = -1;
|
|
||||||
retval = (clutter_events_pending () || clutter_check_xpending (backend));
|
|
||||||
|
|
||||||
clutter_threads_leave ();
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_event_check (GSource *source)
|
|
||||||
{
|
|
||||||
ClutterEventSource *event_source = (ClutterEventSource *) source;
|
|
||||||
ClutterBackend *backend = event_source->backend;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
clutter_threads_enter ();
|
|
||||||
|
|
||||||
if (event_source->event_poll_fd.revents & G_IO_IN)
|
|
||||||
retval = (clutter_events_pending () || clutter_check_xpending (backend));
|
|
||||||
else
|
|
||||||
retval = FALSE;
|
|
||||||
|
|
||||||
clutter_threads_leave ();
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_event_dispatch (GSource *source,
|
|
||||||
GSourceFunc callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
|
||||||
ClutterEvent *event;
|
|
||||||
|
|
||||||
clutter_threads_enter ();
|
|
||||||
|
|
||||||
events_queue (backend);
|
|
||||||
|
|
||||||
event = clutter_event_get ();
|
|
||||||
|
|
||||||
if (event)
|
|
||||||
{
|
|
||||||
clutter_do_event (event);
|
|
||||||
clutter_event_free (event);
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_threads_leave ();
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
@ -15,39 +15,13 @@
|
|||||||
#include "../clutter-debug.h"
|
#include "../clutter-debug.h"
|
||||||
#include "../clutter-units.h"
|
#include "../clutter-units.h"
|
||||||
|
|
||||||
#ifdef HAVE_XFIXES
|
G_DEFINE_TYPE (ClutterStageEGL, clutter_stage_egl, CLUTTER_TYPE_STAGE_X11);
|
||||||
#include <X11/extensions/Xfixes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterStageEGL, clutter_stage_egl, CLUTTER_TYPE_STAGE);
|
|
||||||
|
|
||||||
/* This is currently an EGL on X implementation (eg for use with vincent)
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_egl_show (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
|
||||||
|
|
||||||
if (stage_egl->xwin)
|
|
||||||
XMapWindow (stage_egl->xdpy, stage_egl->xwin);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_egl_hide (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
|
||||||
|
|
||||||
if (stage_egl->xwin)
|
|
||||||
XUnmapWindow (stage_egl->xdpy, stage_egl->xwin);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_egl_unrealize (ClutterActor *actor)
|
clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||||
gboolean was_offscreen;
|
gboolean was_offscreen;
|
||||||
|
|
||||||
CLUTTER_MARK();
|
CLUTTER_MARK();
|
||||||
@ -60,13 +34,13 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (stage_egl->xwin != None)
|
if (stage_x11->xwin != None)
|
||||||
{
|
{
|
||||||
XDestroyWindow (stage_egl->xdpy, stage_egl->xwin);
|
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
|
||||||
stage_egl->xwin = None;
|
stage_x11->xwin = None;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
stage_egl->xwin = None;
|
stage_x11->xwin = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage_egl->egl_surface)
|
if (stage_egl->egl_surface)
|
||||||
@ -87,6 +61,7 @@ static void
|
|||||||
clutter_stage_egl_realize (ClutterActor *actor)
|
clutter_stage_egl_realize (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||||
|
|
||||||
EGLConfig configs[2];
|
EGLConfig configs[2];
|
||||||
EGLint config_count;
|
EGLint config_count;
|
||||||
@ -123,19 +98,19 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
|||||||
if (status != EGL_TRUE)
|
if (status != EGL_TRUE)
|
||||||
g_warning ("eglChooseConfig");
|
g_warning ("eglChooseConfig");
|
||||||
|
|
||||||
if (stage_egl->xwin == None)
|
if (stage_x11->xwin == None)
|
||||||
stage_egl->xwin
|
stage_x11->xwin
|
||||||
= XCreateSimpleWindow(clutter_eglx_get_default_xdisplay(),
|
= XCreateSimpleWindow(stage_x11->xdpy,
|
||||||
clutter_eglx_get_default_root_window(),
|
stage_x11->xwin_root,
|
||||||
0, 0,
|
0, 0,
|
||||||
stage_egl->xwin_width,
|
stage_x11->xwin_width,
|
||||||
stage_egl->xwin_height,
|
stage_x11->xwin_height,
|
||||||
0, 0,
|
0, 0,
|
||||||
WhitePixel(clutter_eglx_get_default_xdisplay(),
|
WhitePixel (stage_x11->xdpy,
|
||||||
clutter_eglx_get_default_screen()));
|
stage_x11->xscreen));
|
||||||
|
|
||||||
XSelectInput(clutter_eglx_get_default_xdisplay(),
|
XSelectInput(stage_x11->xdpy,
|
||||||
stage_egl->xwin,
|
stage_x11->xwin,
|
||||||
StructureNotifyMask
|
StructureNotifyMask
|
||||||
|ExposureMask
|
|ExposureMask
|
||||||
/* FIXME: we may want to eplicity enable MotionMask */
|
/* FIXME: we may want to eplicity enable MotionMask */
|
||||||
@ -155,7 +130,7 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
|||||||
stage_egl->egl_surface
|
stage_egl->egl_surface
|
||||||
= eglCreateWindowSurface (clutter_eglx_display(),
|
= eglCreateWindowSurface (clutter_eglx_display(),
|
||||||
configs[0],
|
configs[0],
|
||||||
(NativeWindowType)stage_egl->xwin,
|
(NativeWindowType)stage_x11->xwin,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
||||||
@ -176,8 +151,6 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
|||||||
|
|
||||||
if (status != EGL_TRUE)
|
if (status != EGL_TRUE)
|
||||||
g_warning ("eglMakeCurrent");
|
g_warning ("eglMakeCurrent");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -187,137 +160,6 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
|||||||
CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES);
|
CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_egl_query_coords (ClutterActor *self,
|
|
||||||
ClutterActorBox *box)
|
|
||||||
{
|
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self);
|
|
||||||
|
|
||||||
box->x1 = box->y1 = 0;
|
|
||||||
box->x2 = box->x1 + CLUTTER_UNITS_FROM_INT (stage_egl->xwin_width);
|
|
||||||
box->y2 = box->y1 + CLUTTER_UNITS_FROM_INT (stage_egl->xwin_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_egl_request_coords (ClutterActor *self,
|
|
||||||
ClutterActorBox *box)
|
|
||||||
{
|
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self);
|
|
||||||
gint new_width, new_height;
|
|
||||||
|
|
||||||
/* FIXME: some how have X configure_notfiys call this ? */
|
|
||||||
new_width = ABS (CLUTTER_UNITS_TO_INT (box->x2 - box->x1));
|
|
||||||
new_height = ABS (CLUTTER_UNITS_TO_INT (box->y2 - box->y1));
|
|
||||||
|
|
||||||
if (new_width != stage_egl->xwin_width ||
|
|
||||||
new_height != stage_egl->xwin_height)
|
|
||||||
{
|
|
||||||
stage_egl->xwin_width = new_width;
|
|
||||||
stage_egl->xwin_height = new_height;
|
|
||||||
|
|
||||||
if (stage_egl->xwin != None)
|
|
||||||
XResizeWindow (stage_egl->xdpy,
|
|
||||||
stage_egl->xwin,
|
|
||||||
stage_egl->xwin_width,
|
|
||||||
stage_egl->xwin_height);
|
|
||||||
|
|
||||||
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stage_egl->xwin != None) /* Do we want to bother ? */
|
|
||||||
XMoveWindow (stage_egl->xdpy,
|
|
||||||
stage_egl->xwin,
|
|
||||||
CLUTTER_UNITS_TO_INT (box->x1),
|
|
||||||
CLUTTER_UNITS_TO_INT (box->y1));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_egl_set_fullscreen (ClutterStage *stage,
|
|
||||||
gboolean fullscreen)
|
|
||||||
{
|
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage);
|
|
||||||
Atom atom_WM_STATE, atom_WM_STATE_FULLSCREEN;
|
|
||||||
|
|
||||||
atom_WM_STATE = XInternAtom (stage_egl->xdpy, "_NET_WM_STATE", False);
|
|
||||||
atom_WM_STATE_FULLSCREEN = XInternAtom (stage_egl->xdpy,
|
|
||||||
"_NET_WM_STATE_FULLSCREEN",
|
|
||||||
False);
|
|
||||||
|
|
||||||
if (fullscreen)
|
|
||||||
{
|
|
||||||
gint width, height;
|
|
||||||
|
|
||||||
width = DisplayWidth (stage_egl->xdpy, stage_egl->xscreen);
|
|
||||||
height = DisplayHeight (stage_egl->xdpy, stage_egl->xscreen);
|
|
||||||
|
|
||||||
clutter_actor_set_size (CLUTTER_ACTOR (stage_egl), width, height);
|
|
||||||
|
|
||||||
if (stage_egl->xwin != None)
|
|
||||||
XChangeProperty (stage_egl->xdpy,
|
|
||||||
stage_egl->xwin,
|
|
||||||
atom_WM_STATE, XA_ATOM, 32,
|
|
||||||
PropModeReplace,
|
|
||||||
(unsigned char *) &atom_WM_STATE_FULLSCREEN, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (stage_egl->xwin != None)
|
|
||||||
XDeleteProperty (stage_egl->xdpy, stage_egl->xwin, atom_WM_STATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_egl_set_cursor_visible (ClutterStage *stage,
|
|
||||||
gboolean show_cursor)
|
|
||||||
{
|
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage);
|
|
||||||
|
|
||||||
if (stage_egl->xwin == None)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "setting cursor state (%s) over stage window (%u)",
|
|
||||||
show_cursor ? "visible" : "invisible",
|
|
||||||
(unsigned int) stage_egl->xwin);
|
|
||||||
|
|
||||||
if (show_cursor)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XFIXES
|
|
||||||
XFixesShowCursor (stage_egl->xdpy, stage_egl->xwin);
|
|
||||||
#else
|
|
||||||
XUndefineCursor (stage_egl->xdpy, stage_egl->xwin);
|
|
||||||
#endif /* HAVE_XFIXES */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XFIXES
|
|
||||||
XFixesHideCursor (stage_egl->xdpy, stage_egl->xwin);
|
|
||||||
#else
|
|
||||||
XColor col;
|
|
||||||
Pixmap pix;
|
|
||||||
Cursor curs;
|
|
||||||
|
|
||||||
pix = XCreatePixmap (stage_egl->xdpy, stage_egl->xwin, 1, 1, 1);
|
|
||||||
memset (&col, 0, sizeof (col));
|
|
||||||
curs = XCreatePixmapCursor (stage_egl->xdpy,
|
|
||||||
pix, pix,
|
|
||||||
&col, &col,
|
|
||||||
1, 1);
|
|
||||||
XFreePixmap (stage_egl->xdpy, pix);
|
|
||||||
XDefineCursor (stage_egl->xdpy, stage_egl->xwin, curs);
|
|
||||||
#endif /* HAVE_XFIXES */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_egl_set_offscreen (ClutterStage *stage,
|
|
||||||
gboolean offscreen)
|
|
||||||
{
|
|
||||||
g_warning ("Stage of type `%s' do not support ClutterStage::set_offscreen",
|
|
||||||
G_OBJECT_TYPE_NAME (stage));
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdkPixbuf*
|
static GdkPixbuf*
|
||||||
clutter_stage_egl_draw_to_pixbuf (ClutterStage *stage,
|
clutter_stage_egl_draw_to_pixbuf (ClutterStage *stage,
|
||||||
gint x,
|
gint x,
|
||||||
@ -334,8 +176,9 @@ static void
|
|||||||
clutter_stage_egl_dispose (GObject *gobject)
|
clutter_stage_egl_dispose (GObject *gobject)
|
||||||
{
|
{
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||||
|
|
||||||
if (stage_egl->xwin)
|
if (stage_x11->xwin)
|
||||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl));
|
clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl));
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
||||||
@ -350,83 +193,15 @@ clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
|||||||
|
|
||||||
gobject_class->dispose = clutter_stage_egl_dispose;
|
gobject_class->dispose = clutter_stage_egl_dispose;
|
||||||
|
|
||||||
actor_class->show = clutter_stage_egl_show;
|
|
||||||
actor_class->hide = clutter_stage_egl_hide;
|
|
||||||
actor_class->realize = clutter_stage_egl_realize;
|
actor_class->realize = clutter_stage_egl_realize;
|
||||||
actor_class->unrealize = clutter_stage_egl_unrealize;
|
actor_class->unrealize = clutter_stage_egl_unrealize;
|
||||||
actor_class->request_coords = clutter_stage_egl_request_coords;
|
|
||||||
actor_class->query_coords = clutter_stage_egl_query_coords;
|
|
||||||
|
|
||||||
stage_class->set_fullscreen = clutter_stage_egl_set_fullscreen;
|
|
||||||
stage_class->set_cursor_visible = clutter_stage_egl_set_cursor_visible;
|
|
||||||
stage_class->set_offscreen = clutter_stage_egl_set_offscreen;
|
|
||||||
stage_class->draw_to_pixbuf = clutter_stage_egl_draw_to_pixbuf;
|
stage_class->draw_to_pixbuf = clutter_stage_egl_draw_to_pixbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_egl_init (ClutterStageEGL *stage)
|
clutter_stage_egl_init (ClutterStageEGL *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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_eglx_get_stage_window:
|
|
||||||
* @stage: a #ClutterStage
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Return value: FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
Window
|
|
||||||
clutter_eglx_get_stage_window (ClutterStage *stage)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_STAGE_EGL (stage), None);
|
|
||||||
|
|
||||||
return CLUTTER_STAGE_EGL (stage)->xwin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_eglx_get_stage_visual:
|
|
||||||
* @stage: a #ClutterStage
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Return value: FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
XVisualInfo *
|
|
||||||
clutter_eglx_get_stage_visual (ClutterStage *stage)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_STAGE_EGL (stage), NULL);
|
|
||||||
|
|
||||||
return CLUTTER_STAGE_EGL (stage)->xvisinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_eglx_set_stage_foreign:
|
|
||||||
* @stage: a #ClutterStage
|
|
||||||
* @window: FIXME
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
clutter_eglx_set_stage_foreign (ClutterStage *stage,
|
|
||||||
Window window)
|
|
||||||
{
|
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE_EGL (stage));
|
|
||||||
|
|
||||||
/* FIXME */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <GLES/gl.h>
|
#include <GLES/gl.h>
|
||||||
#include <GLES/egl.h>
|
#include <GLES/egl.h>
|
||||||
|
|
||||||
|
#include "../x11/clutter-stage-x11.h"
|
||||||
|
|
||||||
#define CLUTTER_TYPE_STAGE_EGL (clutter_stage_egl_get_type ())
|
#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_STAGE_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_EGL, ClutterStageEGL))
|
||||||
@ -24,16 +25,7 @@ typedef struct _ClutterStageEGLClass ClutterStageEGLClass;
|
|||||||
|
|
||||||
struct _ClutterStageEGL
|
struct _ClutterStageEGL
|
||||||
{
|
{
|
||||||
ClutterStage parent_instance;
|
ClutterStageX11 parent_instance;
|
||||||
|
|
||||||
/* from the backend */
|
|
||||||
Display *xdpy;
|
|
||||||
Window xwin_root;
|
|
||||||
int xscreen;
|
|
||||||
XVisualInfo *xvisinfo;
|
|
||||||
Window xwin;
|
|
||||||
gint xwin_width;
|
|
||||||
gint xwin_height;
|
|
||||||
|
|
||||||
EGLSurface egl_surface;
|
EGLSurface egl_surface;
|
||||||
EGLContext egl_context;
|
EGLContext egl_context;
|
||||||
@ -41,7 +33,7 @@ struct _ClutterStageEGL
|
|||||||
|
|
||||||
struct _ClutterStageEGLClass
|
struct _ClutterStageEGLClass
|
||||||
{
|
{
|
||||||
ClutterStageClass parent_class;
|
ClutterStageX11Class parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType clutter_stage_egl_get_type (void) G_GNUC_CONST;
|
GType clutter_stage_egl_get_type (void) G_GNUC_CONST;
|
||||||
|
@ -17,7 +17,6 @@ noinst_LTLIBRARIES = libclutter-glx.la
|
|||||||
libclutter_glx_la_SOURCES = \
|
libclutter_glx_la_SOURCES = \
|
||||||
clutter-backend-glx.h \
|
clutter-backend-glx.h \
|
||||||
clutter-backend-glx.c \
|
clutter-backend-glx.c \
|
||||||
clutter-event-glx.c \
|
|
||||||
clutter-stage-glx.h \
|
clutter-stage-glx.h \
|
||||||
clutter-stage-glx.c \
|
clutter-stage-glx.c \
|
||||||
clutter-glx.h
|
clutter-glx.h
|
||||||
|
@ -37,8 +37,6 @@
|
|||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "clutter-backend-glx.h"
|
#include "clutter-backend-glx.h"
|
||||||
#include "clutter-stage-glx.h"
|
#include "clutter-stage-glx.h"
|
||||||
#include "clutter-glx.h"
|
#include "clutter-glx.h"
|
||||||
@ -50,20 +48,11 @@
|
|||||||
|
|
||||||
#include "cogl.h"
|
#include "cogl.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterBackendGLX, clutter_backend_glx, CLUTTER_TYPE_BACKEND);
|
G_DEFINE_TYPE (ClutterBackendGLX, clutter_backend_glx, CLUTTER_TYPE_BACKEND_X11);
|
||||||
|
|
||||||
/* singleton object */
|
/* singleton object */
|
||||||
static ClutterBackendGLX *backend_singleton = NULL;
|
static ClutterBackendGLX *backend_singleton = NULL;
|
||||||
|
|
||||||
/* options */
|
|
||||||
static gchar *clutter_display_name = NULL;
|
|
||||||
static gint clutter_screen = 0;
|
|
||||||
static gboolean clutter_synchronise = FALSE;
|
|
||||||
|
|
||||||
/* X error trap */
|
|
||||||
static int TrappedErrorCode = 0;
|
|
||||||
static int (* old_error_handler) (Display *, XErrorEvent *);
|
|
||||||
|
|
||||||
static gchar *clutter_vblank_name = NULL;
|
static gchar *clutter_vblank_name = NULL;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -120,16 +109,6 @@ clutter_backend_glx_pre_parse (ClutterBackend *backend,
|
|||||||
{
|
{
|
||||||
const gchar *env_string;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
env_string = g_getenv ("CLUTTER_VBLANK");
|
env_string = g_getenv ("CLUTTER_VBLANK");
|
||||||
if (env_string)
|
if (env_string)
|
||||||
{
|
{
|
||||||
@ -137,53 +116,19 @@ clutter_backend_glx_pre_parse (ClutterBackend *backend,
|
|||||||
env_string = NULL;
|
env_string = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return clutter_backend_x11_pre_parse (backend, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
clutter_backend_glx_post_parse (ClutterBackend *backend,
|
clutter_backend_glx_post_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
if (clutter_display_name)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (BACKEND, "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)
|
|
||||||
{
|
|
||||||
int glx_major, glx_minor;
|
int glx_major, glx_minor;
|
||||||
double dpi;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Getting the X screen");
|
if (clutter_backend_x11_post_parse (backend, error))
|
||||||
|
{
|
||||||
if (clutter_screen == 0)
|
if (!glXQueryVersion (backend_x11->xdpy, &glx_major, &glx_minor)
|
||||||
backend_glx->xscreen = DefaultScreenOfDisplay (backend_glx->xdpy);
|
|
||||||
else
|
|
||||||
backend_glx->xscreen = ScreenOfDisplay (backend_glx->xdpy,
|
|
||||||
clutter_screen);
|
|
||||||
|
|
||||||
backend_glx->xscreen_num = XScreenNumberOfScreen (backend_glx->xscreen);
|
|
||||||
|
|
||||||
backend_glx->xwin_root = RootWindow (backend_glx->xdpy,
|
|
||||||
backend_glx->xscreen_num);
|
|
||||||
|
|
||||||
backend_glx->display_name = g_strdup (clutter_display_name);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Checking GLX info");
|
|
||||||
|
|
||||||
if (!glXQueryVersion (backend_glx->xdpy, &glx_major, &glx_minor)
|
|
||||||
|| !(glx_major > 1 || glx_minor > 1))
|
|| !(glx_major > 1 || glx_minor > 1))
|
||||||
{
|
{
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
@ -191,128 +136,19 @@ clutter_backend_glx_post_parse (ClutterBackend *backend,
|
|||||||
"XServer appears to lack required GLX support");
|
"XServer appears to lack required GLX support");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Prefer current GLX specs over current violations */
|
|
||||||
if (!(glx_major > 1 || glx_minor > 2))
|
|
||||||
{
|
|
||||||
|
|
||||||
const char* exts = glXQueryExtensionsString (display, screen);
|
|
||||||
if (!exts || !strstr (exts, "GLX_SGIX_fbconfig"))
|
|
||||||
have_fbconfig = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dpi = (((double) DisplayHeight (backend_glx->xdpy, backend_glx->xscreen_num) * 25.4)
|
|
||||||
/ (double) DisplayHeightMM (backend_glx->xdpy, backend_glx->xscreen_num));
|
|
||||||
|
|
||||||
clutter_backend_set_resolution (backend, dpi);
|
|
||||||
|
|
||||||
if (clutter_synchronise)
|
|
||||||
XSynchronize (backend_glx->xdpy, True);
|
|
||||||
|
|
||||||
backend_glx->atom_WM_STATE
|
|
||||||
= XInternAtom (backend_glx->xdpy, "_NET_WM_STATE", False);
|
|
||||||
backend_glx->atom_WM_STATE_FULLSCREEN
|
|
||||||
= XInternAtom (backend_glx->xdpy, "_NET_WM_STATE_FULLSCREEN", False);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (clutter_display_name);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND,
|
|
||||||
"X Display `%s'[%p] opened (screen:%d, root:%u, dpi:%f)",
|
|
||||||
backend_glx->display_name,
|
|
||||||
backend_glx->xdpy,
|
|
||||||
backend_glx->xscreen_num,
|
|
||||||
(unsigned int) backend_glx->xwin_root,
|
|
||||||
clutter_backend_get_resolution (backend));
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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_num;
|
|
||||||
stage_glx->backend = backend_glx;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_backend_glx_init_events (ClutterBackend *backend)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (EVENT, "initialising the event loop");
|
|
||||||
|
|
||||||
_clutter_backend_glx_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[] =
|
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"
|
|
||||||
},
|
|
||||||
{ "vblank", 0,
|
{ "vblank", 0,
|
||||||
0,
|
0,
|
||||||
G_OPTION_ARG_STRING, &clutter_vblank_name,
|
G_OPTION_ARG_STRING, &clutter_vblank_name,
|
||||||
"VBlank method to be used (none, dri or glx)", "METHOD"
|
"VBlank method to be used (none, dri or glx)", "METHOD"
|
||||||
},
|
},
|
||||||
{ "synch", 0,
|
|
||||||
0,
|
|
||||||
G_OPTION_ARG_NONE, &clutter_synchronise,
|
|
||||||
"Make X calls synchronous", NULL,
|
|
||||||
},
|
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -321,17 +157,12 @@ clutter_backend_glx_add_options (ClutterBackend *backend,
|
|||||||
GOptionGroup *group)
|
GOptionGroup *group)
|
||||||
{
|
{
|
||||||
g_option_group_add_entries (group, entries);
|
g_option_group_add_entries (group, entries);
|
||||||
|
clutter_backend_x11_add_options (backend, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_glx_finalize (GObject *gobject)
|
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)
|
if (backend_singleton)
|
||||||
backend_singleton = NULL;
|
backend_singleton = NULL;
|
||||||
|
|
||||||
@ -341,19 +172,6 @@ clutter_backend_glx_finalize (GObject *gobject)
|
|||||||
static void
|
static void
|
||||||
clutter_backend_glx_dispose (GObject *gobject)
|
clutter_backend_glx_dispose (GObject *gobject)
|
||||||
{
|
{
|
||||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (gobject);
|
|
||||||
|
|
||||||
if (backend_glx->stage)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (BACKEND, "Disposing the main stage");
|
|
||||||
|
|
||||||
clutter_actor_destroy (backend_glx->stage);
|
|
||||||
backend_glx->stage = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Removing the event source");
|
|
||||||
_clutter_backend_glx_events_uninit (CLUTTER_BACKEND (backend_glx));
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject);
|
G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +208,6 @@ check_vblank_env (const char *name)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ClutterFeatureFlags
|
static ClutterFeatureFlags
|
||||||
clutter_backend_glx_get_features (ClutterBackend *backend)
|
clutter_backend_glx_get_features (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
@ -400,8 +217,6 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
|
|||||||
|
|
||||||
/* FIXME: we really need to check if gl context is set */
|
/* FIXME: we really need to check if gl context is set */
|
||||||
|
|
||||||
flags = CLUTTER_FEATURE_STAGE_USER_RESIZE|CLUTTER_FEATURE_STAGE_CURSOR;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Checking features\n"
|
CLUTTER_NOTE (BACKEND, "Checking features\n"
|
||||||
"GL_VENDOR: %s\n"
|
"GL_VENDOR: %s\n"
|
||||||
"GL_RENDERER: %s\n"
|
"GL_RENDERER: %s\n"
|
||||||
@ -413,8 +228,8 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
|
|||||||
glGetString (GL_EXTENSIONS));
|
glGetString (GL_EXTENSIONS));
|
||||||
|
|
||||||
glx_extensions =
|
glx_extensions =
|
||||||
glXQueryExtensionsString (clutter_glx_get_default_display (),
|
glXQueryExtensionsString (clutter_x11_get_default_display (),
|
||||||
clutter_glx_get_default_screen ());
|
clutter_x11_get_default_screen ());
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "GLX Extensions: %s", glx_extensions);
|
CLUTTER_NOTE (BACKEND, "GLX Extensions: %s", glx_extensions);
|
||||||
|
|
||||||
@ -512,26 +327,28 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
|
|||||||
|
|
||||||
CLUTTER_NOTE (MISC, "backend features checked");
|
CLUTTER_NOTE (MISC, "backend features checked");
|
||||||
|
|
||||||
return flags;
|
return flags|clutter_backend_x11_get_features (backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_glx_redraw (ClutterBackend *backend)
|
clutter_backend_glx_redraw (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
ClutterStageGLX *stage_glx;
|
ClutterStageGLX *stage_glx;
|
||||||
|
ClutterStageX11 *stage_x11;
|
||||||
|
|
||||||
stage_glx = CLUTTER_STAGE_GLX(backend_glx->stage);
|
stage_x11 = CLUTTER_STAGE_X11(backend_x11->stage);
|
||||||
|
stage_glx = CLUTTER_STAGE_GLX(backend_x11->stage);
|
||||||
|
|
||||||
clutter_actor_paint (CLUTTER_ACTOR (stage_glx));
|
clutter_actor_paint (CLUTTER_ACTOR (stage_glx));
|
||||||
|
|
||||||
/* Why this paint is done in backend as likely GL windowing system
|
/* Why this paint is done in backend as likely GL windowing system
|
||||||
* specific calls, like swapping buffers.
|
* specific calls, like swapping buffers.
|
||||||
*/
|
*/
|
||||||
if (stage_glx->xwin)
|
if (stage_x11->xwin)
|
||||||
{
|
{
|
||||||
clutter_backend_glx_wait_for_vblank (stage_glx->backend);
|
clutter_backend_glx_wait_for_vblank (CLUTTER_BACKEND_GLX(backend));
|
||||||
glXSwapBuffers (stage_glx->xdpy, stage_glx->xwin);
|
glXSwapBuffers (stage_x11->xdpy, stage_x11->xwin);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -539,9 +356,52 @@ clutter_backend_glx_redraw (ClutterBackend *backend)
|
|||||||
glXWaitGL ();
|
glXWaitGL ();
|
||||||
CLUTTER_GLERR ();
|
CLUTTER_GLERR ();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_backend_glx_init_stage (ClutterBackend *backend,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
|
if (!backend_x11->stage)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11;
|
||||||
|
ClutterActor *stage;
|
||||||
|
|
||||||
|
stage = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL);
|
||||||
|
|
||||||
|
/* copy backend data into the stage */
|
||||||
|
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
|
stage_x11->xdpy = backend_x11->xdpy;
|
||||||
|
stage_x11->xwin_root = backend_x11->xwin_root;
|
||||||
|
stage_x11->xscreen = backend_x11->xscreen_num;
|
||||||
|
stage_x11->backend = backend_x11;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (MISC, "X11 stage created (display:%p, screen:%d, root:%u)",
|
||||||
|
stage_x11->xdpy,
|
||||||
|
stage_x11->xscreen,
|
||||||
|
(unsigned int) stage_x11->xwin_root);
|
||||||
|
|
||||||
|
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||||
|
|
||||||
|
backend_x11->stage = g_object_ref_sink (stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_actor_realize (backend_x11->stage);
|
||||||
|
|
||||||
|
if (!CLUTTER_ACTOR_IS_REALIZED (backend_x11->stage))
|
||||||
|
{
|
||||||
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
|
CLUTTER_INIT_ERROR_INTERNAL,
|
||||||
|
"Unable to realize the main stage");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
||||||
{
|
{
|
||||||
@ -555,8 +415,6 @@ clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
|||||||
backend_class->pre_parse = clutter_backend_glx_pre_parse;
|
backend_class->pre_parse = clutter_backend_glx_pre_parse;
|
||||||
backend_class->post_parse = clutter_backend_glx_post_parse;
|
backend_class->post_parse = clutter_backend_glx_post_parse;
|
||||||
backend_class->init_stage = clutter_backend_glx_init_stage;
|
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;
|
backend_class->add_options = clutter_backend_glx_add_options;
|
||||||
backend_class->get_features = clutter_backend_glx_get_features;
|
backend_class->get_features = clutter_backend_glx_get_features;
|
||||||
backend_class->redraw = clutter_backend_glx_redraw;
|
backend_class->redraw = clutter_backend_glx_redraw;
|
||||||
@ -565,12 +423,7 @@ clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
|||||||
static void
|
static void
|
||||||
clutter_backend_glx_init (ClutterBackendGLX *backend_glx)
|
clutter_backend_glx_init (ClutterBackendGLX *backend_glx)
|
||||||
{
|
{
|
||||||
ClutterBackend *backend = CLUTTER_BACKEND (backend_glx);
|
;
|
||||||
|
|
||||||
/* FIXME: get from xsettings */
|
|
||||||
clutter_backend_set_double_click_time (backend, 250);
|
|
||||||
clutter_backend_set_double_click_distance (backend, 5);
|
|
||||||
clutter_backend_set_resolution (backend, 96.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* every backend must implement this function */
|
/* every backend must implement this function */
|
||||||
@ -580,14 +433,6 @@ _clutter_backend_impl_get_type (void)
|
|||||||
return clutter_backend_glx_get_type ();
|
return clutter_backend_glx_get_type ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
error_handler(Display *xdpy,
|
|
||||||
XErrorEvent *error)
|
|
||||||
{
|
|
||||||
TrappedErrorCode = error->error_code;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
clutter_backend_glx_wait_for_vblank (ClutterBackendGLX *backend_glx)
|
clutter_backend_glx_wait_for_vblank (ClutterBackendGLX *backend_glx)
|
||||||
{
|
{
|
||||||
@ -623,175 +468,3 @@ clutter_backend_glx_wait_for_vblank (ClutterBackendGLX *backend_glx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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:
|
|
||||||
*
|
|
||||||
* Gets the number of the default X Screen object.
|
|
||||||
*
|
|
||||||
* Return value: the number of the default Screen object.
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
clutter_glx_get_default_screen (void)
|
|
||||||
{
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
|
||||||
g_critical ("GLX backend has not been initialised");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return backend_singleton->xscreen_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_glx_add_filter:
|
|
||||||
* @func: an event filter function
|
|
||||||
* @data: user data to pass to the function, or %NULL
|
|
||||||
*
|
|
||||||
* Adds @func to the list of event filters. Filter functions
|
|
||||||
* receive the raw events and must return %CLUTTER_GLX_FILTER_CONTINUE
|
|
||||||
* if the event should be processed by Clutter, %CLUTTER_GLX_FILTER_TRANSLATE
|
|
||||||
* if the event has been translated by the function and it's ready
|
|
||||||
* to be sent to the stage, or %CLUTTER_GLX_FILTER_REMOVE if the event should
|
|
||||||
* not be sent to the stage.
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
clutter_glx_add_filter (ClutterGLXFilterFunc func,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
ClutterGLXEventFilter *filter;
|
|
||||||
|
|
||||||
g_return_if_fail (func != NULL);
|
|
||||||
|
|
||||||
if (!backend_singleton)
|
|
||||||
{
|
|
||||||
g_critical ("GLX backend has not been initialised");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
filter = g_new0(ClutterGLXEventFilter, 1);
|
|
||||||
filter->func = func;
|
|
||||||
filter->data = data;
|
|
||||||
|
|
||||||
backend_singleton->event_filters =
|
|
||||||
g_slist_append (backend_singleton->event_filters, filter);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_glx_remove_filter:
|
|
||||||
* @func: the filter function to remove
|
|
||||||
* @data: user data of the filter function, or %NULL
|
|
||||||
*
|
|
||||||
* Removes @func from the list of filter functions installed
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
clutter_glx_remove_filter (ClutterGLXFilterFunc func,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GSList *tmp_list, *this;
|
|
||||||
ClutterGLXEventFilter *filter;
|
|
||||||
|
|
||||||
g_return_if_fail (func == NULL);
|
|
||||||
|
|
||||||
tmp_list = backend_singleton->event_filters;
|
|
||||||
|
|
||||||
while (tmp_list)
|
|
||||||
{
|
|
||||||
filter = (ClutterGLXEventFilter *)tmp_list->data;
|
|
||||||
this = tmp_list;
|
|
||||||
tmp_list = tmp_list->next;
|
|
||||||
|
|
||||||
if (filter->func == func && filter->data == data)
|
|
||||||
{
|
|
||||||
backend_singleton->event_filters =
|
|
||||||
g_slist_remove_link (backend_singleton->event_filters, this);
|
|
||||||
|
|
||||||
g_slist_free_1 (this);
|
|
||||||
g_free (filter);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
#include "../x11/clutter-backend-x11.h"
|
||||||
#include "clutter-glx.h"
|
#include "clutter-glx.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@ -59,29 +60,9 @@ typedef int (*WaitVideoSyncProc) (int divisor,
|
|||||||
unsigned int *count);
|
unsigned int *count);
|
||||||
typedef int (*SwapIntervalProc) (int interval);
|
typedef int (*SwapIntervalProc) (int interval);
|
||||||
|
|
||||||
typedef struct _ClutterGLXEventFilter
|
|
||||||
{
|
|
||||||
ClutterGLXFilterFunc func;
|
|
||||||
gpointer data;
|
|
||||||
|
|
||||||
} ClutterGLXEventFilter;
|
|
||||||
|
|
||||||
struct _ClutterBackendGLX
|
struct _ClutterBackendGLX
|
||||||
{
|
{
|
||||||
ClutterBackend parent_instance;
|
ClutterBackendX11 parent_instance;
|
||||||
|
|
||||||
Display *xdpy;
|
|
||||||
Window xwin_root;
|
|
||||||
Screen *xscreen;
|
|
||||||
int xscreen_num;
|
|
||||||
gchar *display_name;
|
|
||||||
|
|
||||||
/* main stage singleton */
|
|
||||||
ClutterActor *stage;
|
|
||||||
|
|
||||||
/* event source */
|
|
||||||
GSource *event_source;
|
|
||||||
GSList *event_filters;
|
|
||||||
|
|
||||||
/* Vblank stuff */
|
/* Vblank stuff */
|
||||||
GetVideoSyncProc get_video_sync;
|
GetVideoSyncProc get_video_sync;
|
||||||
@ -89,20 +70,13 @@ struct _ClutterBackendGLX
|
|||||||
SwapIntervalProc swap_interval;
|
SwapIntervalProc swap_interval;
|
||||||
gint dri_fd;
|
gint dri_fd;
|
||||||
ClutterGLXVBlankType vblank_type;
|
ClutterGLXVBlankType vblank_type;
|
||||||
|
|
||||||
/* props */
|
|
||||||
Atom atom_WM_STATE;
|
|
||||||
Atom atom_WM_STATE_FULLSCREEN;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendGLXClass
|
struct _ClutterBackendGLXClass
|
||||||
{
|
{
|
||||||
ClutterBackendClass parent_class;
|
ClutterBackendX11Class parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
void _clutter_backend_glx_events_init (ClutterBackend *backend);
|
|
||||||
void _clutter_backend_glx_events_uninit (ClutterBackend *backend);
|
|
||||||
|
|
||||||
void clutter_backend_glx_wait_for_vblank (ClutterBackendGLX *backend_glx);
|
void clutter_backend_glx_wait_for_vblank (ClutterBackendGLX *backend_glx);
|
||||||
|
|
||||||
GType clutter_backend_glx_get_type (void) G_GNUC_CONST;
|
GType clutter_backend_glx_get_type (void) G_GNUC_CONST;
|
||||||
|
@ -27,9 +27,8 @@
|
|||||||
* SECTION:clutter-glx
|
* SECTION:clutter-glx
|
||||||
* @short_description: GLX specific API
|
* @short_description: GLX specific API
|
||||||
*
|
*
|
||||||
* The GLX backend for Clutter provides some specific API, allowing
|
* The GLX backend for Clutter provides some specific API for GLX
|
||||||
* integration with the Xlibs API for embedding and manipulating the
|
* related calls.
|
||||||
* stage window, or for trapping X errors.
|
|
||||||
*
|
*
|
||||||
* The ClutterGLX API is available since Clutter 0.4
|
* The ClutterGLX API is available since Clutter 0.4
|
||||||
*/
|
*/
|
||||||
@ -40,40 +39,10 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/Xutil.h>
|
|
||||||
#include <clutter/clutter-stage.h>
|
#include <clutter/clutter-stage.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CLUTTER_GLX_FILTER_CONTINUE, /* Event not handled, continue processesing */
|
|
||||||
CLUTTER_GLX_FILTER_TRANSLATE, /* Native event translated into a Clutter
|
|
||||||
event and stored in the "event" structure
|
|
||||||
that was passed in */
|
|
||||||
CLUTTER_GLX_FILTER_REMOVE /* Terminate processing, removing event */
|
|
||||||
} ClutterGLXFilterReturn;
|
|
||||||
|
|
||||||
typedef ClutterGLXFilterReturn (*ClutterGLXFilterFunc) (XEvent *xev,
|
|
||||||
ClutterEvent *cev,
|
|
||||||
gpointer *data);
|
|
||||||
|
|
||||||
void clutter_glx_trap_x_errors (void);
|
|
||||||
gint clutter_glx_untrap_x_errors (void);
|
|
||||||
|
|
||||||
Display *clutter_glx_get_default_display (void);
|
|
||||||
int clutter_glx_get_default_screen (void);
|
|
||||||
Window clutter_glx_get_root_window (void);
|
|
||||||
|
|
||||||
Window clutter_glx_get_stage_window (ClutterStage *stage);
|
|
||||||
XVisualInfo *clutter_glx_get_stage_visual (ClutterStage *stage);
|
|
||||||
|
|
||||||
gboolean clutter_glx_set_stage_foreign (ClutterStage *stage,
|
|
||||||
Window xwindow);
|
|
||||||
|
|
||||||
void clutter_glx_add_filter (ClutterGLXFilterFunc func, gpointer data);
|
|
||||||
|
|
||||||
void clutter_glx_remove_filter (ClutterGLXFilterFunc func,
|
|
||||||
gpointer data);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -39,172 +39,71 @@
|
|||||||
|
|
||||||
#include "cogl.h"
|
#include "cogl.h"
|
||||||
|
|
||||||
#ifdef HAVE_XFIXES
|
|
||||||
#include <X11/extensions/Xfixes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
|
|
||||||
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
|
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterStageGLX, clutter_stage_glx, CLUTTER_TYPE_STAGE);
|
G_DEFINE_TYPE (ClutterStageGLX, clutter_stage_glx, CLUTTER_TYPE_STAGE_X11);
|
||||||
|
|
||||||
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
|
|
||||||
#define _NET_WM_STATE_ADD 1 /* add/set property */
|
|
||||||
#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_wmspec_change_state (ClutterBackendGLX *backend_glx,
|
|
||||||
Window window,
|
|
||||||
Atom state,
|
|
||||||
gboolean add)
|
|
||||||
{
|
|
||||||
XClientMessageEvent xclient;
|
|
||||||
|
|
||||||
memset (&xclient, 0, sizeof (xclient));
|
|
||||||
|
|
||||||
xclient.type = ClientMessage;
|
|
||||||
xclient.window = window;
|
|
||||||
xclient.message_type = backend_glx->atom_WM_STATE;
|
|
||||||
xclient.format = 32;
|
|
||||||
|
|
||||||
xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
|
||||||
xclient.data.l[1] = state;
|
|
||||||
xclient.data.l[2] = 0;
|
|
||||||
xclient.data.l[3] = 0;
|
|
||||||
xclient.data.l[4] = 0;
|
|
||||||
|
|
||||||
XSendEvent (backend_glx->xdpy,
|
|
||||||
DefaultRootWindow(backend_glx->xdpy),
|
|
||||||
False,
|
|
||||||
SubstructureRedirectMask|SubstructureNotifyMask,
|
|
||||||
(XEvent *)&xclient);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
fix_window_size (ClutterStageGLX *stage_glx)
|
|
||||||
{
|
|
||||||
gboolean resize;
|
|
||||||
|
|
||||||
resize = clutter_stage_get_user_resizable (CLUTTER_STAGE (stage_glx));
|
|
||||||
|
|
||||||
if (stage_glx->xwin != None && stage_glx->is_foreign_xwin == FALSE)
|
|
||||||
{
|
|
||||||
XSizeHints *size_hints;
|
|
||||||
|
|
||||||
size_hints = XAllocSizeHints();
|
|
||||||
|
|
||||||
if (!resize)
|
|
||||||
{
|
|
||||||
size_hints->max_width
|
|
||||||
= size_hints->min_width = stage_glx->xwin_width;
|
|
||||||
size_hints->max_height
|
|
||||||
= size_hints->min_height = stage_glx->xwin_height;
|
|
||||||
size_hints->flags = PMinSize|PMaxSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
XSetWMNormalHints (stage_glx->xdpy, stage_glx->xwin, size_hints);
|
|
||||||
|
|
||||||
XFree(size_hints);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_glx_show (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
|
||||||
|
|
||||||
/* Chain up to set mapped flags */
|
|
||||||
CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->show(actor);
|
|
||||||
|
|
||||||
if (stage_glx->xwin)
|
|
||||||
{
|
|
||||||
/* Fire off a redraw to avoid flicker on first map.
|
|
||||||
* Appears not to work perfectly on intel drivers at least.
|
|
||||||
*/
|
|
||||||
clutter_redraw();
|
|
||||||
XSync (stage_glx->xdpy, FALSE);
|
|
||||||
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
|
static void
|
||||||
clutter_stage_glx_unrealize (ClutterActor *actor)
|
clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
||||||
|
|
||||||
gboolean was_offscreen;
|
gboolean was_offscreen;
|
||||||
|
|
||||||
CLUTTER_MARK();
|
CLUTTER_MARK();
|
||||||
|
|
||||||
g_object_get (actor, "offscreen", &was_offscreen, NULL);
|
g_object_get (actor, "offscreen", &was_offscreen, NULL);
|
||||||
|
|
||||||
clutter_glx_trap_x_errors ();
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
if (G_UNLIKELY (was_offscreen))
|
if (G_UNLIKELY (was_offscreen))
|
||||||
{
|
{
|
||||||
if (stage_glx->glxpixmap)
|
if (stage_glx->glxpixmap)
|
||||||
{
|
{
|
||||||
glXDestroyGLXPixmap (stage_glx->xdpy, stage_glx->glxpixmap);
|
glXDestroyGLXPixmap (stage_x11->xdpy,stage_glx->glxpixmap);
|
||||||
stage_glx->glxpixmap = None;
|
stage_glx->glxpixmap = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage_glx->xpixmap)
|
if (stage_x11->xpixmap)
|
||||||
{
|
{
|
||||||
XFreePixmap (stage_glx->xdpy, stage_glx->xpixmap);
|
XFreePixmap (stage_x11->xdpy, stage_x11->xpixmap);
|
||||||
stage_glx->xpixmap = None;
|
stage_x11->xpixmap = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!stage_glx->is_foreign_xwin && stage_glx->xwin != None)
|
if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
|
||||||
{
|
{
|
||||||
XDestroyWindow (stage_glx->xdpy, stage_glx->xwin);
|
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
|
||||||
stage_glx->xwin = None;
|
stage_x11->xwin = None;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
stage_glx->xwin = None;
|
stage_x11->xwin = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
glXMakeCurrent (stage_glx->xdpy, None, NULL);
|
glXMakeCurrent (stage_x11->xdpy, None, NULL);
|
||||||
|
|
||||||
if (stage_glx->gl_context != None)
|
if (stage_glx->gl_context != None)
|
||||||
{
|
{
|
||||||
glXDestroyContext (stage_glx->xdpy, stage_glx->gl_context);
|
glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context);
|
||||||
stage_glx->gl_context = None;
|
stage_glx->gl_context = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
XSync (stage_glx->xdpy, False);
|
XSync (stage_x11->xdpy, False);
|
||||||
|
|
||||||
clutter_glx_untrap_x_errors ();
|
clutter_x11_untrap_x_errors ();
|
||||||
|
|
||||||
CLUTTER_MARK ();
|
CLUTTER_MARK ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
set_wm_protocols (Display *xdisplay,
|
|
||||||
Window xwindow)
|
|
||||||
{
|
|
||||||
Atom protocols[2];
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
protocols[n++] = XInternAtom (xdisplay, "WM_DELETE_WINDOW", False);
|
|
||||||
protocols[n++] = XInternAtom (xdisplay, "_NET_WM_PING", False);
|
|
||||||
|
|
||||||
XSetWMProtocols (xdisplay, xwindow, protocols, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_glx_realize (ClutterActor *actor)
|
clutter_stage_glx_realize (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
||||||
gboolean is_offscreen;
|
gboolean is_offscreen;
|
||||||
|
|
||||||
@ -225,21 +124,21 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (stage_glx->xvisinfo)
|
if (stage_x11->xvisinfo)
|
||||||
XFree (stage_glx->xvisinfo);
|
XFree (stage_x11->xvisinfo);
|
||||||
|
|
||||||
if (stage_glx->xvisinfo == None)
|
if (stage_x11->xvisinfo == None)
|
||||||
stage_glx->xvisinfo = glXChooseVisual (stage_glx->xdpy,
|
stage_x11->xvisinfo = glXChooseVisual (stage_x11->xdpy,
|
||||||
stage_glx->xscreen,
|
stage_x11->xscreen,
|
||||||
gl_attributes);
|
gl_attributes);
|
||||||
if (!stage_glx->xvisinfo)
|
if (!stage_x11->xvisinfo)
|
||||||
{
|
{
|
||||||
g_critical ("Unable to find suitable GL visual.");
|
g_critical ("Unable to find suitable GL visual.");
|
||||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage_glx->xwin == None)
|
if (stage_x11->xwin == None)
|
||||||
{
|
{
|
||||||
XSetWindowAttributes xattr;
|
XSetWindowAttributes xattr;
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
@ -247,28 +146,28 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
CLUTTER_NOTE (MISC, "Creating stage X window");
|
CLUTTER_NOTE (MISC, "Creating stage X window");
|
||||||
|
|
||||||
/* window attributes */
|
/* window attributes */
|
||||||
xattr.background_pixel = WhitePixel (stage_glx->xdpy,
|
xattr.background_pixel = WhitePixel (stage_x11->xdpy,
|
||||||
stage_glx->xscreen);
|
stage_x11->xscreen);
|
||||||
xattr.border_pixel = 0;
|
xattr.border_pixel = 0;
|
||||||
xattr.colormap = XCreateColormap (stage_glx->xdpy,
|
xattr.colormap = XCreateColormap (stage_x11->xdpy,
|
||||||
stage_glx->xwin_root,
|
stage_x11->xwin_root,
|
||||||
stage_glx->xvisinfo->visual,
|
stage_x11->xvisinfo->visual,
|
||||||
AllocNone);
|
AllocNone);
|
||||||
mask = CWBackPixel | CWBorderPixel | CWColormap;
|
mask = CWBackPixel | CWBorderPixel | CWColormap;
|
||||||
stage_glx->xwin = XCreateWindow (stage_glx->xdpy,
|
stage_x11->xwin = XCreateWindow (stage_x11->xdpy,
|
||||||
stage_glx->xwin_root,
|
stage_x11->xwin_root,
|
||||||
0, 0,
|
0, 0,
|
||||||
stage_glx->xwin_width,
|
stage_x11->xwin_width,
|
||||||
stage_glx->xwin_height,
|
stage_x11->xwin_height,
|
||||||
0,
|
0,
|
||||||
stage_glx->xvisinfo->depth,
|
stage_x11->xvisinfo->depth,
|
||||||
InputOutput,
|
InputOutput,
|
||||||
stage_glx->xvisinfo->visual,
|
stage_x11->xvisinfo->visual,
|
||||||
mask, &xattr);
|
mask, &xattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "XSelectInput");
|
CLUTTER_NOTE (MISC, "XSelectInput");
|
||||||
XSelectInput (stage_glx->xdpy, stage_glx->xwin,
|
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
|
||||||
StructureNotifyMask |
|
StructureNotifyMask |
|
||||||
FocusChangeMask |
|
FocusChangeMask |
|
||||||
ExposureMask |
|
ExposureMask |
|
||||||
@ -279,16 +178,16 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
PropertyChangeMask);
|
PropertyChangeMask);
|
||||||
|
|
||||||
/* no user resize.. */
|
/* no user resize.. */
|
||||||
fix_window_size (stage_glx);
|
clutter_stage_x11_fix_window_size (stage_x11);
|
||||||
|
|
||||||
set_wm_protocols (stage_glx->xdpy, stage_glx->xwin);
|
clutter_stage_x11_set_wm_protocols (stage_x11->xdpy, stage_x11->xwin);
|
||||||
|
|
||||||
if (stage_glx->gl_context)
|
if (stage_glx->gl_context)
|
||||||
glXDestroyContext (stage_glx->xdpy, stage_glx->gl_context);
|
glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context);
|
||||||
|
|
||||||
CLUTTER_NOTE (GL, "Creating GL Context");
|
CLUTTER_NOTE (GL, "Creating GL Context");
|
||||||
stage_glx->gl_context = glXCreateContext (stage_glx->xdpy,
|
stage_glx->gl_context = glXCreateContext (stage_x11->xdpy,
|
||||||
stage_glx->xvisinfo,
|
stage_x11->xvisinfo,
|
||||||
0,
|
0,
|
||||||
True);
|
True);
|
||||||
|
|
||||||
@ -302,7 +201,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CLUTTER_NOTE (GL, "glXMakeCurrent");
|
CLUTTER_NOTE (GL, "glXMakeCurrent");
|
||||||
glXMakeCurrent (stage_glx->xdpy, stage_glx->xwin, stage_glx->gl_context);
|
glXMakeCurrent (stage_x11->xdpy, stage_x11->xwin, stage_glx->gl_context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -317,78 +216,50 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (stage_glx->xvisinfo)
|
if (stage_x11->xvisinfo)
|
||||||
XFree (stage_glx->xvisinfo);
|
XFree (stage_x11->xvisinfo);
|
||||||
|
|
||||||
CLUTTER_NOTE (GL, "glXChooseVisual");
|
CLUTTER_NOTE (GL, "glXChooseVisual");
|
||||||
stage_glx->xvisinfo = glXChooseVisual (stage_glx->xdpy,
|
stage_x11->xvisinfo = glXChooseVisual (stage_x11->xdpy,
|
||||||
stage_glx->xscreen,
|
stage_x11->xscreen,
|
||||||
gl_attributes);
|
gl_attributes);
|
||||||
if (!stage_glx->xvisinfo)
|
if (!stage_x11->xvisinfo)
|
||||||
{
|
{
|
||||||
g_critical ("Unable to find suitable GL visual.");
|
g_critical ("Unable to find suitable GL visual.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage_glx->gl_context)
|
if (stage_glx->gl_context)
|
||||||
glXDestroyContext (stage_glx->xdpy, stage_glx->gl_context);
|
glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context);
|
||||||
|
|
||||||
stage_glx->xpixmap = XCreatePixmap (stage_glx->xdpy,
|
stage_x11->xpixmap = XCreatePixmap (stage_x11->xdpy,
|
||||||
stage_glx->xwin_root,
|
stage_x11->xwin_root,
|
||||||
stage_glx->xwin_width,
|
stage_x11->xwin_width,
|
||||||
stage_glx->xwin_height,
|
stage_x11->xwin_height,
|
||||||
DefaultDepth (stage_glx->xdpy,
|
DefaultDepth (stage_x11->xdpy,
|
||||||
stage_glx->xscreen));
|
stage_x11->xscreen));
|
||||||
|
|
||||||
stage_glx->glxpixmap = glXCreateGLXPixmap (stage_glx->xdpy,
|
stage_glx->glxpixmap = glXCreateGLXPixmap (stage_x11->xdpy,
|
||||||
stage_glx->xvisinfo,
|
stage_x11->xvisinfo,
|
||||||
stage_glx->xpixmap);
|
stage_x11->xpixmap);
|
||||||
|
|
||||||
/* indirect */
|
/* indirect */
|
||||||
stage_glx->gl_context = glXCreateContext (stage_glx->xdpy,
|
stage_glx->gl_context = glXCreateContext (stage_x11->xdpy,
|
||||||
stage_glx->xvisinfo,
|
stage_x11->xvisinfo,
|
||||||
0,
|
0,
|
||||||
False);
|
False);
|
||||||
|
|
||||||
clutter_glx_trap_x_errors ();
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
glXMakeCurrent (stage_glx->xdpy,
|
glXMakeCurrent (stage_x11->xdpy,
|
||||||
stage_glx->glxpixmap,
|
stage_glx->glxpixmap,
|
||||||
stage_glx->gl_context);
|
stage_glx->gl_context);
|
||||||
|
|
||||||
if (clutter_glx_untrap_x_errors ())
|
if (clutter_x11_untrap_x_errors ())
|
||||||
{
|
{
|
||||||
g_critical ("Unable to set up offscreen context.");
|
g_critical ("Unable to set up offscreen context.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the viewport gets set up correctly */
|
/* Make sure the viewport gets set up correctly */
|
||||||
@ -402,235 +273,6 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_glx_query_coords (ClutterActor *self,
|
|
||||||
ClutterActorBox *box)
|
|
||||||
{
|
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (self);
|
|
||||||
|
|
||||||
box->x1 = box->y1 = 0;
|
|
||||||
box->x2 = box->x1 + CLUTTER_UNITS_FROM_INT (stage_glx->xwin_width);
|
|
||||||
box->y2 = box->y1 + CLUTTER_UNITS_FROM_INT (stage_glx->xwin_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_glx_request_coords (ClutterActor *self,
|
|
||||||
ClutterActorBox *box)
|
|
||||||
{
|
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (self);
|
|
||||||
gint new_width, new_height;
|
|
||||||
|
|
||||||
new_width = ABS (CLUTTER_UNITS_TO_INT (box->x2 - box->x1));
|
|
||||||
new_height = ABS (CLUTTER_UNITS_TO_INT (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);
|
|
||||||
|
|
||||||
fix_window_size (stage_glx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stage_glx->xpixmap != None)
|
|
||||||
{
|
|
||||||
/* Need to recreate to resize */
|
|
||||||
clutter_actor_unrealize (self);
|
|
||||||
clutter_actor_realize (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stage_glx->xwin != None) /* Do we want to bother ? */
|
|
||||||
XMoveWindow (stage_glx->xdpy,
|
|
||||||
stage_glx->xwin,
|
|
||||||
CLUTTER_UNITS_TO_INT (box->x1),
|
|
||||||
CLUTTER_UNITS_TO_INT (box->y1));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_glx_set_fullscreen (ClutterStage *stage,
|
|
||||||
gboolean fullscreen)
|
|
||||||
{
|
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage);
|
|
||||||
ClutterBackendGLX *backend_glx = stage_glx->backend;
|
|
||||||
|
|
||||||
static gboolean was_resizeable = FALSE;
|
|
||||||
|
|
||||||
if (fullscreen)
|
|
||||||
{
|
|
||||||
if (stage_glx->xwin != None)
|
|
||||||
{
|
|
||||||
if (!CLUTTER_ACTOR_IS_MAPPED(CLUTTER_ACTOR (stage_glx)))
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
/* FIXME: This wont work if we support more states */
|
|
||||||
XChangeProperty
|
|
||||||
(stage_glx->xdpy,
|
|
||||||
stage_glx->xwin,
|
|
||||||
backend_glx->atom_WM_STATE, XA_ATOM, 32,
|
|
||||||
PropModeReplace,
|
|
||||||
(unsigned char *)&backend_glx->atom_WM_STATE_FULLSCREEN,
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We need to set window user resize-able for metacity at
|
|
||||||
* at least to allow the window to fullscreen *sigh*
|
|
||||||
*/
|
|
||||||
if (clutter_stage_get_user_resizable (stage) == TRUE)
|
|
||||||
was_resizeable = TRUE;
|
|
||||||
else
|
|
||||||
clutter_stage_set_user_resizable (stage, TRUE);
|
|
||||||
|
|
||||||
send_wmspec_change_state(backend_glx,
|
|
||||||
stage_glx->xwin,
|
|
||||||
backend_glx->atom_WM_STATE_FULLSCREEN,
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (stage_glx->xwin != None)
|
|
||||||
{
|
|
||||||
if (!CLUTTER_ACTOR_IS_MAPPED(CLUTTER_ACTOR (stage_glx)))
|
|
||||||
{
|
|
||||||
/* FIXME: This wont work if we support more states */
|
|
||||||
XDeleteProperty (stage_glx->xdpy,
|
|
||||||
stage_glx->xwin,
|
|
||||||
backend_glx->atom_WM_STATE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clutter_stage_set_user_resizable (stage, TRUE);
|
|
||||||
|
|
||||||
send_wmspec_change_state(backend_glx,
|
|
||||||
stage_glx->xwin,
|
|
||||||
backend_glx->atom_WM_STATE_FULLSCREEN,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
/* reset the windows state - this isn't fun - see above */
|
|
||||||
if (!was_resizeable)
|
|
||||||
clutter_stage_set_user_resizable (stage, FALSE);
|
|
||||||
|
|
||||||
was_resizeable = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (BACKEND, "setting cursor state ('%s') over stage window (%u)",
|
|
||||||
show_cursor ? "visible" : "invisible",
|
|
||||||
(unsigned int) stage_glx->xwin);
|
|
||||||
|
|
||||||
if (show_cursor)
|
|
||||||
{
|
|
||||||
#if 0 /* HAVE_XFIXES - borked on fiesty at least so disabled until further
|
|
||||||
* investigation.
|
|
||||||
*/
|
|
||||||
XFixesShowCursor (stage_glx->xdpy, stage_glx->xwin);
|
|
||||||
#else
|
|
||||||
XUndefineCursor (stage_glx->xdpy, stage_glx->xwin);
|
|
||||||
#endif /* HAVE_XFIXES */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if 0 /* HAVE_XFIXES - borked */
|
|
||||||
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 /* HAVE_XFIXES */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_glx_set_title (ClutterStage *stage,
|
|
||||||
const gchar *title)
|
|
||||||
{
|
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage);
|
|
||||||
Atom atom_NET_WM_NAME, atom_UTF8_STRING;
|
|
||||||
|
|
||||||
if (stage_glx->xwin == None)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* FIXME: pre create these to avoid too many round trips */
|
|
||||||
atom_NET_WM_NAME = XInternAtom (stage_glx->xdpy, "_NET_WM_NAME", False);
|
|
||||||
atom_UTF8_STRING = XInternAtom (stage_glx->xdpy, "UTF8_STRING", False);
|
|
||||||
|
|
||||||
if (title == NULL)
|
|
||||||
{
|
|
||||||
XDeleteProperty (stage_glx->xdpy,
|
|
||||||
stage_glx->xwin,
|
|
||||||
atom_NET_WM_NAME);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XChangeProperty (stage_glx->xdpy,
|
|
||||||
stage_glx->xwin,
|
|
||||||
atom_NET_WM_NAME,
|
|
||||||
atom_UTF8_STRING,
|
|
||||||
8,
|
|
||||||
PropModeReplace,
|
|
||||||
(unsigned char*)title,
|
|
||||||
(int)strlen(title));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_glx_set_user_resize (ClutterStage *stage,
|
|
||||||
gboolean value)
|
|
||||||
{
|
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage);
|
|
||||||
|
|
||||||
fix_window_size (stage_glx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_glx_set_offscreen (ClutterStage *stage,
|
|
||||||
gboolean offscreen)
|
|
||||||
{
|
|
||||||
/* Do nothing ? */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
snapshot_pixbuf_free (guchar *pixels,
|
snapshot_pixbuf_free (guchar *pixels,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
@ -649,9 +291,11 @@ clutter_stage_glx_draw_to_pixbuf (ClutterStage *stage,
|
|||||||
GdkPixbuf *pixb;
|
GdkPixbuf *pixb;
|
||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
ClutterStageGLX *stage_glx;
|
ClutterStageGLX *stage_glx;
|
||||||
|
ClutterStageX11 *stage_x11;
|
||||||
gboolean is_offscreen = FALSE;
|
gboolean is_offscreen = FALSE;
|
||||||
|
|
||||||
stage_glx = CLUTTER_STAGE_GLX (stage);
|
stage_glx = CLUTTER_STAGE_GLX (stage);
|
||||||
|
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
actor = CLUTTER_ACTOR (stage);
|
actor = CLUTTER_ACTOR (stage);
|
||||||
|
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
@ -664,13 +308,13 @@ clutter_stage_glx_draw_to_pixbuf (ClutterStage *stage,
|
|||||||
|
|
||||||
if (G_UNLIKELY (is_offscreen))
|
if (G_UNLIKELY (is_offscreen))
|
||||||
{
|
{
|
||||||
gdk_pixbuf_xlib_init (stage_glx->xdpy, stage_glx->xscreen);
|
gdk_pixbuf_xlib_init (stage_x11->xdpy, stage_x11->xscreen);
|
||||||
|
|
||||||
pixb = gdk_pixbuf_xlib_get_from_drawable (NULL,
|
pixb = gdk_pixbuf_xlib_get_from_drawable (NULL,
|
||||||
(Drawable) stage_glx->xpixmap,
|
(Drawable) stage_x11->xpixmap,
|
||||||
DefaultColormap (stage_glx->xdpy,
|
DefaultColormap (stage_x11->xdpy,
|
||||||
stage_glx->xscreen),
|
stage_x11->xscreen),
|
||||||
stage_glx->xvisinfo->visual,
|
stage_x11->xvisinfo->visual,
|
||||||
x, y,
|
x, y,
|
||||||
0, 0,
|
0, 0,
|
||||||
width, height);
|
width, height);
|
||||||
@ -712,8 +356,9 @@ static void
|
|||||||
clutter_stage_glx_dispose (GObject *gobject)
|
clutter_stage_glx_dispose (GObject *gobject)
|
||||||
{
|
{
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (gobject);
|
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (gobject);
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||||
|
|
||||||
if (stage_glx->xwin)
|
if (stage_x11->xwin)
|
||||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_glx));
|
clutter_actor_unrealize (CLUTTER_ACTOR (stage_glx));
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_stage_glx_parent_class)->dispose (gobject);
|
G_OBJECT_CLASS (clutter_stage_glx_parent_class)->dispose (gobject);
|
||||||
@ -728,133 +373,13 @@ clutter_stage_glx_class_init (ClutterStageGLXClass *klass)
|
|||||||
|
|
||||||
gobject_class->dispose = clutter_stage_glx_dispose;
|
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->realize = clutter_stage_glx_realize;
|
||||||
actor_class->unrealize = clutter_stage_glx_unrealize;
|
actor_class->unrealize = clutter_stage_glx_unrealize;
|
||||||
actor_class->request_coords = clutter_stage_glx_request_coords;
|
|
||||||
actor_class->query_coords = clutter_stage_glx_query_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->draw_to_pixbuf = clutter_stage_glx_draw_to_pixbuf;
|
stage_class->draw_to_pixbuf = clutter_stage_glx_draw_to_pixbuf;
|
||||||
stage_class->set_title = clutter_stage_glx_set_title;
|
|
||||||
stage_class->set_user_resize = clutter_stage_glx_set_user_resize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_glx_init (ClutterStageGLX *stage)
|
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_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_glx_get_stage_window:
|
|
||||||
* @stage: a #ClutterStage
|
|
||||||
*
|
|
||||||
* Gets the stages X Window.
|
|
||||||
*
|
|
||||||
* Return value: An XID for the stage window.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Returns the stage XVisualInfo
|
|
||||||
*
|
|
||||||
* Return value: The XVisualInfo for the stage.
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_glx_set_stage_foreign:
|
|
||||||
* @stage: a #ClutterStage
|
|
||||||
* @xwindow: an existing X Window id
|
|
||||||
*
|
|
||||||
* Target the #ClutterStage to use an existing external X Window
|
|
||||||
*
|
|
||||||
* Return value: %TRUE if foreign window is valid
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
clutter_glx_set_stage_foreign (ClutterStage *stage,
|
|
||||||
Window xwindow)
|
|
||||||
{
|
|
||||||
ClutterStageGLX *stage_glx;
|
|
||||||
ClutterActor *actor;
|
|
||||||
gint x, y;
|
|
||||||
guint width, height, border, depth;
|
|
||||||
Window root_return;
|
|
||||||
Status status;
|
|
||||||
ClutterGeometry geom;
|
|
||||||
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_STAGE_GLX (stage), FALSE);
|
|
||||||
g_return_val_if_fail (xwindow != None, FALSE);
|
|
||||||
|
|
||||||
stage_glx = CLUTTER_STAGE_GLX (stage);
|
|
||||||
actor = CLUTTER_ACTOR (stage);
|
|
||||||
|
|
||||||
clutter_glx_trap_x_errors ();
|
|
||||||
|
|
||||||
status = XGetGeometry (stage_glx->xdpy,
|
|
||||||
xwindow,
|
|
||||||
&root_return,
|
|
||||||
&x, &y,
|
|
||||||
&width, &height,
|
|
||||||
&border,
|
|
||||||
&depth);
|
|
||||||
|
|
||||||
if (clutter_glx_untrap_x_errors () ||
|
|
||||||
!status ||
|
|
||||||
width == 0 || height == 0 ||
|
|
||||||
depth != stage_glx->xvisinfo->depth)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_actor_unrealize (actor);
|
|
||||||
|
|
||||||
stage_glx->xwin = xwindow;
|
|
||||||
stage_glx->is_foreign_xwin = TRUE;
|
|
||||||
|
|
||||||
geom.x = x;
|
|
||||||
geom.y = y;
|
|
||||||
geom.width = stage_glx->xwin_width = width;
|
|
||||||
geom.height = stage_glx->xwin_height = height;
|
|
||||||
|
|
||||||
clutter_actor_set_geometry (actor, &geom);
|
|
||||||
clutter_actor_realize (actor);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
|
|
||||||
#include "clutter-backend-glx.h"
|
#include "clutter-backend-glx.h"
|
||||||
|
#include "../x11/clutter-stage-x11.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -45,32 +46,15 @@ typedef struct _ClutterStageGLXClass ClutterStageGLXClass;
|
|||||||
|
|
||||||
struct _ClutterStageGLX
|
struct _ClutterStageGLX
|
||||||
{
|
{
|
||||||
ClutterStage parent_instance;
|
ClutterStageX11 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;
|
GLXPixmap glxpixmap;
|
||||||
GLXContext gl_context;
|
GLXContext gl_context;
|
||||||
|
|
||||||
guint is_foreign_xwin : 1;
|
|
||||||
|
|
||||||
ClutterBackendGLX *backend;
|
|
||||||
|
|
||||||
ClutterStageState state;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterStageGLXClass
|
struct _ClutterStageGLXClass
|
||||||
{
|
{
|
||||||
ClutterStageClass parent_class;
|
ClutterStageX11Class parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType clutter_stage_glx_get_type (void) G_GNUC_CONST;
|
GType clutter_stage_glx_get_type (void) G_GNUC_CONST;
|
||||||
|
23
clutter/x11/Makefile.am
Normal file
23
clutter/x11/Makefile.am
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
libclutterincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter
|
||||||
|
libclutterinclude_HEADERS = clutter-x11.h
|
||||||
|
|
||||||
|
INCLUDES = \
|
||||||
|
-DG_LOG_DOMAIN=\"ClutterX11\" \
|
||||||
|
-I$(top_srcdir) \
|
||||||
|
-I$(top_srcdir)/clutter/cogl \
|
||||||
|
-I$(top_srcdir)/clutter/cogl/@CLUTTER_COGL@ \
|
||||||
|
$(CLUTTER_CFLAGS) \
|
||||||
|
$(CLUTTER_DEBUG_CFLAGS) \
|
||||||
|
$(GCC_FLAGS)
|
||||||
|
|
||||||
|
LDADD = $(CLUTTER_LIBS)
|
||||||
|
|
||||||
|
noinst_LTLIBRARIES = libclutter-x11.la
|
||||||
|
|
||||||
|
libclutter_x11_la_SOURCES = \
|
||||||
|
clutter-backend-x11.h \
|
||||||
|
clutter-backend-x11.c \
|
||||||
|
clutter-event-x11.c \
|
||||||
|
clutter-stage-x11.h \
|
||||||
|
clutter-stage-x11.c \
|
||||||
|
clutter-x11.h
|
32
clutter/x11/clutter-backend-x11-private.h
Normal file
32
clutter/x11/clutter-backend-x11-private.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Copyright (C) 2006-2007 OpenedHand
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_BACKEND_PRIVATE_X11_H__
|
||||||
|
#define __CLUTTER_BACKEND_PRIVATE_X11_H__
|
||||||
|
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void _clutter_backend_x11_events_init (ClutterBackend *backend);
|
||||||
|
void _clutter_backend_x11_events_uninit (ClutterBackend *backend);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
463
clutter/x11/clutter-backend-x11.c
Normal file
463
clutter/x11/clutter-backend-x11.c
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
/* Clutter.
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Copyright (C) 2006-2007 OpenedHand
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, 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 <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "clutter-backend-x11.h"
|
||||||
|
#include "clutter-stage-x11.h"
|
||||||
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
|
#include "../clutter-event.h"
|
||||||
|
#include "../clutter-main.h"
|
||||||
|
#include "../clutter-debug.h"
|
||||||
|
#include "../clutter-private.h"
|
||||||
|
|
||||||
|
#include "cogl.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
|
||||||
|
|
||||||
|
/* singleton object */
|
||||||
|
static ClutterBackendX11 *backend_singleton = NULL;
|
||||||
|
|
||||||
|
/* options */
|
||||||
|
static gchar *clutter_display_name = NULL;
|
||||||
|
static gint clutter_screen = 0;
|
||||||
|
static gboolean clutter_synchronise = FALSE;
|
||||||
|
|
||||||
|
/* X error trap */
|
||||||
|
static int TrappedErrorCode = 0;
|
||||||
|
static int (* old_error_handler) (Display *, XErrorEvent *);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_backend_x11_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_backend_x11_post_parse (ClutterBackend *backend,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
|
if (clutter_display_name)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "XOpenDisplay on `%s'", clutter_display_name);
|
||||||
|
backend_x11->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_x11->xdpy)
|
||||||
|
{
|
||||||
|
double dpi;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "Getting the X screen");
|
||||||
|
|
||||||
|
if (clutter_screen == 0)
|
||||||
|
backend_x11->xscreen = DefaultScreenOfDisplay (backend_x11->xdpy);
|
||||||
|
else
|
||||||
|
backend_x11->xscreen = ScreenOfDisplay (backend_x11->xdpy,
|
||||||
|
clutter_screen);
|
||||||
|
|
||||||
|
backend_x11->xscreen_num = XScreenNumberOfScreen (backend_x11->xscreen);
|
||||||
|
|
||||||
|
backend_x11->xwin_root = RootWindow (backend_x11->xdpy,
|
||||||
|
backend_x11->xscreen_num);
|
||||||
|
|
||||||
|
backend_x11->display_name = g_strdup (clutter_display_name);
|
||||||
|
|
||||||
|
dpi = (((double) DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num) * 25.4)
|
||||||
|
/ (double) DisplayHeightMM (backend_x11->xdpy, backend_x11->xscreen_num));
|
||||||
|
|
||||||
|
clutter_backend_set_resolution (backend, dpi);
|
||||||
|
|
||||||
|
if (clutter_synchronise)
|
||||||
|
XSynchronize (backend_x11->xdpy, True);
|
||||||
|
|
||||||
|
backend_x11->atom_WM_STATE
|
||||||
|
= XInternAtom (backend_x11->xdpy, "_NET_WM_STATE", False);
|
||||||
|
backend_x11->atom_WM_STATE_FULLSCREEN
|
||||||
|
= XInternAtom (backend_x11->xdpy, "_NET_WM_STATE_FULLSCREEN", False);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (clutter_display_name);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND,
|
||||||
|
"X Display `%s'[%p] opened (screen:%d, root:%u, dpi:%f)",
|
||||||
|
backend_x11->display_name,
|
||||||
|
backend_x11->xdpy,
|
||||||
|
backend_x11->xscreen_num,
|
||||||
|
(unsigned int) backend_x11->xwin_root,
|
||||||
|
clutter_backend_get_resolution (backend));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_x11_init_events (ClutterBackend *backend)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (EVENT, "initialising the event loop");
|
||||||
|
|
||||||
|
_clutter_backend_x11_events_init (backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterActor *
|
||||||
|
clutter_backend_x11_get_stage (ClutterBackend *backend)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
|
return backend_x11->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"
|
||||||
|
},
|
||||||
|
{ "synch", 0,
|
||||||
|
0,
|
||||||
|
G_OPTION_ARG_NONE, &clutter_synchronise,
|
||||||
|
"Make X calls synchronous", NULL,
|
||||||
|
},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_backend_x11_add_options (ClutterBackend *backend,
|
||||||
|
GOptionGroup *group)
|
||||||
|
{
|
||||||
|
g_option_group_add_entries (group, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_x11_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
|
||||||
|
|
||||||
|
g_free (backend_x11->display_name);
|
||||||
|
|
||||||
|
XCloseDisplay (backend_x11->xdpy);
|
||||||
|
|
||||||
|
if (backend_singleton)
|
||||||
|
backend_singleton = NULL;
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_backend_x11_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_x11_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
|
||||||
|
|
||||||
|
if (backend_x11->stage)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND, "Disposing the main stage");
|
||||||
|
|
||||||
|
clutter_actor_destroy (backend_x11->stage);
|
||||||
|
backend_x11->stage = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "Removing the event source");
|
||||||
|
_clutter_backend_x11_events_uninit (CLUTTER_BACKEND (backend_x11));
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_backend_x11_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
clutter_backend_x11_constructor (GType gtype,
|
||||||
|
guint n_params,
|
||||||
|
GObjectConstructParam *params)
|
||||||
|
{
|
||||||
|
GObjectClass *parent_class;
|
||||||
|
GObject *retval;
|
||||||
|
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
parent_class = G_OBJECT_CLASS (clutter_backend_x11_parent_class);
|
||||||
|
retval = parent_class->constructor (gtype, n_params, params);
|
||||||
|
|
||||||
|
backend_singleton = CLUTTER_BACKEND_X11 (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterFeatureFlags
|
||||||
|
clutter_backend_x11_get_features (ClutterBackend *backend)
|
||||||
|
{
|
||||||
|
ClutterFeatureFlags flags = 0;
|
||||||
|
|
||||||
|
/* FIXME: we really need to check if gl context is set */
|
||||||
|
|
||||||
|
flags = CLUTTER_FEATURE_STAGE_USER_RESIZE|CLUTTER_FEATURE_STAGE_CURSOR;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_x11_class_init (ClutterBackendX11Class *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->constructor = clutter_backend_x11_constructor;
|
||||||
|
gobject_class->dispose = clutter_backend_x11_dispose;
|
||||||
|
gobject_class->finalize = clutter_backend_x11_finalize;
|
||||||
|
|
||||||
|
backend_class->pre_parse = clutter_backend_x11_pre_parse;
|
||||||
|
backend_class->post_parse = clutter_backend_x11_post_parse;
|
||||||
|
backend_class->init_events = clutter_backend_x11_init_events;
|
||||||
|
backend_class->get_stage = clutter_backend_x11_get_stage;
|
||||||
|
backend_class->add_options = clutter_backend_x11_add_options;
|
||||||
|
backend_class->get_features = clutter_backend_x11_get_features;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_x11_init (ClutterBackendX11 *backend_x11)
|
||||||
|
{
|
||||||
|
ClutterBackend *backend = CLUTTER_BACKEND (backend_x11);
|
||||||
|
|
||||||
|
/* FIXME: get from xsettings */
|
||||||
|
clutter_backend_set_double_click_time (backend, 250);
|
||||||
|
clutter_backend_set_double_click_distance (backend, 5);
|
||||||
|
clutter_backend_set_resolution (backend, 96.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
error_handler(Display *xdpy,
|
||||||
|
XErrorEvent *error)
|
||||||
|
{
|
||||||
|
TrappedErrorCode = error->error_code;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_trap_x_errors:
|
||||||
|
*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_x11_trap_x_errors (void)
|
||||||
|
{
|
||||||
|
TrappedErrorCode = 0;
|
||||||
|
old_error_handler = XSetErrorHandler (error_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_untrap_x_errors:
|
||||||
|
*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* Return value: FIXME
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
gint
|
||||||
|
clutter_x11_untrap_x_errors (void)
|
||||||
|
{
|
||||||
|
XSetErrorHandler (old_error_handler);
|
||||||
|
|
||||||
|
return TrappedErrorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_get_default_display:
|
||||||
|
*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* Return value: FIXME
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
Display *
|
||||||
|
clutter_x11_get_default_display (void)
|
||||||
|
{
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return backend_singleton->xdpy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_get_default_screen:
|
||||||
|
*
|
||||||
|
* Gets the pointer to the default X Screen object.
|
||||||
|
*
|
||||||
|
* Return value: FIXME
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clutter_x11_get_default_screen (void)
|
||||||
|
{
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return backend_singleton->xscreen_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_get_root_window:
|
||||||
|
*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* Return value: FIXME
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
Window
|
||||||
|
clutter_x11_get_root_window (void)
|
||||||
|
{
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return backend_singleton->xwin_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_add_filter:
|
||||||
|
*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* Return value: FIXME
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_x11_add_filter (ClutterX11FilterFunc func, gpointer data)
|
||||||
|
{
|
||||||
|
ClutterX11EventFilter *filter;
|
||||||
|
|
||||||
|
g_return_if_fail (func != NULL);
|
||||||
|
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = g_new0(ClutterX11EventFilter, 1);
|
||||||
|
filter->func = func;
|
||||||
|
filter->data = data;
|
||||||
|
|
||||||
|
backend_singleton->event_filters
|
||||||
|
= g_slist_append (backend_singleton->event_filters, filter);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_remove_filter:
|
||||||
|
*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* Return value: FIXME
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_x11_remove_filter (ClutterX11FilterFunc func, gpointer data)
|
||||||
|
{
|
||||||
|
GSList *tmp_list, *this;
|
||||||
|
ClutterX11EventFilter *filter;
|
||||||
|
|
||||||
|
g_return_if_fail (func == NULL);
|
||||||
|
|
||||||
|
tmp_list = backend_singleton->event_filters;
|
||||||
|
|
||||||
|
while (tmp_list)
|
||||||
|
{
|
||||||
|
filter = (ClutterX11EventFilter *)tmp_list->data;
|
||||||
|
this = tmp_list;
|
||||||
|
tmp_list = tmp_list->next;
|
||||||
|
|
||||||
|
if (filter->func == func && filter->data == data)
|
||||||
|
{
|
||||||
|
backend_singleton->event_filters
|
||||||
|
= g_slist_remove_link (backend_singleton->event_filters, this);
|
||||||
|
|
||||||
|
g_slist_free_1 (this);
|
||||||
|
g_free (filter);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
clutter/x11/clutter-backend-x11.h
Normal file
110
clutter/x11/clutter-backend-x11.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* Clutter.
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Copyright (C) 2006-2007 OpenedHand
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_BACKEND_X11_H__
|
||||||
|
#define __CLUTTER_BACKEND_X11_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-event.h>
|
||||||
|
#include <clutter/clutter-backend.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_BACKEND_X11 (clutter_backend_x11_get_type ())
|
||||||
|
#define CLUTTER_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_X11, ClutterBackendX11))
|
||||||
|
#define CLUTTER_IS_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_X11))
|
||||||
|
#define CLUTTER_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_X11, ClutterBackendX11Class))
|
||||||
|
#define CLUTTER_IS_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_X11))
|
||||||
|
#define CLUTTER_BACKEND_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_X11, ClutterBackendX11Class))
|
||||||
|
|
||||||
|
typedef struct _ClutterBackendX11 ClutterBackendX11;
|
||||||
|
typedef struct _ClutterBackendX11Class ClutterBackendX11Class;
|
||||||
|
|
||||||
|
typedef struct _ClutterX11EventFilter
|
||||||
|
{
|
||||||
|
ClutterX11FilterFunc func;
|
||||||
|
gpointer data;
|
||||||
|
|
||||||
|
} ClutterX11EventFilter;
|
||||||
|
|
||||||
|
struct _ClutterBackendX11
|
||||||
|
{
|
||||||
|
ClutterBackend parent_instance;
|
||||||
|
|
||||||
|
/* main stage singleton */
|
||||||
|
ClutterActor *stage;
|
||||||
|
|
||||||
|
Display *xdpy;
|
||||||
|
Window xwin_root;
|
||||||
|
Screen *xscreen;
|
||||||
|
int xscreen_num;
|
||||||
|
gchar *display_name;
|
||||||
|
|
||||||
|
/* event source */
|
||||||
|
GSource *event_source;
|
||||||
|
GSList *event_filters;
|
||||||
|
|
||||||
|
/* props */
|
||||||
|
Atom atom_WM_STATE;
|
||||||
|
Atom atom_WM_STATE_FULLSCREEN;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterBackendX11Class
|
||||||
|
{
|
||||||
|
ClutterBackendClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
void _clutter_backend_x11_events_init (ClutterBackend *backend);
|
||||||
|
void _clutter_backend_x11_events_uninit (ClutterBackend *backend);
|
||||||
|
|
||||||
|
GType clutter_backend_x11_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
/* Private to glx/eglx backends */
|
||||||
|
gboolean
|
||||||
|
clutter_backend_x11_pre_parse (ClutterBackend *backend,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_backend_x11_post_parse (ClutterBackend *backend,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_backend_x11_init_stage (ClutterBackend *backend,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
ClutterActor *
|
||||||
|
clutter_backend_x11_get_stage (ClutterBackend *backend);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_backend_x11_add_options (ClutterBackend *backend,
|
||||||
|
GOptionGroup *group);
|
||||||
|
|
||||||
|
ClutterFeatureFlags
|
||||||
|
clutter_backend_x11_get_features (ClutterBackend *backend);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_BACKEND_X11_H__ */
|
@ -19,13 +19,11 @@
|
|||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "clutter-stage-glx.h"
|
#include "clutter-stage-x11.h"
|
||||||
#include "clutter-backend-glx.h"
|
#include "clutter-backend-x11.h"
|
||||||
#include "clutter-glx.h"
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
#include "../clutter-backend.h"
|
#include "../clutter-backend.h"
|
||||||
#include "../clutter-event.h"
|
#include "../clutter-event.h"
|
||||||
@ -107,7 +105,7 @@ clutter_event_source_new (ClutterBackend *backend)
|
|||||||
static gboolean
|
static gboolean
|
||||||
check_xpending (ClutterBackend *backend)
|
check_xpending (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
return XPending (CLUTTER_BACKEND_GLX (backend)->xdpy);
|
return XPending (CLUTTER_BACKEND_X11 (backend)->xdpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -132,12 +130,12 @@ xembed_send_message (Display *xdisplay,
|
|||||||
ev.xclient.data.l[3] = data1;
|
ev.xclient.data.l[3] = data1;
|
||||||
ev.xclient.data.l[4] = data2;
|
ev.xclient.data.l[4] = data2;
|
||||||
|
|
||||||
clutter_glx_trap_x_errors ();
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
XSendEvent (xdisplay, window, False, NoEventMask, &ev);
|
XSendEvent (xdisplay, window, False, NoEventMask, &ev);
|
||||||
XSync (xdisplay, False);
|
XSync (xdisplay, False);
|
||||||
|
|
||||||
if (clutter_glx_untrap_x_errors ())
|
if (clutter_x11_untrap_x_errors ())
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
@ -156,29 +154,29 @@ xembed_set_info (Display *xdisplay,
|
|||||||
list[0] = MAX_SUPPORTED_XEMBED_VERSION;
|
list[0] = MAX_SUPPORTED_XEMBED_VERSION;
|
||||||
list[1] = XEMBED_MAPPED;
|
list[1] = XEMBED_MAPPED;
|
||||||
|
|
||||||
clutter_glx_trap_x_errors ();
|
clutter_x11_trap_x_errors ();
|
||||||
XChangeProperty (xdisplay, window,
|
XChangeProperty (xdisplay, window,
|
||||||
atom_XEMBED_INFO,
|
atom_XEMBED_INFO,
|
||||||
atom_XEMBED_INFO, 32,
|
atom_XEMBED_INFO, 32,
|
||||||
PropModeReplace, (unsigned char *) list, 2);
|
PropModeReplace, (unsigned char *) list, 2);
|
||||||
clutter_glx_untrap_x_errors ();
|
clutter_x11_untrap_x_errors ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_clutter_backend_glx_events_init (ClutterBackend *backend)
|
_clutter_backend_x11_events_init (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
GSource *source;
|
GSource *source;
|
||||||
ClutterEventSource *event_source;
|
ClutterEventSource *event_source;
|
||||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
int connection_number;
|
int connection_number;
|
||||||
|
|
||||||
connection_number = ConnectionNumber (backend_glx->xdpy);
|
connection_number = ConnectionNumber (backend_x11->xdpy);
|
||||||
CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number);
|
CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number);
|
||||||
|
|
||||||
Atom_XEMBED = XInternAtom (backend_glx->xdpy, "_XEMBED", False);
|
Atom_XEMBED = XInternAtom (backend_x11->xdpy, "_XEMBED", False);
|
||||||
Atom_WM_PROTOCOLS = XInternAtom (backend_glx->xdpy, "WM_PROTOCOLS", False);
|
Atom_WM_PROTOCOLS = XInternAtom (backend_x11->xdpy, "WM_PROTOCOLS", False);
|
||||||
|
|
||||||
source = backend_glx->event_source = clutter_event_source_new (backend);
|
source = backend_x11->event_source = clutter_event_source_new (backend);
|
||||||
event_source = (ClutterEventSource *) source;
|
event_source = (ClutterEventSource *) source;
|
||||||
g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
|
g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
|
||||||
|
|
||||||
@ -191,30 +189,30 @@ _clutter_backend_glx_events_init (ClutterBackend *backend)
|
|||||||
g_source_set_can_recurse (source, TRUE);
|
g_source_set_can_recurse (source, TRUE);
|
||||||
g_source_attach (source, NULL);
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
xembed_set_info (backend_glx->xdpy,
|
xembed_set_info (backend_x11->xdpy,
|
||||||
clutter_glx_get_stage_window (CLUTTER_STAGE (backend_glx->stage)),
|
clutter_x11_get_stage_window
|
||||||
|
(CLUTTER_STAGE (backend_x11->stage)),
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_clutter_backend_glx_events_uninit (ClutterBackend *backend)
|
_clutter_backend_x11_events_uninit (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
|
||||||
if (backend_glx->event_source)
|
if (backend_x11->event_source)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (EVENT, "Destroying the event source");
|
CLUTTER_NOTE (EVENT, "Destroying the event source");
|
||||||
|
|
||||||
event_sources = g_list_remove (event_sources,
|
event_sources = g_list_remove (event_sources,
|
||||||
backend_glx->event_source);
|
backend_x11->event_source);
|
||||||
|
|
||||||
g_source_destroy (backend_glx->event_source);
|
g_source_destroy (backend_x11->event_source);
|
||||||
g_source_unref (backend_glx->event_source);
|
g_source_unref (backend_x11->event_source);
|
||||||
backend_glx->event_source = NULL;
|
backend_x11->event_source = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_user_time (Display *display,
|
set_user_time (Display *display,
|
||||||
Window *xwindow,
|
Window *xwindow,
|
||||||
@ -256,20 +254,20 @@ translate_key_event (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_wm_protocols_event (ClutterBackendGLX *backend_glx,
|
handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
|
||||||
XEvent *xevent)
|
XEvent *xevent)
|
||||||
{
|
{
|
||||||
Atom atom = (Atom) xevent->xclient.data.l[0];
|
Atom atom = (Atom) xevent->xclient.data.l[0];
|
||||||
Atom Atom_WM_DELETE_WINDOW;
|
Atom Atom_WM_DELETE_WINDOW;
|
||||||
Atom Atom_NEW_WM_PING;
|
Atom Atom_NEW_WM_PING;
|
||||||
|
|
||||||
ClutterStage *stage = CLUTTER_STAGE (backend_glx->stage);
|
ClutterStage *stage = CLUTTER_STAGE (backend_x11->stage);
|
||||||
Window stage_xwindow = clutter_glx_get_stage_window (stage);
|
Window stage_xwindow = clutter_x11_get_stage_window (stage);
|
||||||
|
|
||||||
Atom_WM_DELETE_WINDOW = XInternAtom (backend_glx->xdpy,
|
Atom_WM_DELETE_WINDOW = XInternAtom (backend_x11->xdpy,
|
||||||
"WM_DELETE_WINDOW",
|
"WM_DELETE_WINDOW",
|
||||||
False);
|
False);
|
||||||
Atom_NEW_WM_PING = XInternAtom (backend_glx->xdpy, "_NET_WM_PING", False);
|
Atom_NEW_WM_PING = XInternAtom (backend_x11->xdpy, "_NET_WM_PING", False);
|
||||||
|
|
||||||
if (atom == Atom_WM_DELETE_WINDOW &&
|
if (atom == Atom_WM_DELETE_WINDOW &&
|
||||||
xevent->xany.window == stage_xwindow)
|
xevent->xany.window == stage_xwindow)
|
||||||
@ -282,7 +280,7 @@ handle_wm_protocols_event (ClutterBackendGLX *backend_glx,
|
|||||||
CLUTTER_NOTE (EVENT, "delete window:\twindow: %ld",
|
CLUTTER_NOTE (EVENT, "delete window:\twindow: %ld",
|
||||||
xevent->xclient.window);
|
xevent->xclient.window);
|
||||||
|
|
||||||
set_user_time (backend_glx->xdpy,
|
set_user_time (backend_x11->xdpy,
|
||||||
&stage_xwindow,
|
&stage_xwindow,
|
||||||
xevent->xclient.data.l[1]);
|
xevent->xclient.data.l[1]);
|
||||||
|
|
||||||
@ -293,8 +291,8 @@ handle_wm_protocols_event (ClutterBackendGLX *backend_glx,
|
|||||||
{
|
{
|
||||||
XClientMessageEvent xclient = xevent->xclient;
|
XClientMessageEvent xclient = xevent->xclient;
|
||||||
|
|
||||||
xclient.window = backend_glx->xwin_root;
|
xclient.window = backend_x11->xwin_root;
|
||||||
XSendEvent (backend_glx->xdpy, xclient.window,
|
XSendEvent (backend_x11->xdpy, xclient.window,
|
||||||
False,
|
False,
|
||||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||||
(XEvent *) &xclient);
|
(XEvent *) &xclient);
|
||||||
@ -307,12 +305,12 @@ handle_wm_protocols_event (ClutterBackendGLX *backend_glx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_xembed_event (ClutterBackendGLX *backend_glx,
|
handle_xembed_event (ClutterBackendX11 *backend_x11,
|
||||||
XEvent *xevent)
|
XEvent *xevent)
|
||||||
{
|
{
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
|
|
||||||
stage = _clutter_backend_get_stage (CLUTTER_BACKEND (backend_glx));
|
stage = _clutter_backend_get_stage (CLUTTER_BACKEND (backend_x11));
|
||||||
|
|
||||||
switch (xevent->xclient.data.l[1])
|
switch (xevent->xclient.data.l[1])
|
||||||
{
|
{
|
||||||
@ -325,8 +323,8 @@ handle_xembed_event (ClutterBackendGLX *backend_glx,
|
|||||||
clutter_actor_realize (stage);
|
clutter_actor_realize (stage);
|
||||||
clutter_actor_show (stage);
|
clutter_actor_show (stage);
|
||||||
|
|
||||||
xembed_set_info (backend_glx->xdpy,
|
xembed_set_info (backend_x11->xdpy,
|
||||||
clutter_glx_get_stage_window (CLUTTER_STAGE (stage)),
|
clutter_x11_get_stage_window (CLUTTER_STAGE (stage)),
|
||||||
XEMBED_MAPPED);
|
XEMBED_MAPPED);
|
||||||
break;
|
break;
|
||||||
case XEMBED_WINDOW_ACTIVATE:
|
case XEMBED_WINDOW_ACTIVATE:
|
||||||
@ -338,7 +336,7 @@ handle_xembed_event (ClutterBackendGLX *backend_glx,
|
|||||||
case XEMBED_FOCUS_IN:
|
case XEMBED_FOCUS_IN:
|
||||||
CLUTTER_NOTE (EVENT, "got XEMBED_FOCUS_IN");
|
CLUTTER_NOTE (EVENT, "got XEMBED_FOCUS_IN");
|
||||||
if (ParentEmbedderWin)
|
if (ParentEmbedderWin)
|
||||||
xembed_send_message (backend_glx->xdpy, ParentEmbedderWin,
|
xembed_send_message (backend_x11->xdpy, ParentEmbedderWin,
|
||||||
XEMBED_FOCUS_NEXT,
|
XEMBED_FOCUS_NEXT,
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
break;
|
break;
|
||||||
@ -356,39 +354,39 @@ event_translate (ClutterBackend *backend,
|
|||||||
ClutterEvent *event,
|
ClutterEvent *event,
|
||||||
XEvent *xevent)
|
XEvent *xevent)
|
||||||
{
|
{
|
||||||
ClutterBackendGLX *backend_glx;
|
ClutterBackendX11 *backend_x11;
|
||||||
ClutterStageGLX *stage_glx;
|
ClutterStageX11 *stage_x11;
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
Window xwindow, stage_xwindow;
|
Window xwindow, stage_xwindow;
|
||||||
|
|
||||||
backend_glx = CLUTTER_BACKEND_GLX (backend);
|
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend));
|
stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend));
|
||||||
stage_glx = CLUTTER_STAGE_GLX (stage);
|
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
stage_xwindow = clutter_glx_get_stage_window (stage);
|
stage_xwindow = clutter_x11_get_stage_window (stage);
|
||||||
|
|
||||||
xwindow = xevent->xany.window;
|
xwindow = xevent->xany.window;
|
||||||
if (xwindow == None)
|
if (xwindow == None)
|
||||||
xwindow = stage_xwindow;
|
xwindow = stage_xwindow;
|
||||||
|
|
||||||
if (backend_glx->event_filters)
|
if (backend_x11->event_filters)
|
||||||
{
|
{
|
||||||
GSList *node;
|
GSList *node;
|
||||||
ClutterGLXEventFilter *filter;
|
ClutterX11EventFilter *filter;
|
||||||
|
|
||||||
node = backend_glx->event_filters;
|
node = backend_x11->event_filters;
|
||||||
|
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
filter = (ClutterGLXEventFilter *)node->data;
|
filter = (ClutterX11EventFilter *)node->data;
|
||||||
|
|
||||||
switch (filter->func(xevent, event, filter->data))
|
switch (filter->func(xevent, event, filter->data))
|
||||||
{
|
{
|
||||||
case CLUTTER_GLX_FILTER_CONTINUE:
|
case CLUTTER_X11_FILTER_CONTINUE:
|
||||||
break;
|
break;
|
||||||
case CLUTTER_GLX_FILTER_TRANSLATE:
|
case CLUTTER_X11_FILTER_TRANSLATE:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case CLUTTER_GLX_FILTER_REMOVE:
|
case CLUTTER_X11_FILTER_REMOVE:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -414,7 +412,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
break;
|
break;
|
||||||
case PropertyNotify:
|
case PropertyNotify:
|
||||||
{
|
{
|
||||||
if (xevent->xproperty.atom == backend_glx->atom_WM_STATE)
|
if (xevent->xproperty.atom == backend_x11->atom_WM_STATE)
|
||||||
{
|
{
|
||||||
Atom type;
|
Atom type;
|
||||||
gint format;
|
gint format;
|
||||||
@ -424,15 +422,15 @@ event_translate (ClutterBackend *backend,
|
|||||||
gulong i;
|
gulong i;
|
||||||
gboolean fullscreen_set = FALSE;
|
gboolean fullscreen_set = FALSE;
|
||||||
|
|
||||||
clutter_glx_trap_x_errors ();
|
clutter_x11_trap_x_errors ();
|
||||||
XGetWindowProperty (backend_glx->xdpy,
|
XGetWindowProperty (backend_x11->xdpy,
|
||||||
stage_xwindow,
|
stage_xwindow,
|
||||||
backend_glx->atom_WM_STATE,
|
backend_x11->atom_WM_STATE,
|
||||||
0, G_MAXLONG,
|
0, G_MAXLONG,
|
||||||
False, XA_ATOM,
|
False, XA_ATOM,
|
||||||
&type, &format, &nitems,
|
&type, &format, &nitems,
|
||||||
&bytes_after, &data);
|
&bytes_after, &data);
|
||||||
clutter_glx_untrap_x_errors ();
|
clutter_x11_untrap_x_errors ();
|
||||||
|
|
||||||
if (type != None && data != NULL)
|
if (type != None && data != NULL)
|
||||||
{
|
{
|
||||||
@ -441,23 +439,23 @@ event_translate (ClutterBackend *backend,
|
|||||||
i = 0;
|
i = 0;
|
||||||
while (i < nitems)
|
while (i < nitems)
|
||||||
{
|
{
|
||||||
if (atoms[i] == backend_glx->atom_WM_STATE_FULLSCREEN)
|
if (atoms[i] == backend_x11->atom_WM_STATE_FULLSCREEN)
|
||||||
fullscreen_set = TRUE;
|
fullscreen_set = TRUE;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullscreen_set
|
if (fullscreen_set
|
||||||
!= !!(stage_glx->state & CLUTTER_STAGE_STATE_FULLSCREEN))
|
!= !!(stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN))
|
||||||
{
|
{
|
||||||
if (fullscreen_set)
|
if (fullscreen_set)
|
||||||
stage_glx->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
|
stage_x11->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
|
||||||
else
|
else
|
||||||
stage_glx->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
|
stage_x11->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
|
||||||
|
|
||||||
event->type = CLUTTER_STAGE_STATE;
|
event->type = CLUTTER_STAGE_STATE;
|
||||||
event->stage_state.changed_mask
|
event->stage_state.changed_mask
|
||||||
= CLUTTER_STAGE_STATE_FULLSCREEN;
|
= CLUTTER_STAGE_STATE_FULLSCREEN;
|
||||||
event->stage_state.new_state = stage_glx->state;
|
event->stage_state.new_state = stage_x11->state;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
@ -470,26 +468,26 @@ event_translate (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FocusIn:
|
case FocusIn:
|
||||||
if (!(stage_glx->state & CLUTTER_STAGE_STATE_ACTIVATED))
|
if (!(stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED))
|
||||||
{
|
{
|
||||||
/* TODO: check xevent->xfocus.detail ? */
|
/* TODO: check xevent->xfocus.detail ? */
|
||||||
stage_glx->state |= CLUTTER_STAGE_STATE_ACTIVATED;
|
stage_x11->state |= CLUTTER_STAGE_STATE_ACTIVATED;
|
||||||
|
|
||||||
event->type = CLUTTER_STAGE_STATE;
|
event->type = CLUTTER_STAGE_STATE;
|
||||||
event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
|
event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
|
||||||
event->stage_state.new_state = stage_glx->state;
|
event->stage_state.new_state = stage_x11->state;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
case FocusOut:
|
case FocusOut:
|
||||||
if (stage_glx->state & CLUTTER_STAGE_STATE_ACTIVATED)
|
if (stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED)
|
||||||
{
|
{
|
||||||
stage_glx->state &= ~CLUTTER_STAGE_STATE_ACTIVATED;
|
stage_x11->state &= ~CLUTTER_STAGE_STATE_ACTIVATED;
|
||||||
|
|
||||||
event->type = CLUTTER_STAGE_STATE;
|
event->type = CLUTTER_STAGE_STATE;
|
||||||
event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
|
event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
|
||||||
event->stage_state.new_state = stage_glx->state;
|
event->stage_state.new_state = stage_x11->state;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
@ -499,7 +497,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
XEvent foo_xev;
|
XEvent foo_xev;
|
||||||
|
|
||||||
/* Cheap compress */
|
/* Cheap compress */
|
||||||
while (XCheckTypedWindowEvent (backend_glx->xdpy,
|
while (XCheckTypedWindowEvent (backend_x11->xdpy,
|
||||||
xevent->xexpose.window,
|
xevent->xexpose.window,
|
||||||
Expose,
|
Expose,
|
||||||
&foo_xev));
|
&foo_xev));
|
||||||
@ -514,7 +512,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
case KeyPress:
|
case KeyPress:
|
||||||
event->type = CLUTTER_KEY_PRESS;
|
event->type = CLUTTER_KEY_PRESS;
|
||||||
translate_key_event (backend, event, xevent);
|
translate_key_event (backend, event, xevent);
|
||||||
set_user_time (backend_glx->xdpy, &xwindow, xevent->xkey.time);
|
set_user_time (backend_x11->xdpy, &xwindow, xevent->xkey.time);
|
||||||
break;
|
break;
|
||||||
case KeyRelease:
|
case KeyRelease:
|
||||||
event->type = CLUTTER_KEY_RELEASE;
|
event->type = CLUTTER_KEY_RELEASE;
|
||||||
@ -555,7 +553,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_user_time (backend_glx->xdpy, &xwindow, event->button.time);
|
set_user_time (backend_x11->xdpy, &xwindow, event->button.time);
|
||||||
break;
|
break;
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
/* scroll events don't have a corresponding release */
|
/* scroll events don't have a corresponding release */
|
||||||
@ -593,10 +591,10 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->type = event->any.type = CLUTTER_CLIENT_MESSAGE;
|
event->type = event->any.type = CLUTTER_CLIENT_MESSAGE;
|
||||||
|
|
||||||
if (xevent->xclient.message_type == Atom_XEMBED)
|
if (xevent->xclient.message_type == Atom_XEMBED)
|
||||||
res = handle_xembed_event (backend_glx, xevent);
|
res = handle_xembed_event (backend_x11, xevent);
|
||||||
else if (xevent->xclient.message_type == Atom_WM_PROTOCOLS)
|
else if (xevent->xclient.message_type == Atom_WM_PROTOCOLS)
|
||||||
{
|
{
|
||||||
res = handle_wm_protocols_event (backend_glx, xevent);
|
res = handle_wm_protocols_event (backend_x11, xevent);
|
||||||
event->type = event->any.type = CLUTTER_DELETE;
|
event->type = event->any.type = CLUTTER_DELETE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -612,9 +610,9 @@ event_translate (ClutterBackend *backend,
|
|||||||
static void
|
static void
|
||||||
events_queue (ClutterBackend *backend)
|
events_queue (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
ClutterEvent *event;
|
ClutterEvent *event;
|
||||||
Display *xdisplay = backend_glx->xdpy;
|
Display *xdisplay = backend_x11->xdpy;
|
||||||
XEvent xevent;
|
XEvent xevent;
|
||||||
ClutterMainContext *clutter_context;
|
ClutterMainContext *clutter_context;
|
||||||
|
|
524
clutter/x11/clutter-stage-x11.c
Normal file
524
clutter/x11/clutter-stage-x11.c
Normal file
@ -0,0 +1,524 @@
|
|||||||
|
/* Clutter.
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Copyright (C) 2006-2007 OpenedHand
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, 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-x11.h"
|
||||||
|
#include "clutter-stage-x11.h"
|
||||||
|
#include "clutter-x11.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 "../clutter-units.h"
|
||||||
|
|
||||||
|
#include "cogl.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_XFIXES
|
||||||
|
#include <X11/extensions/Xfixes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterStageX11, clutter_stage_x11, CLUTTER_TYPE_STAGE);
|
||||||
|
|
||||||
|
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
|
||||||
|
#define _NET_WM_STATE_ADD 1 /* add/set property */
|
||||||
|
#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_wmspec_change_state (ClutterBackendX11 *backend_x11,
|
||||||
|
Window window,
|
||||||
|
Atom state,
|
||||||
|
gboolean add)
|
||||||
|
{
|
||||||
|
XClientMessageEvent xclient;
|
||||||
|
|
||||||
|
memset (&xclient, 0, sizeof (xclient));
|
||||||
|
|
||||||
|
xclient.type = ClientMessage;
|
||||||
|
xclient.window = window;
|
||||||
|
xclient.message_type = backend_x11->atom_WM_STATE;
|
||||||
|
xclient.format = 32;
|
||||||
|
|
||||||
|
xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
||||||
|
xclient.data.l[1] = state;
|
||||||
|
xclient.data.l[2] = 0;
|
||||||
|
xclient.data.l[3] = 0;
|
||||||
|
xclient.data.l[4] = 0;
|
||||||
|
|
||||||
|
XSendEvent (backend_x11->xdpy,
|
||||||
|
DefaultRootWindow(backend_x11->xdpy),
|
||||||
|
False,
|
||||||
|
SubstructureRedirectMask|SubstructureNotifyMask,
|
||||||
|
(XEvent *)&xclient);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11)
|
||||||
|
{
|
||||||
|
gboolean resize;
|
||||||
|
|
||||||
|
resize = clutter_stage_get_user_resizable (CLUTTER_STAGE (stage_x11));
|
||||||
|
|
||||||
|
if (stage_x11->xwin != None && stage_x11->is_foreign_xwin == FALSE)
|
||||||
|
{
|
||||||
|
XSizeHints *size_hints;
|
||||||
|
|
||||||
|
size_hints = XAllocSizeHints();
|
||||||
|
|
||||||
|
if (!resize)
|
||||||
|
{
|
||||||
|
size_hints->max_width
|
||||||
|
= size_hints->min_width = stage_x11->xwin_width;
|
||||||
|
size_hints->max_height
|
||||||
|
= size_hints->min_height = stage_x11->xwin_height;
|
||||||
|
size_hints->flags = PMinSize|PMaxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
XSetWMNormalHints (stage_x11->xdpy, stage_x11->xwin, size_hints);
|
||||||
|
|
||||||
|
XFree(size_hints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_show (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||||
|
|
||||||
|
/* Chain up to set mapped flags */
|
||||||
|
CLUTTER_ACTOR_CLASS (clutter_stage_x11_parent_class)->show(actor);
|
||||||
|
|
||||||
|
if (stage_x11->xwin)
|
||||||
|
{
|
||||||
|
/* Fire off a redraw to avoid flicker on first map.
|
||||||
|
* Appears not to work perfectly on intel drivers at least.
|
||||||
|
*/
|
||||||
|
clutter_redraw();
|
||||||
|
XSync (stage_x11->xdpy, FALSE);
|
||||||
|
XMapWindow (stage_x11->xdpy, stage_x11->xwin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_hide (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||||
|
|
||||||
|
if (stage_x11->xwin)
|
||||||
|
XUnmapWindow (stage_x11->xdpy, stage_x11->xwin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_stage_x11_set_wm_protocols (Display *xdisplay,
|
||||||
|
Window xwindow)
|
||||||
|
{
|
||||||
|
Atom protocols[2];
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
protocols[n++] = XInternAtom (xdisplay, "WM_DELETE_WINDOW", False);
|
||||||
|
protocols[n++] = XInternAtom (xdisplay, "_NET_WM_PING", False);
|
||||||
|
|
||||||
|
XSetWMProtocols (xdisplay, xwindow, protocols, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_query_coords (ClutterActor *self,
|
||||||
|
ClutterActorBox *box)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (self);
|
||||||
|
|
||||||
|
box->x1 = box->y1 = 0;
|
||||||
|
box->x2 = box->x1 + CLUTTER_UNITS_FROM_INT (stage_x11->xwin_width);
|
||||||
|
box->y2 = box->y1 + CLUTTER_UNITS_FROM_INT (stage_x11->xwin_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_request_coords (ClutterActor *self,
|
||||||
|
ClutterActorBox *box)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (self);
|
||||||
|
gint new_width, new_height;
|
||||||
|
|
||||||
|
new_width = ABS (CLUTTER_UNITS_TO_INT (box->x2 - box->x1));
|
||||||
|
new_height = ABS (CLUTTER_UNITS_TO_INT (box->y2 - box->y1));
|
||||||
|
|
||||||
|
if (new_width != stage_x11->xwin_width ||
|
||||||
|
new_height != stage_x11->xwin_height)
|
||||||
|
{
|
||||||
|
stage_x11->xwin_width = new_width;
|
||||||
|
stage_x11->xwin_height = new_height;
|
||||||
|
|
||||||
|
if (stage_x11->xwin != None)
|
||||||
|
{
|
||||||
|
XResizeWindow (stage_x11->xdpy,
|
||||||
|
stage_x11->xwin,
|
||||||
|
stage_x11->xwin_width,
|
||||||
|
stage_x11->xwin_height);
|
||||||
|
|
||||||
|
clutter_stage_x11_fix_window_size (stage_x11);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stage_x11->xpixmap != None)
|
||||||
|
{
|
||||||
|
/* Need to recreate to resize */
|
||||||
|
clutter_actor_unrealize (self);
|
||||||
|
clutter_actor_realize (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stage_x11->xwin != None) /* Do we want to bother ? */
|
||||||
|
XMoveWindow (stage_x11->xdpy,
|
||||||
|
stage_x11->xwin,
|
||||||
|
CLUTTER_UNITS_TO_INT (box->x1),
|
||||||
|
CLUTTER_UNITS_TO_INT (box->y1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_set_fullscreen (ClutterStage *stage,
|
||||||
|
gboolean fullscreen)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
|
ClutterBackendX11 *backend_x11 = stage_x11->backend;
|
||||||
|
|
||||||
|
static gboolean was_resizeable = FALSE;
|
||||||
|
|
||||||
|
if (fullscreen)
|
||||||
|
{
|
||||||
|
if (stage_x11->xwin != None)
|
||||||
|
{
|
||||||
|
if (!CLUTTER_ACTOR_IS_MAPPED(CLUTTER_ACTOR (stage_x11)))
|
||||||
|
{
|
||||||
|
gint width, height;
|
||||||
|
|
||||||
|
width = DisplayWidth (stage_x11->xdpy, stage_x11->xscreen);
|
||||||
|
height = DisplayHeight (stage_x11->xdpy, stage_x11->xscreen);
|
||||||
|
|
||||||
|
clutter_actor_set_size (CLUTTER_ACTOR (stage_x11),
|
||||||
|
width, height);
|
||||||
|
/* FIXME: This wont work if we support more states */
|
||||||
|
XChangeProperty
|
||||||
|
(stage_x11->xdpy,
|
||||||
|
stage_x11->xwin,
|
||||||
|
backend_x11->atom_WM_STATE, XA_ATOM, 32,
|
||||||
|
PropModeReplace,
|
||||||
|
(unsigned char *)&backend_x11->atom_WM_STATE_FULLSCREEN,
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We need to set window user resize-able for metacity at
|
||||||
|
* at least to allow the window to fullscreen *sigh*
|
||||||
|
*/
|
||||||
|
if (clutter_stage_get_user_resizable (stage) == TRUE)
|
||||||
|
was_resizeable = TRUE;
|
||||||
|
else
|
||||||
|
clutter_stage_set_user_resizable (stage, TRUE);
|
||||||
|
|
||||||
|
send_wmspec_change_state(backend_x11,
|
||||||
|
stage_x11->xwin,
|
||||||
|
backend_x11->atom_WM_STATE_FULLSCREEN,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (stage_x11->xwin != None)
|
||||||
|
{
|
||||||
|
if (!CLUTTER_ACTOR_IS_MAPPED(CLUTTER_ACTOR (stage_x11)))
|
||||||
|
{
|
||||||
|
/* FIXME: This wont work if we support more states */
|
||||||
|
XDeleteProperty (stage_x11->xdpy,
|
||||||
|
stage_x11->xwin,
|
||||||
|
backend_x11->atom_WM_STATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clutter_stage_set_user_resizable (stage, TRUE);
|
||||||
|
|
||||||
|
send_wmspec_change_state(backend_x11,
|
||||||
|
stage_x11->xwin,
|
||||||
|
backend_x11->atom_WM_STATE_FULLSCREEN,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
/* reset the windows state - this isn't fun - see above */
|
||||||
|
if (!was_resizeable)
|
||||||
|
clutter_stage_set_user_resizable (stage, FALSE);
|
||||||
|
|
||||||
|
was_resizeable = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_set_cursor_visible (ClutterStage *stage,
|
||||||
|
gboolean show_cursor)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
|
|
||||||
|
if (stage_x11->xwin == None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "setting cursor state ('%s') over stage window (%u)",
|
||||||
|
show_cursor ? "visible" : "invisible",
|
||||||
|
(unsigned int) stage_x11->xwin);
|
||||||
|
|
||||||
|
if (show_cursor)
|
||||||
|
{
|
||||||
|
#if 0 /* HAVE_XFIXES - borked on fiesty at least so disabled until further
|
||||||
|
* investigation.
|
||||||
|
*/
|
||||||
|
XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||||
|
#else
|
||||||
|
XUndefineCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||||
|
#endif /* HAVE_XFIXES */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if 0 /* HAVE_XFIXES - borked */
|
||||||
|
XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||||
|
#else
|
||||||
|
XColor col;
|
||||||
|
Pixmap pix;
|
||||||
|
Cursor curs;
|
||||||
|
|
||||||
|
pix = XCreatePixmap (stage_x11->xdpy, stage_x11->xwin, 1, 1, 1);
|
||||||
|
memset (&col, 0, sizeof (col));
|
||||||
|
curs = XCreatePixmapCursor (stage_x11->xdpy,
|
||||||
|
pix, pix,
|
||||||
|
&col, &col,
|
||||||
|
1, 1);
|
||||||
|
XFreePixmap (stage_x11->xdpy, pix);
|
||||||
|
XDefineCursor (stage_x11->xdpy, stage_x11->xwin, curs);
|
||||||
|
#endif /* HAVE_XFIXES */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_set_title (ClutterStage *stage,
|
||||||
|
const gchar *title)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
|
Atom atom_NET_WM_NAME, atom_UTF8_STRING;
|
||||||
|
|
||||||
|
if (stage_x11->xwin == None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* FIXME: pre create these to avoid too many round trips */
|
||||||
|
atom_NET_WM_NAME = XInternAtom (stage_x11->xdpy, "_NET_WM_NAME", False);
|
||||||
|
atom_UTF8_STRING = XInternAtom (stage_x11->xdpy, "UTF8_STRING", False);
|
||||||
|
|
||||||
|
if (title == NULL)
|
||||||
|
{
|
||||||
|
XDeleteProperty (stage_x11->xdpy,
|
||||||
|
stage_x11->xwin,
|
||||||
|
atom_NET_WM_NAME);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XChangeProperty (stage_x11->xdpy,
|
||||||
|
stage_x11->xwin,
|
||||||
|
atom_NET_WM_NAME,
|
||||||
|
atom_UTF8_STRING,
|
||||||
|
8,
|
||||||
|
PropModeReplace,
|
||||||
|
(unsigned char*)title,
|
||||||
|
(int)strlen(title));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_set_user_resize (ClutterStage *stage,
|
||||||
|
gboolean value)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
|
|
||||||
|
clutter_stage_x11_fix_window_size (stage_x11);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_set_offscreen (ClutterStage *stage,
|
||||||
|
gboolean offscreen)
|
||||||
|
{
|
||||||
|
/* Do nothing ? */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||||
|
|
||||||
|
if (stage_x11->xwin)
|
||||||
|
clutter_actor_unrealize (CLUTTER_ACTOR (stage_x11));
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_stage_x11_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_class_init (ClutterStageX11Class *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_x11_dispose;
|
||||||
|
|
||||||
|
actor_class->show = clutter_stage_x11_show;
|
||||||
|
actor_class->hide = clutter_stage_x11_hide;
|
||||||
|
actor_class->request_coords = clutter_stage_x11_request_coords;
|
||||||
|
actor_class->query_coords = clutter_stage_x11_query_coords;
|
||||||
|
|
||||||
|
stage_class->set_fullscreen = clutter_stage_x11_set_fullscreen;
|
||||||
|
stage_class->set_cursor_visible = clutter_stage_x11_set_cursor_visible;
|
||||||
|
stage_class->set_offscreen = clutter_stage_x11_set_offscreen;
|
||||||
|
stage_class->set_title = clutter_stage_x11_set_title;
|
||||||
|
stage_class->set_user_resize = clutter_stage_x11_set_user_resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_x11_init (ClutterStageX11 *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_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_get_stage_window:
|
||||||
|
* @stage: a #ClutterStage
|
||||||
|
*
|
||||||
|
* Gets the stages X Window.
|
||||||
|
*
|
||||||
|
* Return value: An XID for the stage window.
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
Window
|
||||||
|
clutter_x11_get_stage_window (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_STAGE_X11 (stage), None);
|
||||||
|
|
||||||
|
return CLUTTER_STAGE_X11 (stage)->xwin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_get_stage_visual:
|
||||||
|
* @stage: a #ClutterStage
|
||||||
|
*
|
||||||
|
* Returns the stage XVisualInfo
|
||||||
|
*
|
||||||
|
* Return value: The XVisualInfo for the stage.
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
XVisualInfo *
|
||||||
|
clutter_x11_get_stage_visual (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_STAGE_X11 (stage), NULL);
|
||||||
|
|
||||||
|
return CLUTTER_STAGE_X11 (stage)->xvisinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_set_stage_foreign:
|
||||||
|
* @stage: a #ClutterStage
|
||||||
|
* @xwindow: an existing X Window id
|
||||||
|
*
|
||||||
|
* Target the #ClutterStage to use an existing external X Window
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if foreign window is valid
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
clutter_x11_set_stage_foreign (ClutterStage *stage,
|
||||||
|
Window xwindow)
|
||||||
|
{
|
||||||
|
ClutterStageX11 *stage_x11;
|
||||||
|
ClutterActor *actor;
|
||||||
|
gint x, y;
|
||||||
|
guint width, height, border, depth;
|
||||||
|
Window root_return;
|
||||||
|
Status status;
|
||||||
|
ClutterGeometry geom;
|
||||||
|
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_STAGE_X11 (stage), FALSE);
|
||||||
|
g_return_val_if_fail (xwindow != None, FALSE);
|
||||||
|
|
||||||
|
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||||
|
actor = CLUTTER_ACTOR (stage);
|
||||||
|
|
||||||
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
|
status = XGetGeometry (stage_x11->xdpy,
|
||||||
|
xwindow,
|
||||||
|
&root_return,
|
||||||
|
&x, &y,
|
||||||
|
&width, &height,
|
||||||
|
&border,
|
||||||
|
&depth);
|
||||||
|
|
||||||
|
if (clutter_x11_untrap_x_errors () ||
|
||||||
|
!status ||
|
||||||
|
width == 0 || height == 0 ||
|
||||||
|
depth != stage_x11->xvisinfo->depth)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_actor_unrealize (actor);
|
||||||
|
|
||||||
|
stage_x11->xwin = xwindow;
|
||||||
|
stage_x11->is_foreign_xwin = TRUE;
|
||||||
|
|
||||||
|
geom.x = x;
|
||||||
|
geom.y = y;
|
||||||
|
geom.width = stage_x11->xwin_width = width;
|
||||||
|
geom.height = stage_x11->xwin_height = height;
|
||||||
|
|
||||||
|
clutter_actor_set_geometry (actor, &geom);
|
||||||
|
clutter_actor_realize (actor);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
80
clutter/x11/clutter-stage-x11.h
Normal file
80
clutter/x11/clutter-stage-x11.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/* Clutter.
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Copyright (C) 2006-2007 OpenedHand
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_STAGE_X11_H__
|
||||||
|
#define __CLUTTER_STAGE_X11_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-stage.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#include "clutter-backend-x11.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_STAGE_X11 (clutter_stage_x11_get_type ())
|
||||||
|
#define CLUTTER_STAGE_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_X11, ClutterStageX11))
|
||||||
|
#define CLUTTER_IS_STAGE_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_X11))
|
||||||
|
#define CLUTTER_STAGE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_X11, ClutterStageX11Class))
|
||||||
|
#define CLUTTER_IS_STAGE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_X11))
|
||||||
|
#define CLUTTER_STAGE_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_X11, ClutterStageX11Class))
|
||||||
|
|
||||||
|
typedef struct _ClutterStageX11 ClutterStageX11;
|
||||||
|
typedef struct _ClutterStageX11Class ClutterStageX11Class;
|
||||||
|
|
||||||
|
struct _ClutterStageX11
|
||||||
|
{
|
||||||
|
ClutterStage parent_instance;
|
||||||
|
|
||||||
|
int is_foreign_xwin :1;
|
||||||
|
|
||||||
|
Display *xdpy;
|
||||||
|
Window xwin_root;
|
||||||
|
int xscreen;
|
||||||
|
XVisualInfo *xvisinfo;
|
||||||
|
Window xwin;
|
||||||
|
gint xwin_width;
|
||||||
|
gint xwin_height; /* FIXME target_width / height */
|
||||||
|
Pixmap xpixmap;
|
||||||
|
|
||||||
|
ClutterBackendX11 *backend;
|
||||||
|
ClutterStageState state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterStageX11Class
|
||||||
|
{
|
||||||
|
ClutterStageClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType clutter_stage_x11_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
/* Private to subclasses */
|
||||||
|
void
|
||||||
|
clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_stage_x11_set_wm_protocols (Display *xdisplay,
|
||||||
|
Window xwindow);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_STAGE_H__ */
|
80
clutter/x11/clutter-x11.h
Normal file
80
clutter/x11/clutter-x11.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
*
|
||||||
|
* 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-x11
|
||||||
|
* @short_description: X11 specific API
|
||||||
|
*
|
||||||
|
* The X11 backend for Clutter provides some specific API, allowing
|
||||||
|
* integration with the Xlibs API for embedding and manipulating the
|
||||||
|
* stage window, or for trapping X errors.
|
||||||
|
*
|
||||||
|
* The ClutterX11 API is available since Clutter 0.6
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_X11_H__
|
||||||
|
#define __CLUTTER_X11_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <clutter/clutter-stage.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CLUTTER_X11_FILTER_CONTINUE, /* Event not handled, continue processesing */
|
||||||
|
CLUTTER_X11_FILTER_TRANSLATE, /* Native event translated into a Clutter
|
||||||
|
event and stored in the "event" structure
|
||||||
|
that was passed in */
|
||||||
|
CLUTTER_X11_FILTER_REMOVE /* Terminate processing, removing event */
|
||||||
|
} ClutterX11FilterReturn;
|
||||||
|
|
||||||
|
typedef ClutterX11FilterReturn (*ClutterX11FilterFunc) (XEvent *xev,
|
||||||
|
ClutterEvent *cev,
|
||||||
|
gpointer *data);
|
||||||
|
|
||||||
|
void clutter_x11_trap_x_errors (void);
|
||||||
|
gint clutter_x11_untrap_x_errors (void);
|
||||||
|
|
||||||
|
Display *clutter_x11_get_default_display (void);
|
||||||
|
int clutter_x11_get_default_screen (void);
|
||||||
|
Window clutter_x11_get_root_window (void);
|
||||||
|
|
||||||
|
Window clutter_x11_get_stage_window (ClutterStage *stage);
|
||||||
|
XVisualInfo *clutter_x11_get_stage_visual (ClutterStage *stage);
|
||||||
|
|
||||||
|
gboolean clutter_x11_set_stage_foreign (ClutterStage *stage,
|
||||||
|
Window xwindow);
|
||||||
|
|
||||||
|
void clutter_x11_add_filter (ClutterX11FilterFunc func, gpointer data);
|
||||||
|
|
||||||
|
void clutter_x11_remove_filter (ClutterX11FilterFunc func,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_X11_H__ */
|
62
configure.ac
62
configure.ac
@ -87,6 +87,8 @@ fi
|
|||||||
|
|
||||||
AC_SUBST(CLUTTER_NO_FPU)
|
AC_SUBST(CLUTTER_NO_FPU)
|
||||||
|
|
||||||
|
backendextra=
|
||||||
|
backendextralib=
|
||||||
clutterbackend=glx
|
clutterbackend=glx
|
||||||
AC_ARG_WITH([flavour],
|
AC_ARG_WITH([flavour],
|
||||||
AC_HELP_STRING([--with-flavour=@<:@glx/eglx/eglnative/sdl@:>@],
|
AC_HELP_STRING([--with-flavour=@<:@glx/eglx/eglnative/sdl@:>@],
|
||||||
@ -151,35 +153,6 @@ case $clutterbackend in
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
sdles)
|
|
||||||
#
|
|
||||||
# Temp Hack for building with dgles (runs atop SDL)
|
|
||||||
#
|
|
||||||
clutterbackend=sdl
|
|
||||||
CLUTTER_FLAVOUR="sdl"
|
|
||||||
AC_DEFINE([HAVE_CLUTTER_SDL], 1, [Have the SDL backend])
|
|
||||||
|
|
||||||
CLUTTER_COGL="gles"
|
|
||||||
AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL for rendering])
|
|
||||||
|
|
||||||
AC_PATH_PROG(SDL_CONFIG, sdl-config)
|
|
||||||
if test "x$SDL_CONFIG" = "x"; then
|
|
||||||
AC_MSG_ERROR([[No sdl-config binary found in path and SDL flavour requested.]])
|
|
||||||
else
|
|
||||||
SDL_CFLAGS=`$SDL_CONFIG --cflags`
|
|
||||||
SDL_LIBS=`$SDL_CONFIG --libs`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# FIXME: Obviously we need some real detection here
|
|
||||||
SDL_CFLAGS="-I/usr/local/include $SDL_CFLAGS"
|
|
||||||
SDL_LIBS="-L/usr/local/lib -lGLES_CM $SDL_LIBS"
|
|
||||||
|
|
||||||
AC_MSG_WARN([])
|
|
||||||
AC_MSG_WARN([The SDL/Open GL ES Backend is purely for experimental])
|
|
||||||
AC_MSG_WARN([and devlopment purposes. Do not use in production code!!])
|
|
||||||
AC_MSG_WARN([])
|
|
||||||
;;
|
|
||||||
|
|
||||||
glx)
|
glx)
|
||||||
|
|
||||||
clutter_gl_header="GL/gl.h"
|
clutter_gl_header="GL/gl.h"
|
||||||
@ -205,11 +178,13 @@ case $clutterbackend in
|
|||||||
|
|
||||||
GLX_LIBS="$X11_LIBS -lGL"
|
GLX_LIBS="$X11_LIBS -lGL"
|
||||||
GLX_CFLAGS="$X11_CFLAGS"
|
GLX_CFLAGS="$X11_CFLAGS"
|
||||||
|
backendextra=x11
|
||||||
|
backendextralib="x11/libclutter-x11.la"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
eglx)
|
eglx)
|
||||||
|
|
||||||
$clutter_gl_header="GLES/gl.h"
|
clutter_gl_header="GLES/gl.h"
|
||||||
CLUTTER_FLAVOUR="eglx"
|
CLUTTER_FLAVOUR="eglx"
|
||||||
AC_DEFINE([HAVE_CLUTTER_EGL], 1, [Have the EGL backend])
|
AC_DEFINE([HAVE_CLUTTER_EGL], 1, [Have the EGL backend])
|
||||||
|
|
||||||
@ -217,15 +192,11 @@ case $clutterbackend in
|
|||||||
CLUTTER_COGL="gles"
|
CLUTTER_COGL="gles"
|
||||||
AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL/ES for rendering])
|
AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL/ES for rendering])
|
||||||
|
|
||||||
# try for libvincent first (though its not so good)
|
|
||||||
PKG_CHECK_MODULES(EGL, libvincent, HAVE_OGLES=yes, HAVE_OGLES=no)
|
|
||||||
if test "x$HAVE_OGLES" = "xno"; then
|
|
||||||
AC_CHECK_HEADERS([GLES/egl.h $clutter_gl_header],,
|
AC_CHECK_HEADERS([GLES/egl.h $clutter_gl_header],,
|
||||||
[AC_MSG_ERROR([Unable to locate required GLES headers])])
|
[AC_MSG_ERROR([Unable to locate required GLES headers])])
|
||||||
|
|
||||||
# No libvincent so start checking for upper/lower case libgles_em
|
# check for upper/lower case libgles_em
|
||||||
# The powervr sdk uses lower case.
|
# The powervr sdk uses lower case.
|
||||||
|
|
||||||
AC_CHECK_LIB(GLES_CM, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no)
|
AC_CHECK_LIB(GLES_CM, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no)
|
||||||
if test "x$HAVE_LIBGLES" = "xno"; then
|
if test "x$HAVE_LIBGLES" = "xno"; then
|
||||||
|
|
||||||
@ -233,14 +204,21 @@ case $clutterbackend in
|
|||||||
if test "x$HAVE_LIBGLES" = "xno"; then
|
if test "x$HAVE_LIBGLES" = "xno"; then
|
||||||
AC_MSG_ERROR([GLES library not found and egl backend requested.]);
|
AC_MSG_ERROR([GLES library not found and egl backend requested.]);
|
||||||
fi
|
fi
|
||||||
EGL_LIBS="-lgles_cm"
|
EGL_LIBS="gles_cm"
|
||||||
|
|
||||||
else
|
else
|
||||||
EGL_LIBS="-lGLES_CM"
|
EGL_LIBS="GLES_CM"
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
EGL_LIBS="$EGL_LIBS $X11_LIBS"
|
# glColor4ub needed for more precise picking, seems presence is a
|
||||||
|
# bit random in egl 1.1 (in SDK header, but not lib)
|
||||||
|
AC_CHECK_LIB($EGL_LIBS, glColor4ub, COLOR4UB=1, COLOR4UB=0)
|
||||||
|
AC_DEFINE([HAVE_GLES_COLOR4UB], $COLOR4UB, [Have GL/ES glColor4ub])
|
||||||
|
|
||||||
|
EGL_LIBS="-l$EGL_LIBS $X11_LIBS"
|
||||||
EGL_CFLAGS="$EGL_CFLAGS $X11_CFLAGS"
|
EGL_CFLAGS="$EGL_CFLAGS $X11_CFLAGS"
|
||||||
|
backendextra=x11
|
||||||
|
backendextralib="x11/libclutter-x11.la"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
eglnative)
|
eglnative)
|
||||||
@ -264,6 +242,9 @@ case $clutterbackend in
|
|||||||
AC_MSG_ERROR([libGLES_CM not found and egl backend requested.]);
|
AC_MSG_ERROR([libGLES_CM not found and egl backend requested.]);
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_CHECK_LIB(GLES_CM, glColor4ub, COLOR4UB=1, COLOR4UB=0)
|
||||||
|
AC_DEFINE([HAVE_GLES_COLOR4UB], COLOR4UB, [Have GL/ES glColor4ub])
|
||||||
|
|
||||||
PKG_CHECK_MODULES(TSLIB, tslib-1.0, [have_tslib=yes], [have_tslib=no])
|
PKG_CHECK_MODULES(TSLIB, tslib-1.0, [have_tslib=yes], [have_tslib=no])
|
||||||
if test x$have_tslib = xyes; then
|
if test x$have_tslib = xyes; then
|
||||||
AC_DEFINE([HAVE_TSLIB], 1, [Have tslib for touchscreen handling])
|
AC_DEFINE([HAVE_TSLIB], 1, [Have tslib for touchscreen handling])
|
||||||
@ -295,6 +276,8 @@ esac
|
|||||||
CLUTTER_GL_HEADER=$clutter_gl_header
|
CLUTTER_GL_HEADER=$clutter_gl_header
|
||||||
|
|
||||||
AC_SUBST([clutterbackend])
|
AC_SUBST([clutterbackend])
|
||||||
|
AC_SUBST([backendextra])
|
||||||
|
AC_SUBST([backendextralib])
|
||||||
AC_SUBST(CLUTTER_FLAVOUR)
|
AC_SUBST(CLUTTER_FLAVOUR)
|
||||||
AC_SUBST(CLUTTER_COGL)
|
AC_SUBST(CLUTTER_COGL)
|
||||||
AC_SUBST(CLUTTER_GL_HEADER)
|
AC_SUBST(CLUTTER_GL_HEADER)
|
||||||
@ -392,6 +375,7 @@ AC_CONFIG_FILES([
|
|||||||
Makefile
|
Makefile
|
||||||
clutter/Makefile
|
clutter/Makefile
|
||||||
clutter/clutter-version.h
|
clutter/clutter-version.h
|
||||||
|
clutter/x11/Makefile
|
||||||
clutter/glx/Makefile
|
clutter/glx/Makefile
|
||||||
clutter/eglx/Makefile
|
clutter/eglx/Makefile
|
||||||
clutter/eglnative/Makefile
|
clutter/eglnative/Makefile
|
||||||
|
Loading…
Reference in New Issue
Block a user