2007-08-24 Matthew Allum <mallum@openedhand.com>
authorMatthew Allum <mallum@openedhand.com>
Fri, 24 Aug 2007 15:12:52 +0000 (15:12 +0000)
committerMatthew Allum <mallum@openedhand.com>
Fri, 24 Aug 2007 15:12:52 +0000 (15:12 +0000)
        * clutter/clutter-actor.c:
        * clutter/clutter-event.h:
        * clutter/clutter-main.c:
        * clutter/clutter-stage.c:
        * clutter/clutter-stage.h:
        * clutter/glx/clutter-backend-glx.c:
        * clutter/glx/clutter-backend-glx.h:
        * clutter/glx/clutter-event-glx.c:
        * clutter/glx/clutter-stage-glx.c:
        * clutter/glx/clutter-stage-glx.h:
        Add initial support for stage state events.
        Fix fullscreening for an already mapped stage.

        * tests/test-events.c:
        Print out info from the above. Blue button now toggles
        fullscreen.

        * clutter/clutter-effect.c:
        * clutter/clutter-effect.h:
        Add a setting for templates to ref or clone underlying
        timelines. (As to improve sync issues like those in foofone)

        * tests/test-timeline.c:
        Also add completed signals.

        * clutter/cogl/gles/cogl.c: (cogl_texture_image_2d):
        * configure.ac:
        Forward port from stable branch. RGB Image fixes gles
        and check for lower case libgles_cm.

17 files changed:
ChangeLog
clutter/clutter-actor.c
clutter/clutter-effect.c
clutter/clutter-effect.h
clutter/clutter-event.h
clutter/clutter-main.c
clutter/clutter-stage.c
clutter/clutter-stage.h
clutter/cogl/gles/cogl.c
clutter/glx/clutter-backend-glx.c
clutter/glx/clutter-backend-glx.h
clutter/glx/clutter-event-glx.c
clutter/glx/clutter-stage-glx.c
clutter/glx/clutter-stage-glx.h
configure.ac
tests/test-events.c
tests/test-timeline.c

index fd2ad18..68d758d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2007-08-24  Matthew Allum  <mallum@openedhand.com>
+
+       * clutter/clutter-actor.c:
+       * clutter/clutter-event.h:
+       * clutter/clutter-main.c:
+       * clutter/clutter-stage.c:
+       * clutter/clutter-stage.h:
+       * clutter/glx/clutter-backend-glx.c:
+       * clutter/glx/clutter-backend-glx.h:
+       * clutter/glx/clutter-event-glx.c:
+       * clutter/glx/clutter-stage-glx.c:
+       * clutter/glx/clutter-stage-glx.h:
+       Add initial support for stage state events.
+       Fix fullscreening for an already mapped stage. 
+
+       * tests/test-events.c:
+       Print out info from the above. Blue button now toggles 
+       fullscreen.
+
+       * clutter/clutter-effect.c:
+       * clutter/clutter-effect.h:
+       Add a setting for templates to ref or clone underlying 
+       timelines. (As to improve sync issues like those in foofone)
+
+       * tests/test-timeline.c:
+       Also add completed signals.     
+
+       * clutter/cogl/gles/cogl.c: (cogl_texture_image_2d):
+       * configure.ac:
+       Forward port from stable branch. RGB Image fixes gles
+       and check for lower case libgles_cm.
+
+
 2007-08-24  Tomas Frydrych  <tf@openedhand.com>
        
        * clutter/clutter-actor.c:
index e11c78a..5bddecc 100644 (file)
@@ -2861,15 +2861,10 @@ clutter_actor_event (ClutterActor *actor,
       signal_num = MOTION_EVENT;
       break;
     case CLUTTER_DELETE:
-      signal_num = -1;
-      break;
     case CLUTTER_DESTROY_NOTIFY:
-      signal_num = -1;
-      break;
     case CLUTTER_CLIENT_MESSAGE:
-      signal_num = -1;
-      break;
     default:
+      signal_num = -1;
       break;
     }
 
index 96f61d1..76e893d 100644 (file)
@@ -82,6 +82,7 @@ G_DEFINE_TYPE (ClutterEffectTemplate, clutter_effect_template, G_TYPE_OBJECT);
 struct _ClutterEffectTemplatePrivate
 {
   ClutterTimeline *timeline;
+  gboolean         do_clone;
 
   ClutterAlphaFunc alpha_func;
   gpointer alpha_data;
@@ -94,6 +95,7 @@ enum
 
   PROP_ALPHA_FUNC,
   PROP_TIMELINE,
+  PROP_DO_CLONE
 };
 
 static void
@@ -152,6 +154,9 @@ clutter_effect_template_set_property (GObject      *object,
     case PROP_TIMELINE:
       priv->timeline = g_value_get_object (value);
       g_object_ref(priv->timeline);
+    case PROP_DO_CLONE:
+      clutter_effect_template_set_timeline_clone (template, 
+                                                 g_value_get_boolean (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -179,6 +184,9 @@ clutter_effect_template_get_property (GObject    *object,
     case PROP_TIMELINE:
       g_value_set_object (value, priv->timeline);
       break;
+    case PROP_DO_CLONE:
+      g_value_set_boolean (value, priv->do_clone);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -228,12 +236,31 @@ clutter_effect_template_class_init (ClutterEffectTemplateClass *klass)
                                 CLUTTER_TYPE_TIMELINE,
                                 G_PARAM_CONSTRUCT_ONLY |
                                 CLUTTER_PARAM_READWRITE));
+
+  /**
+   * ClutterEffectTemplate:clone:
+   *
+   * Controls if effects should clone or reference the templated timeline
+   *
+   * Since: 0.6
+   */
+  g_object_class_install_property 
+           (object_class,
+           PROP_DO_CLONE,
+           g_param_spec_boolean ("clone",
+                                 "Clone",
+                                 "controls if effects should clone or reference the templated timeline",
+                                 TRUE,
+                                 G_PARAM_CONSTRUCT |
+                                 CLUTTER_PARAM_READWRITE));
+
 }
 
 static void
 clutter_effect_template_init (ClutterEffectTemplate *self)
 {
   self->priv = EFFECT_TEMPLATE_PRIVATE (self);
+  self->priv->do_clone = TRUE;
 }
 
 static void
@@ -258,6 +285,40 @@ clutter_effect_template_set_alpha_func (ClutterEffectTemplate *self,
 }
 
 /**
+ * clutter_effect_template_set_timeline_clone:
+ * @template_:  A #ClutterEffectTemplate
+ * @setting: A boolean indicating if effects should clone the timeline.
+ *
+ * Sets if effects using this template should make a copy of the 
+ * templates timeline (default) or reference the effects timeline.
+ * 
+ * Since: 0.6
+ */
+void
+clutter_effect_template_set_timeline_clone (ClutterEffectTemplate *template_,
+                                           gboolean               setting)
+{
+  template_->priv->do_clone = setting;
+}
+
+/**
+ * clutter_effect_template_get_timeline_clone:
+ * @template:  A #ClutterEffectTemplate
+ *
+ * 
+ *
+ * Return value: TRUE if the templates timeline is to be cloned.
+ *
+ * Since: 0.6
+ */
+gboolean
+clutter_effect_template_get_timeline_clone (ClutterEffectTemplate *template_)
+{
+  return template_->priv->do_clone;
+}
+
+
+/**
  * clutter_effect_template_new:
  * @timeline:  A #ClutterTimeline for the template (will be cloned)
  * @alpha_func: An alpha func to use for the template.
@@ -276,7 +337,7 @@ clutter_effect_template_set_alpha_func (ClutterEffectTemplate *self,
  *
  * Since: 0.4
  */
-ClutterEffectTemplate *
+ClutterEffectTemplate*
 clutter_effect_template_new (ClutterTimeline *timeline, 
                             ClutterAlphaFunc alpha_func)
 {
@@ -368,7 +429,15 @@ clutter_effect_closure_new (ClutterEffectTemplate *template,
 
   c->template = template;
   c->actor    = actor;
-  c->timeline = clutter_timeline_clone (priv->timeline);
+
+  if (clutter_effect_template_get_timeline_clone (template))
+    c->timeline = clutter_timeline_clone (priv->timeline);
+  else
+    {
+      c->timeline = priv->timeline;
+      g_object_ref (priv->timeline);
+    }
+      
   c->alpha    = clutter_alpha_new_full (c->timeline,
                                        priv->alpha_func,
                                        priv->alpha_data,
index dabd0b3..f77da4e 100644 (file)
@@ -101,6 +101,11 @@ ClutterEffectTemplate *clutter_effect_template_new_full (ClutterTimeline  *timel
                                                          gpointer          user_data,
                                                          GDestroyNotify    notify);
 
+void                   clutter_effect_template_set_timeline_clone (ClutterEffectTemplate *template_,
+                                                                  gboolean               setting);
+gboolean               clutter_effect_template_get_timeline_clone (ClutterEffectTemplate *template_);
+
+
 /*
  * Clutter effects
  */
index 3badad4..fcedc31 100644 (file)
@@ -83,8 +83,7 @@ typedef enum
   CLUTTER_STAGE_STATE_OFFSCREEN        = (1<<2),
   CLUTTER_STAGE_STATE_POINTER_ENTER    = (1<<3),
   CLUTTER_STAGE_STATE_POINTER_LEAVE    = (1<<4),
-  CLUTTER_STAGE_STATE_FOCUS_ACTIVATE   = (1<<5),
-  CLUTTER_STAGE_STATE_FOCUS_DEACTIVATE = (1<<6),
+  CLUTTER_STAGE_STATE_ACTIVATED        = (1<<5),
 } ClutterStageState;
 
 typedef union _ClutterEvent ClutterEvent;
index 3bddfab..6537e0e 100644 (file)
@@ -315,7 +315,8 @@ clutter_do_event (ClutterEvent *event)
       }
       break;
     case CLUTTER_STAGE_STATE:
-      /* FIXME: fullscreen / focus / mouse - forward to stage */
+      /* fullscreen / focus - forward to stage */
+      clutter_stage_event (CLUTTER_STAGE(stage), event);
       break;
     case CLUTTER_CLIENT_MESSAGE:
       break;
index 276c643..5aeca38 100644 (file)
@@ -82,9 +82,10 @@ enum
 
 enum
 {
-  STAGE_STATE_EVENT,
-  ACTIVATE_STAGE,
-  DEACTIVATE_STAGE,
+  FULLSCREEN,
+  UNFULLSCREEN,
+  ACTIVATE,
+  DEACTIVATE,
   LAST_SIGNAL
 };
 
@@ -295,6 +296,78 @@ clutter_stage_class_init (ClutterStageClass *klass)
                          "Stage Title",
                          NULL,
                          CLUTTER_PARAM_READWRITE));
+
+  /**
+   * ClutterStage::fullscreen
+   * @stage: the stage which was fullscreened
+   *
+   * The ::fullscreen signal is emitted when the stage is made fullscreen.
+   *
+   * Since: 0.6
+   */
+  stage_signals[FULLSCREEN] =
+    g_signal_new ("fullscreen",
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (ClutterStageClass, fullscreen),
+                 NULL, NULL,
+                 clutter_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+
+  /**
+   * ClutterStage::unfullscreen
+   * @stage: the stage which has left a fullscreen state.
+   *
+   * The ::unfullscreen signal is emitted when the stage leaves a fullscreen
+   * state.
+   *
+   * Since: 0.6
+   */
+  stage_signals[UNFULLSCREEN] =
+    g_signal_new ("unfullscreen",
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (ClutterStageClass, unfullscreen),
+                 NULL, NULL,
+                 clutter_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+
+
+  /**
+   * ClutterStage::activate
+   * @stage: the stage which was activated
+   *
+   * The ::activate signal is emitted when the stage recieves key focus
+   * from the underlying window system.
+   *
+   * Since: 0.6
+   */
+  stage_signals[ACTIVATE] =
+    g_signal_new ("activate",
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (ClutterStageClass, activate),
+                 NULL, NULL,
+                 clutter_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+
+  /**
+   * ClutterStage::deactivate
+   * @stage: the stage which was deactivated
+   *
+   * The ::activate signal is emitted when the stage loses key focus
+   * from the underlying window system.
+   *
+   * Since: 0.6
+   */
+  stage_signals[DEACTIVATE] =
+    g_signal_new ("deactivate",
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (ClutterStageClass, deactivate),
+                 NULL, NULL,
+                 clutter_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
   
   g_type_class_add_private (gobject_class, sizeof (ClutterStagePrivate));
 }
@@ -750,7 +823,30 @@ clutter_stage_event (ClutterStage *stage,
   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
-  /* FIXME: Handle StageState Changes and Delete events */
+  if (event->type == CLUTTER_DELETE)
+    return TRUE;
+
+  if (event->type != CLUTTER_STAGE_STATE)
+    return FALSE;
+
+  /* emit raw event */
+  clutter_actor_event (CLUTTER_ACTOR(stage), event);
+
+  if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_FULLSCREEN)
+    {
+      if (event->stage_state.new_state & CLUTTER_STAGE_STATE_FULLSCREEN)
+       g_signal_emit (stage, stage_signals[FULLSCREEN], 0);
+      else
+       g_signal_emit (stage, stage_signals[UNFULLSCREEN], 0);
+    }
+  
+  if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_ACTIVATED)
+    {
+      if (event->stage_state.new_state & CLUTTER_STAGE_STATE_ACTIVATED)
+       g_signal_emit (stage, stage_signals[ACTIVATE], 0);
+      else
+       g_signal_emit (stage, stage_signals[DEACTIVATE], 0);
+    }
 
   return TRUE;
 }
index d10d2ad..462fcf1 100644 (file)
@@ -99,8 +99,10 @@ struct _ClutterStageClass
                                         gboolean      value);
 
   /* events */
-  void     (* stage_state_event)    (ClutterStage           *stage,
-                                     ClutterStageStateEvent *event);
+  void     (* fullscreen)      (ClutterStage           *stage);
+  void     (* unfullscreen)    (ClutterStage           *stage);
+  void     (* activate)        (ClutterStage           *stage);
+  void     (* deactivate)      (ClutterStage           *stage);
 
   /*< private >*/
   /* padding for future expansion */
index 088c4eb..6725975 100644 (file)
@@ -374,11 +374,17 @@ cogl_texture_image_2d (COGLenum      target,
                       const guchar* pixels)
 {
   GE( glTexImage2D (target,
-                   0,          /* No mipmap support as yet */
-                   internal_format,
+                   0,  
+                   format, /* HACK: For gles we set the internal_format equal
+                            * to the pixel format. This is for RGB data (i.e
+                            * jpgs) which seem to need a matching internal
+                             * format rather than RGBA (which is used by GL) 
+                            *.
+                             * This fix isn't ideal..
+                            */
                    width,
                    height,
-                   0,          /* 0 pixel border */
+                   0,  
                    format,
                    type,
                    pixels) );
index 5269b2d..0848440 100644 (file)
@@ -210,6 +210,11 @@ clutter_backend_glx_post_parse (ClutterBackend  *backend,
 
       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);
index 8da36d1..db47918 100644 (file)
@@ -89,6 +89,10 @@ struct _ClutterBackendGLX
   SwapIntervalProc       swap_interval;
   gint                   dri_fd;
   ClutterGLXVBlankType   vblank_type;
+
+  /* props */
+  Atom atom_WM_STATE;
+  Atom atom_WM_STATE_FULLSCREEN;
 };
 
 struct _ClutterBackendGLXClass
index 8636601..0941af0 100644 (file)
@@ -355,13 +355,15 @@ event_translate (ClutterBackend *backend,
                 XEvent         *xevent)
 {
   ClutterBackendGLX *backend_glx;
-  ClutterStage *stage;
-  gboolean res;
-  Window xwindow, stage_xwindow;
+  ClutterStageGLX   *stage_glx;
+  ClutterStage      *stage;
+  gboolean           res;
+  Window             xwindow, stage_xwindow;
 
-  backend_glx = CLUTTER_BACKEND_GLX (backend);
-  stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend));
-  stage_xwindow = clutter_glx_get_stage_window (stage);
+  backend_glx    = CLUTTER_BACKEND_GLX (backend);
+  stage          = CLUTTER_STAGE (_clutter_backend_get_stage (backend));
+  stage_glx      = CLUTTER_STAGE_GLX (stage);
+  stage_xwindow  = clutter_glx_get_stage_window (stage);
 
   xwindow = xevent->xany.window;
   if (xwindow == None)
@@ -397,6 +399,99 @@ event_translate (ClutterBackend *backend,
 
   switch (xevent->type)
     {
+    case ConfigureNotify:
+      if (xevent->xconfigure.width 
+         != clutter_actor_get_width (CLUTTER_ACTOR (stage))
+         ||
+         xevent->xconfigure.height 
+         != clutter_actor_get_height (CLUTTER_ACTOR (stage)))
+       clutter_actor_set_size (CLUTTER_ACTOR (stage),
+                               xevent->xconfigure.width,
+                               xevent->xconfigure.height);
+      res = FALSE;
+      break;
+    case PropertyNotify:
+      {
+       if (xevent->xproperty.atom == backend_glx->atom_WM_STATE)
+         {
+           Atom     type;
+           gint     format;
+           gulong   nitems, bytes_after;
+           guchar  *data = NULL;
+           Atom    *atoms = NULL;
+           gulong   i;
+           gboolean fullscreen_set = FALSE;
+
+           clutter_glx_trap_x_errors ();
+           XGetWindowProperty (backend_glx->xdpy, 
+                               stage_xwindow,
+                               backend_glx->atom_WM_STATE,
+                               0, G_MAXLONG, 
+                               False, XA_ATOM, 
+                               &type, &format, &nitems,
+                               &bytes_after, &data);
+           clutter_glx_untrap_x_errors ();
+
+           if (type != None && data != NULL)
+             {
+               atoms = (Atom *)data;
+
+               i = 0;
+               while (i < nitems)
+                 {
+                   if (atoms[i] == backend_glx->atom_WM_STATE_FULLSCREEN)
+                     fullscreen_set = TRUE;
+                   i++;
+                 }
+
+               if (fullscreen_set 
+                     != !!(stage_glx->state & CLUTTER_STAGE_STATE_FULLSCREEN))
+                 {
+                   if (fullscreen_set)
+                     stage_glx->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
+                   else
+                     stage_glx->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
+
+                   event->type = CLUTTER_STAGE_STATE;
+                   event->stage_state.changed_mask 
+                               = CLUTTER_STAGE_STATE_FULLSCREEN;
+                   event->stage_state.new_state = stage_glx->state;
+                 }
+               else
+                 res = FALSE;
+
+               XFree (data);
+             }
+         }
+       else
+         res = FALSE;
+      }
+      break;
+    case FocusIn:
+      if (!(stage_glx->state & CLUTTER_STAGE_STATE_ACTIVATED))
+       {
+         /* TODO: check xevent->xfocus.detail ? */
+         stage_glx->state |= CLUTTER_STAGE_STATE_ACTIVATED;
+
+         event->type = CLUTTER_STAGE_STATE;
+         event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
+         event->stage_state.new_state = stage_glx->state;
+       }
+      else
+       res = FALSE;
+      break;
+    case FocusOut:
+      if (stage_glx->state & CLUTTER_STAGE_STATE_ACTIVATED)
+       {
+         stage_glx->state &= ~CLUTTER_STAGE_STATE_ACTIVATED;
+
+         event->type = CLUTTER_STAGE_STATE;
+         event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
+         event->stage_state.new_state = stage_glx->state;
+       }
+      else
+       res = FALSE;
+      break;
     case Expose:
       {
         XEvent foo_xev;
index b969765..8cc8d2b 100644 (file)
 
 G_DEFINE_TYPE (ClutterStageGLX, clutter_stage_glx, 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 (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)
 {
@@ -83,6 +115,9 @@ 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.
@@ -236,6 +271,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
       CLUTTER_NOTE (MISC, "XSelectInput");
       XSelectInput (stage_glx->xdpy, stage_glx->xwin,
                     StructureNotifyMask |
+                   FocusChangeMask |
                     ExposureMask |
                   /* FIXME: we may want to eplicity enable MotionMask */
                    PointerMotionMask |
@@ -434,33 +470,76 @@ clutter_stage_glx_set_fullscreen (ClutterStage *stage,
                                   gboolean      fullscreen)
 {
   ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage);
-  Atom atom_WM_STATE, atom_WM_STATE_FULLSCREEN;
+  ClutterBackendGLX *backend_glx = stage_glx->backend;
 
-  atom_WM_STATE = XInternAtom (stage_glx->xdpy, "_NET_WM_STATE", False);
-  atom_WM_STATE_FULLSCREEN = XInternAtom (stage_glx->xdpy,
-                                          "_NET_WM_STATE_FULLSCREEN",
-                                          False);
+  static gboolean was_resizeable = FALSE;
 
   if (fullscreen)
     {
-      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);
-
       if (stage_glx->xwin != None)
-       XChangeProperty (stage_glx->xdpy,
-                         stage_glx->xwin,
-                         atom_WM_STATE, XA_ATOM, 32,
-                         PropModeReplace,
-                         (unsigned char *) &atom_WM_STATE_FULLSCREEN, 1);
+       {
+         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)
-        XDeleteProperty (stage_glx->xdpy, stage_glx->xwin, atom_WM_STATE);
+       {
+         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);
index 9ff5949..c81b674 100644 (file)
@@ -65,6 +65,7 @@ struct _ClutterStageGLX
 
   ClutterBackendGLX *backend;
 
+  ClutterStageState  state;
 };
 
 struct _ClutterStageGLXClass
index aed891e..3b11b27 100644 (file)
@@ -205,19 +205,26 @@ case $clutterbackend in
     CLUTTER_COGL="gles"
     AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL/ES for rendering])
 
-    # try for libvincent first
+    # 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 GLES/gl.h],,
                 [AC_MSG_ERROR([Unable to locate required GLES headers])])
 
-      AC_CHECK_LIB(GLES_CM, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no)
+      # No libvincent so start checking for upper/lower case libgles_em
+      # The powervr sdk uses lower case.
 
+      AC_CHECK_LIB(GLES_CM, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no)
       if test "x$HAVE_LIBGLES" = "xno"; then
+        
+        AC_CHECK_LIB(gles_cm, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no)
+       if test "x$HAVE_LIBGLES" = "xno"; then
          AC_MSG_ERROR([GLES library not found and egl backend requested.]);
+       fi
+        EGL_LIBS="-lgles_cm"  
+      else
+        EGL_LIBS="-lGLES_CM"  
       fi
-
-      EGL_LIBS="-lGLES_CM"
     fi
 
     EGL_LIBS="$EGL_LIBS $X11_LIBS"
index 11dc131..e56b346 100644 (file)
@@ -1,6 +1,32 @@
 #include <clutter/clutter.h>
 
+gboolean IsFullScreen = FALSE;
 
+static void
+stage_state_cb (ClutterStage    *stage,
+               gpointer         data)
+{
+  gchar *detail = (gchar*)data;
+
+  printf("[stage signal] %s\n", detail);
+}
+
+static void
+blue_button_cb (ClutterActor    *actor,
+               ClutterEvent    *event,
+               gpointer         data)
+{
+  ClutterActor *stage;
+
+  stage = clutter_stage_get_default ();
+
+  if (IsFullScreen)
+    IsFullScreen = FALSE;
+  else
+    IsFullScreen = TRUE;
+
+  g_object_set (stage, "fullscreen", IsFullScreen, NULL);
+}
 
 void
 key_focus_in_cb (ClutterActor    *actor,
@@ -104,6 +130,14 @@ main (int argc, char *argv[])
 
   stage = clutter_stage_get_default ();
   g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage");
+  g_signal_connect (stage, "fullscreen", 
+                   G_CALLBACK (stage_state_cb), "fullscreen");
+  g_signal_connect (stage, "unfullscreen", 
+                   G_CALLBACK (stage_state_cb), "unfullscreen");
+  g_signal_connect (stage, "activate", 
+                   G_CALLBACK (stage_state_cb), "activate");
+  g_signal_connect (stage, "deactivate", 
+                   G_CALLBACK (stage_state_cb), "deactivate");
 
   focus_box = clutter_rectangle_new_with_color (&ncol);
   clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
@@ -145,6 +179,7 @@ main (int argc, char *argv[])
   g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
   g_signal_connect (actor, "focus-in", G_CALLBACK (key_focus_in_cb), 
                    focus_box);
+  g_signal_connect (actor, "button-press-event", G_CALLBACK (blue_button_cb), NULL);
 
   actor = clutter_rectangle_new_with_color (&ncol);
   clutter_actor_set_size (actor, 400, 50);
index 7942e7f..9b2b74c 100644 (file)
@@ -3,6 +3,24 @@
 #include <clutter/clutter.h>
 
 static void
+timeline_1_complete (ClutterTimeline *timeline)
+{
+  g_debug ("1: Completed");
+}
+
+static void
+timeline_2_complete (ClutterTimeline *timeline)
+{
+  g_debug ("2: Completed");
+}
+
+static void
+timeline_3_complete (ClutterTimeline *timeline)
+{
+  g_debug ("3: Completed");
+}
+
+static void
 timeline_1_new_frame_cb (ClutterTimeline *timeline, gint frame_no)
 {
   g_debug ("1: Doing frame %d.", frame_no);
@@ -29,19 +47,30 @@ main (int argc, char **argv)
 
   clutter_init (&argc, &argv);
 
-  timeline_1 = clutter_timeline_new (100, 50);
+  timeline_1 = clutter_timeline_new (10, 120);
   timeline_2 = clutter_timeline_clone (timeline_1);
   timeline_3 = clutter_timeline_clone (timeline_1);
 
   g_signal_connect (timeline_1,
                     "new-frame", G_CALLBACK (timeline_1_new_frame_cb),
                     NULL);
+  g_signal_connect (timeline_1,
+                    "completed", G_CALLBACK (timeline_1_complete),
+                    NULL);
+
   g_signal_connect (timeline_2,
                     "new-frame", G_CALLBACK (timeline_2_new_frame_cb),
                     NULL);
+  g_signal_connect (timeline_2,
+                    "completed", G_CALLBACK (timeline_2_complete),
+                    NULL);
+
   g_signal_connect (timeline_3,
                     "new-frame", G_CALLBACK (timeline_3_new_frame_cb),
                     NULL);
+  g_signal_connect (timeline_3,
+                    "completed", G_CALLBACK (timeline_3_complete),
+                    NULL);
 
   clutter_timeline_start (timeline_1);
   clutter_timeline_start (timeline_2);