2006-06-15 Matthew Allum <mallum@openedhand.com>
authorMatthew Allum <mallum@openedhand.com>
Thu, 15 Jun 2006 22:04:19 +0000 (22:04 +0000)
committerMatthew Allum <mallum@openedhand.com>
Thu, 15 Jun 2006 22:04:19 +0000 (22:04 +0000)
        * 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
clutter/clutter-actor.h
clutter/clutter-stage.c
clutter/clutter-stage.h
clutter/clutter-util.c
clutter/clutter-util.h
examples/super-oh.c

index 34a8e17..b91c6a5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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:
index d7957fe..6fdbb09 100644 (file)
@@ -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,
index 350253c..f39296a 100644 (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,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
@@ -793,6 +794,61 @@ clutter_stage_get_xwindow (ClutterStage *stage)
 }
 
 /**
+ * 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
  *
index f7a3249..b6d38a4 100644 (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);
 
index 2b9deb4..35d3fc8 100644 (file)
 #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)
 {
index 9a4d61e..c34bde3 100644 (file)
 
 G_BEGIN_DECLS
 
+void
+clutter_util_trap_x_errors(void);
+
+int
+clutter_util_untrap_x_errors(void);
+
 int 
 clutter_util_next_p2 (int a);
 
index daf2d38..bc78336 100644 (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 */