+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:
void
clutter_actor_request_coords (ClutterActor *self,
- ClutterActorBox *box);
+ ClutterActorBox *box);
void
clutter_actor_allocate_coords (ClutterActor *self,
#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 */
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
}
/**
+ * 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
*
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);
#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)
{
G_BEGIN_DECLS
+void
+clutter_util_trap_x_errors(void);
+
+int
+clutter_util_untrap_x_errors(void);
+
int
clutter_util_next_p2 (int a);
#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
{
} 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,
#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);
/* 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 */
/*
clutter_actor_rotate_x (CLUTTER_ACTOR(oh->group),
75.0,
- WINHEIGHT/2, 0);
+ CLUTTER_STAGE_HEIGHT()/2, 0);
*/
}
+
int
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);
#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
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);
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 */