Blame clutter-gtk/gtk-clutter-window.c

Packit 1069cd
/* gtk-clutter-window.c: GtkWindow which provides a hidden ClutterStage
Packit 1069cd
 *
Packit 1069cd
 * Copyright (C) 2009 Collabora Ltd.
Packit 1069cd
 *
Packit 1069cd
 * This library is free software; you can redistribute it and/or
Packit 1069cd
 * modify it under the terms of the GNU Lesser General Public
Packit 1069cd
 * License as published by the Free Software Foundation; either
Packit 1069cd
 * version 2 of the License, or (at your option) any later version.
Packit 1069cd
 *
Packit 1069cd
 * This library is distributed in the hope that it will be useful,
Packit 1069cd
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 1069cd
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 1069cd
 * Lesser General Public License for more details.
Packit 1069cd
 *
Packit 1069cd
 * You should have received a copy of the GNU Lesser General Public
Packit 1069cd
 * License along with this library. If not see <http://www.fsf.org/licensing>.
Packit 1069cd
 *
Packit 1069cd
 * Authors:
Packit 1069cd
 *   Danielle Madeley <danielle.madeley@collabora.co.uk>
Packit 1069cd
 */
Packit 1069cd
Packit 1069cd
/**
Packit 1069cd
 * SECTION:gtk-clutter-window
Packit 1069cd
 * @Title: GtkClutterWindow
Packit 1069cd
 * @short_description: a GtkWindow that embeds its contents onto a stage
Packit 1069cd
 *
Packit 1069cd
 * #GtkClutterWindow is a #GtkWindow sub-class that embeds a Clutter stage.
Packit 1069cd
 *
Packit 1069cd
 * #GtkClutterWindow behaves exactly like a #GtkWindow, except that its
Packit 1069cd
 * child is automatically embedded inside a #GtkClutterActor and it is
Packit 1069cd
 * thus part of the embedded #ClutterStage.
Packit 1069cd
 *
Packit 1069cd
 * Clutter actors can be added to the same stage by calling
Packit 1069cd
 * gtk_clutter_window_get_stage().
Packit 1069cd
 */
Packit 1069cd
Packit 1069cd
#include "config.h"
Packit 1069cd
Packit 1069cd
#include "gtk-clutter-window.h"
Packit 1069cd
#include "gtk-clutter-actor.h"
Packit 1069cd
#include "gtk-clutter-embed.h"
Packit 1069cd
#include "gtk-clutter-util.h"
Packit 1069cd
Packit 1069cd
#include <glib-object.h>
Packit 1069cd
Packit 1069cd
G_DEFINE_TYPE (GtkClutterWindow, gtk_clutter_window, GTK_TYPE_WINDOW);
Packit 1069cd
Packit 1069cd
#define GTK_CLUTTER_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_CLUTTER_TYPE_WINDOW, GtkClutterWindowPrivate))
Packit 1069cd
Packit 1069cd
struct _GtkClutterWindowPrivate
Packit 1069cd
{
Packit 1069cd
  GtkWidget *embed;
Packit 1069cd
Packit 1069cd
  ClutterActor *actor;
Packit 1069cd
};
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_finalize (GObject *self)
Packit 1069cd
{
Packit 1069cd
  G_OBJECT_CLASS (gtk_clutter_window_parent_class)->finalize (self);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_get_preferred_width (GtkWidget *self,
Packit 1069cd
                                        gint      *minimum,
Packit 1069cd
                                        gint      *natural)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
  gtk_widget_get_preferred_width (gtk_bin_get_child (GTK_BIN (bin)),
Packit 1069cd
                                  minimum,
Packit 1069cd
                                  natural);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_get_preferred_height (GtkWidget *self,
Packit 1069cd
                                         gint      *minimum,
Packit 1069cd
                                         gint      *natural)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
  gtk_widget_get_preferred_height (gtk_bin_get_child (GTK_BIN (bin)),
Packit 1069cd
                                   minimum,
Packit 1069cd
                                   natural);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_add (GtkContainer *self,
Packit 1069cd
                        GtkWidget    *widget)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  g_return_if_fail (GTK_CLUTTER_IS_WINDOW (self));
Packit 1069cd
  priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
  GTK_CONTAINER_GET_CLASS (bin)->add (GTK_CONTAINER (bin), widget);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_remove (GtkContainer *self,
Packit 1069cd
                           GtkWidget    *widget)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  g_return_if_fail (GTK_CLUTTER_IS_WINDOW (self));
Packit 1069cd
  priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
  GTK_CONTAINER_GET_CLASS (bin)->remove (GTK_CONTAINER (bin), widget);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_forall (GtkContainer *self,
Packit 1069cd
                           gboolean      include_internals,
Packit 1069cd
                           GtkCallback   callback,
Packit 1069cd
                           gpointer      callback_data)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  g_return_if_fail (GTK_CLUTTER_IS_WINDOW (self));
Packit 1069cd
  priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
Packit 1069cd
  /* this is particularly dodgy -- if we have asked to include_internals
Packit 1069cd
   * let's only return the internals, on the assumption that when events
Packit 1069cd
   * are sent to those internals, the child container will be iterated;
Packit 1069cd
   * otherwise, we don't want anyone to know about the container, so we
Packit 1069cd
   * return the contents of the bin */
Packit 1069cd
  if (include_internals)
Packit 1069cd
    {
Packit 1069cd
      GTK_CONTAINER_CLASS (gtk_clutter_window_parent_class)->forall (self,
Packit 1069cd
              include_internals, callback, callback_data);
Packit 1069cd
    }
Packit 1069cd
  else
Packit 1069cd
    {
Packit 1069cd
      bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
      GTK_CONTAINER_GET_CLASS (bin)->forall (GTK_CONTAINER (bin),
Packit 1069cd
              include_internals, callback, callback_data);
Packit 1069cd
    }
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_set_focus_child (GtkContainer *self,
Packit 1069cd
                                    GtkWidget    *widget)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  g_return_if_fail (GTK_CLUTTER_IS_WINDOW (self));
Packit 1069cd
  priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
  GTK_CONTAINER_GET_CLASS (bin)->set_focus_child (GTK_CONTAINER (bin), widget);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static GType
Packit 1069cd
gtk_clutter_window_child_type (GtkContainer *self)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
Packit 1069cd
  return GTK_CONTAINER_GET_CLASS (bin)->child_type (GTK_CONTAINER (bin));
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static char *
Packit 1069cd
gtk_clutter_window_composite_name (GtkContainer *self,
Packit 1069cd
                                   GtkWidget    *widget)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
Packit 1069cd
  return GTK_CONTAINER_GET_CLASS (bin)->composite_name (GTK_CONTAINER (bin),
Packit 1069cd
                                                        widget);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_set_child_property (GtkContainer *self,
Packit 1069cd
                                       GtkWidget    *widget,
Packit 1069cd
                                       guint         property_id,
Packit 1069cd
                                       const GValue *value,
Packit 1069cd
                                       GParamSpec   *pspec)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
Packit 1069cd
  GTK_CONTAINER_GET_CLASS (bin)->set_child_property (GTK_CONTAINER (bin),
Packit 1069cd
                                                     widget,
Packit 1069cd
                                                     property_id,
Packit 1069cd
                                                     value, pspec);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_get_child_property (GtkContainer *self,
Packit 1069cd
                                       GtkWidget    *widget,
Packit 1069cd
                                       guint         property_id,
Packit 1069cd
                                       GValue       *value,
Packit 1069cd
                                       GParamSpec   *pspec)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  GtkWidget *bin;
Packit 1069cd
Packit 1069cd
  priv = GTK_CLUTTER_WINDOW (self)->priv;
Packit 1069cd
  bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (priv->actor));
Packit 1069cd
Packit 1069cd
  GTK_CONTAINER_GET_CLASS (bin)->get_child_property (GTK_CONTAINER (bin),
Packit 1069cd
                                                     widget,
Packit 1069cd
                                                     property_id,
Packit 1069cd
                                                     value, pspec);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_class_init (GtkClutterWindowClass *klass)
Packit 1069cd
{
Packit 1069cd
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit 1069cd
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
Packit 1069cd
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
Packit 1069cd
Packit 1069cd
  g_type_class_add_private (klass, sizeof (GtkClutterWindowPrivate));
Packit 1069cd
Packit 1069cd
  gobject_class->finalize = gtk_clutter_window_finalize;
Packit 1069cd
Packit 1069cd
  widget_class->get_preferred_width = gtk_clutter_window_get_preferred_width;
Packit 1069cd
  widget_class->get_preferred_height = gtk_clutter_window_get_preferred_height;
Packit 1069cd
Packit 1069cd
  /* connect all of the container methods up to our bin */
Packit 1069cd
  container_class->add                = gtk_clutter_window_add;
Packit 1069cd
  container_class->remove             = gtk_clutter_window_remove;
Packit 1069cd
  container_class->forall             = gtk_clutter_window_forall;
Packit 1069cd
  container_class->set_focus_child    = gtk_clutter_window_set_focus_child;
Packit 1069cd
  container_class->child_type         = gtk_clutter_window_child_type;
Packit 1069cd
  container_class->composite_name     = gtk_clutter_window_composite_name;
Packit 1069cd
  container_class->set_child_property = gtk_clutter_window_set_child_property;
Packit 1069cd
  container_class->get_child_property = gtk_clutter_window_get_child_property;
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
static void
Packit 1069cd
gtk_clutter_window_init (GtkClutterWindow *self)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
  ClutterActor *stage;
Packit 1069cd
Packit 1069cd
  self->priv = priv = GTK_CLUTTER_WINDOW_GET_PRIVATE (self);
Packit 1069cd
Packit 1069cd
  priv->embed = gtk_clutter_embed_new ();
Packit 1069cd
  gtk_widget_set_name (priv->embed, "GtkClutterEmbed");
Packit 1069cd
Packit 1069cd
  GTK_CONTAINER_CLASS (gtk_clutter_window_parent_class)->add (GTK_CONTAINER (self), priv->embed);
Packit 1069cd
  gtk_widget_show (priv->embed);
Packit 1069cd
Packit 1069cd
  stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (priv->embed));
Packit 1069cd
Packit 1069cd
  priv->actor = gtk_clutter_actor_new ();
Packit 1069cd
  clutter_actor_add_child (stage, priv->actor);
Packit 1069cd
  clutter_actor_set_name (priv->actor, "GtkClutterActor");
Packit 1069cd
  clutter_actor_add_constraint_with_name (priv->actor, "content-x",
Packit 1069cd
                                          clutter_bind_constraint_new (stage, CLUTTER_BIND_WIDTH, 0.0));
Packit 1069cd
  clutter_actor_add_constraint_with_name (priv->actor, "content-y",
Packit 1069cd
                                          clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, 0.0));
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
/**
Packit 1069cd
 * gtk_clutter_window_new:
Packit 1069cd
 *
Packit 1069cd
 * Creates a new #GtkClutterWindow widget.
Packit 1069cd
 *
Packit 1069cd
 * This window provides a hidden #ClutterStage on which the child
Packit 1069cd
 * #GtkWidgets are placed. This allows other #ClutterActors
Packit 1069cd
 * to also be placed on the stage.
Packit 1069cd
 *
Packit 1069cd
 * Return value: the newly created #GtkClutterWindow
Packit 1069cd
 */
Packit 1069cd
GtkWidget *
Packit 1069cd
gtk_clutter_window_new (void)
Packit 1069cd
{
Packit 1069cd
  return g_object_new (GTK_CLUTTER_TYPE_WINDOW, NULL);
Packit 1069cd
}
Packit 1069cd
Packit 1069cd
/**
Packit 1069cd
 * gtk_clutter_window_get_stage:
Packit 1069cd
 * @window: the #GtkClutterWindow
Packit 1069cd
 *
Packit 1069cd
 * Retrieves the #ClutterStage that this window is embedding
Packit 1069cd
 *
Packit 1069cd
 * Use this function if you wish to add other actors to the #ClutterStage.
Packit 1069cd
 *
Packit 1069cd
 * Return value: (transfer none): the window's #ClutterStage
Packit 1069cd
 */
Packit 1069cd
ClutterActor *
Packit 1069cd
gtk_clutter_window_get_stage (GtkClutterWindow *window)
Packit 1069cd
{
Packit 1069cd
  GtkClutterWindowPrivate *priv;
Packit 1069cd
Packit 1069cd
  g_return_val_if_fail (GTK_CLUTTER_IS_WINDOW (window), NULL);
Packit 1069cd
Packit 1069cd
  priv = window->priv;
Packit 1069cd
Packit 1069cd
  return gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (priv->embed));
Packit 1069cd
}