From 13ce0e3709c5acd08360e7acf54649deeda87075 Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Thu, 15 Jun 2006 22:04:19 +0000 Subject: [PATCH] 2006-06-15 Matthew Allum * 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. --- ChangeLog | 12 +++++++ clutter/clutter-actor.h | 2 +- clutter/clutter-stage.c | 72 ++++++++++++++++++++++++++++++++++++----- clutter/clutter-stage.h | 3 ++ clutter/clutter-util.c | 25 ++++++++++++++ clutter/clutter-util.h | 6 ++++ examples/super-oh.c | 59 +++++++++++++++++++++++++-------- 7 files changed, 157 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 34a8e17c7..b91c6a51d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2006-06-15 Matthew Allum + + * 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 * configure.ac: diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index d7957feb6..6fdbb099b 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -145,7 +145,7 @@ clutter_actor_queue_redraw (ClutterActor *self); void clutter_actor_request_coords (ClutterActor *self, - ClutterActorBox *box); + ClutterActorBox *box); void clutter_actor_allocate_coords (ClutterActor *self, diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 350253ca5..f39296ade 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -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,14 +391,14 @@ clutter_stage_realize (ClutterActor *actor) return; } - priv->xwin = XCreateSimpleWindow(clutter_xdisplay(), - clutter_root_xwindow(), - 0, 0, - priv->xwin_width, priv->xwin_height, - 0, 0, - WhitePixel(clutter_xdisplay(), - clutter_xscreen())); - + if (priv->xwin == None) + priv->xwin = XCreateSimpleWindow(clutter_xdisplay(), + clutter_root_xwindow(), + 0, 0, + priv->xwin_width, priv->xwin_height, + 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 diff --git a/clutter/clutter-stage.h b/clutter/clutter-stage.h index f7a324961..b6d38a482 100644 --- a/clutter/clutter-stage.h +++ b/clutter/clutter-stage.h @@ -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); diff --git a/clutter/clutter-util.c b/clutter/clutter-util.c index 2b9deb409..35d3fc87e 100644 --- a/clutter/clutter-util.c +++ b/clutter/clutter-util.c @@ -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) { diff --git a/clutter/clutter-util.h b/clutter/clutter-util.h index 9a4d61e88..c34bde359 100644 --- a/clutter/clutter-util.h +++ b/clutter/clutter-util.h @@ -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); diff --git a/examples/super-oh.c b/examples/super-oh.c index daf2d38fb..bc78336c8 100644 --- a/examples/super-oh.c +++ b/examples/super-oh.c @@ -1,11 +1,11 @@ #include #include +#include +#include #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 */