2006-06-15 Matthew Allum <mallum@openedhand.com>

* clutter/clutter-stage.c:
        * clutter/clutter-stage.h:
        Add clutter_stage_set_xwindow_foreign() call
        * clutter/clutter-util.c:
        * clutter/clutter-util.h:
        Add some X error traps
        * examples/super-oh.c:
        Toy with us of new clutter_stage_set_xwindow_foreign() for
        optional screensaver functionality.
This commit is contained in:
Matthew Allum 2006-06-15 22:04:19 +00:00
parent 7639872f5f
commit 13ce0e3709
7 changed files with 157 additions and 22 deletions

View File

@ -1,3 +1,15 @@
2006-06-15 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-stage.c:
* clutter/clutter-stage.h:
Add clutter_stage_set_xwindow_foreign() call
* clutter/clutter-util.c:
* clutter/clutter-util.h:
Add some X error traps
* examples/super-oh.c:
Toy with us of new clutter_stage_set_xwindow_foreign() for
optional screensaver functionality.
2006-06-14 Matthew Allum <mallum@openedhand.com>
* configure.ac:

View File

@ -28,6 +28,7 @@
#include "clutter-stage.h"
#include "clutter-main.h"
#include "clutter-color.h"
#include "clutter-util.h"
#include "clutter-marshal.h"
#include "clutter-enum-types.h"
#include "clutter-private.h" /* for DBG */
@ -390,6 +391,7 @@ clutter_stage_realize (ClutterActor *actor)
return;
}
if (priv->xwin == None)
priv->xwin = XCreateSimpleWindow(clutter_xdisplay(),
clutter_root_xwindow(),
0, 0,
@ -397,7 +399,6 @@ clutter_stage_realize (ClutterActor *actor)
0, 0,
WhitePixel(clutter_xdisplay(),
clutter_xscreen()));
XSelectInput(clutter_xdisplay(),
priv->xwin,
StructureNotifyMask
@ -792,6 +793,61 @@ clutter_stage_get_xwindow (ClutterStage *stage)
return stage->priv->xwin;
}
/**
* clutter_stage_set_xwindow_foreign
* @stage: A #ClutterStage
* @xid: A preexisting X Window ID
*
* Target the #ClutterStage to use an existing externtal X Window.
*
* Return Value: TRUE if foreign window valid, FALSE otherwise
**/
gboolean
clutter_stage_set_xwindow_foreign (ClutterStage *stage,
Window xid)
{
/* For screensavers via XSCREENSAVER_WINDOW env var.
* Also for toolkit binding.
*/
gint x,y;
guint width, height, border, depth;
Window root_return;
Status status;
ClutterGeometry geom;
clutter_util_trap_x_errors();
status = XGetGeometry (clutter_xdisplay(),
xid,
&root_return,
&x,
&y,
&width,
&height,
&border,
&depth);
if (clutter_util_untrap_x_errors() || !status
|| width == 0 || height == 0 || depth != stage->priv->xvisinfo->depth)
return FALSE;
clutter_actor_unrealize (CLUTTER_ACTOR(stage));
stage->priv->xwin = xid;
geom.x = x;
geom.y = y;
geom.width = stage->priv->xwin_width = width;
geom.height = stage->priv->xwin_height = height;
clutter_actor_set_geometry (CLUTTER_ACTOR(stage), &geom);
clutter_actor_realize (CLUTTER_ACTOR(stage));
return TRUE;
}
/**
* clutter_stage_get_xvisual
* @stage: A #ClutterStage

View File

@ -112,6 +112,9 @@ ClutterActor *clutter_stage_get_default (void);
Window clutter_stage_get_xwindow (ClutterStage *stage);
gboolean clutter_stage_set_xwindow_foreign (ClutterStage *stage,
Window xid);
void clutter_stage_set_color (ClutterStage *stage,
const ClutterColor *color);

View File

@ -26,6 +26,31 @@
#include "clutter-util.h"
#include "clutter-main.h"
static int TrappedErrorCode = 0;
static int (*old_error_handler) (Display *, XErrorEvent *);
static int
error_handler(Display *xdpy,
XErrorEvent *error)
{
TrappedErrorCode = error->error_code;
return 0;
}
void
clutter_util_trap_x_errors(void)
{
TrappedErrorCode = 0;
old_error_handler = XSetErrorHandler(error_handler);
}
int
clutter_util_untrap_x_errors(void)
{
XSetErrorHandler(old_error_handler);
return TrappedErrorCode;
}
int
clutter_util_next_p2 (int a)
{

View File

@ -30,6 +30,12 @@
G_BEGIN_DECLS
void
clutter_util_trap_x_errors(void);
int
clutter_util_untrap_x_errors(void);
int
clutter_util_next_p2 (int a);

View File

@ -1,11 +1,11 @@
#include <clutter/clutter.h>
#include <math.h>
#include <errno.h>
#include <stdlib.h>
#define TRAILS 0
#define NHANDS 6
#define WINWIDTH 800
#define WINHEIGHT 800
#define RADIUS 250
#define RADIUS ((CLUTTER_STAGE_WIDTH()+CLUTTER_STAGE_HEIGHT())/6)
typedef struct SuperOH
{
@ -15,6 +15,33 @@ typedef struct SuperOH
} SuperOH;
void
screensaver_setup (void)
{
Window remote_xwindow;
const char *preview_xid;
gboolean foreign_success = FALSE;
preview_xid = g_getenv ("XSCREENSAVER_WINDOW");
if (preview_xid != NULL)
{
char *end;
remote_xwindow = (Window) strtoul (preview_xid, &end, 0);
if ((remote_xwindow != 0) && (end != NULL) &&
((*end == ' ') || (*end == '\0')) &&
((remote_xwindow < G_MAXULONG) || (errno != ERANGE)))
{
foreign_success = clutter_stage_set_xwindow_foreign
(CLUTTER_STAGE(clutter_stage_get_default()), remote_xwindow);
}
}
if (!foreign_success)
clutter_actor_set_size (clutter_stage_get_default(), 800, 600);
}
/* input handler */
void
input_cb (ClutterStage *stage,
@ -64,8 +91,8 @@ frame_cb (ClutterTimeline *timeline,
#if TRAILS
oh->bgpixb = clutter_stage_snapshot (CLUTTER_STAGE (stage),
0, 0,
WINWIDTH,
WINHEIGHT);
CLUTTER_STAGE_WIDTH(),
CLUTTER_STAGE_HEIGHT();
clutter_texture_set_pixbuf (CLUTTER_TEXTURE (oh->bgtex), oh->bgpixb);
g_object_unref (G_OBJECT (oh->bgpixb));
g_object_unref (stage);
@ -74,8 +101,8 @@ frame_cb (ClutterTimeline *timeline,
/* Rotate everything clockwise about stage center*/
clutter_actor_rotate_z (CLUTTER_ACTOR(oh->group),
frame_num,
WINWIDTH/2,
WINHEIGHT/2);
CLUTTER_STAGE_WIDTH()/2,
CLUTTER_STAGE_HEIGHT()/2);
for (i = 0; i < NHANDS; i++)
{
/* rotate each hand around there centers */
@ -88,10 +115,11 @@ frame_cb (ClutterTimeline *timeline,
/*
clutter_actor_rotate_x (CLUTTER_ACTOR(oh->group),
75.0,
WINHEIGHT/2, 0);
CLUTTER_STAGE_HEIGHT()/2, 0);
*/
}
int
main (int argc, char *argv[])
{
@ -112,10 +140,12 @@ main (int argc, char *argv[])
g_error("pixbuf load failed");
/* Set our stage (window) size */
clutter_actor_set_size (stage, WINWIDTH, WINHEIGHT);
// clutter_actor_set_size (stage, WINWIDTH, WINHEIGHT);
/* and its background color */
screensaver_setup ();
clutter_stage_set_color (CLUTTER_STAGE (stage),
&stage_color);
@ -123,7 +153,8 @@ main (int argc, char *argv[])
#if TRAILS
oh->bgtex = clutter_texture_new();
clutter_actor_set_size (oh->bgtex, WINWIDTH, WINHEIGHT);
clutter_actor_set_size (oh->bgtex,
CLUTTER_STAGE_WIDTH(), CLUTTER_STAGE_HEIGHT());
clutter_actor_set_opacity (oh->bgtex, 0x99);
clutter_group_add (CLUTTER_GROUP (stage), oh->bgtex);
#endif
@ -145,8 +176,10 @@ main (int argc, char *argv[])
w = clutter_actor_get_width (oh->hand[0]);
h = clutter_actor_get_height (oh->hand[0]);
x = WINWIDTH/2 + RADIUS * cos (i * M_PI / (NHANDS/2)) - w/2;
y = WINHEIGHT/2 + RADIUS * sin (i * M_PI / (NHANDS/2)) - h/2;
x = CLUTTER_STAGE_WIDTH() / 2
+ RADIUS * cos (i * M_PI / (NHANDS/2)) - w/2;
y = CLUTTER_STAGE_HEIGHT() / 2
+ RADIUS * sin (i * M_PI / (NHANDS/2)) - h/2;
clutter_actor_set_position (oh->hand[i], x, y);
@ -169,7 +202,7 @@ main (int argc, char *argv[])
oh);
/* Create a timeline to manage animation */
timeline = clutter_timeline_new (360, 60); /* num frames, fps */
timeline = clutter_timeline_new (360, 90); /* num frames, fps */
g_object_set(timeline, "loop", TRUE, 0); /* have it loop */
/* fire a callback for frame change */