diff options
author | Alexander Larsson <alexl@redhat.com> | 2012-06-01 16:55:59 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2012-06-05 11:06:56 +0200 |
commit | c98d0593d6d382028637dd3dcf285016f84fad72 (patch) | |
tree | cd6999e7d3868cb6648c14529245d6ed502ef35f | |
parent | 8cd6fde59a732951999692db451fb7e85d103017 (diff) | |
download | clutter-gtk-c98d0593d6d382028637dd3dcf285016f84fad72.tar.gz |
Allow GtkClutterEmbed to follow the ClutterStage size
This is nice when you combine Gtk and Clutter layouts, for instance
to get a right minimum size for the window.
https://bugzilla.gnome.org/show_bug.cgi?id=677282
-rw-r--r-- | clutter-gtk/gtk-clutter-embed.c | 236 | ||||
-rw-r--r-- | clutter-gtk/gtk-clutter-embed.h | 3 |
2 files changed, 238 insertions, 1 deletions
diff --git a/clutter-gtk/gtk-clutter-embed.c b/clutter-gtk/gtk-clutter-embed.c index 1a4fce1..add1078 100644 --- a/clutter-gtk/gtk-clutter-embed.c +++ b/clutter-gtk/gtk-clutter-embed.c @@ -45,6 +45,7 @@ #include "config.h" #endif +#include <math.h> #include "gtk-clutter-embed.h" #include "gtk-clutter-offscreen.h" #include "gtk-clutter-actor.h" @@ -87,6 +88,14 @@ struct _GtkClutterEmbedPrivate guint queue_redraw_id; guint geometry_changed : 1; + guint use_layout_size : 1; +}; + +enum +{ + PROP_0, + + PROP_USE_LAYOUT_SIZE }; static void @@ -365,6 +374,111 @@ gtk_clutter_embed_unrealize (GtkWidget *widget) GTK_WIDGET_CLASS (gtk_clutter_embed_parent_class)->unrealize (widget); } +static GtkSizeRequestMode +gtk_clutter_embed_get_request_mode (GtkWidget *widget) +{ + GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv; + GtkSizeRequestMode mode; + + mode = GTK_SIZE_REQUEST_CONSTANT_SIZE; + if (priv->stage != NULL && + priv->use_layout_size && + clutter_actor_get_layout_manager (priv->stage) != NULL) + { + switch (clutter_actor_get_request_mode (priv->stage)) + { + case CLUTTER_REQUEST_HEIGHT_FOR_WIDTH: + mode = GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; + break; + case CLUTTER_REQUEST_WIDTH_FOR_HEIGHT: + mode = GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT; + break; + } + } + + return mode; +} + +static void +gtk_clutter_embed_get_preferred_width_for_height (GtkWidget *widget, + gint height, + gint *minimum, + gint *natural) +{ + GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv; + float min, nat; + + min = 0; + nat = 0; + + if (priv->stage != NULL && + priv->use_layout_size) + { + ClutterLayoutManager *manager = clutter_actor_get_layout_manager (priv->stage); + if (manager) + clutter_layout_manager_get_preferred_width (manager, + CLUTTER_CONTAINER (priv->stage), + (float)height, &min, &nat); + } + + min = ceilf (min); + nat = ceilf (nat); + + if (minimum) + *minimum = min; + + if (natural) + *natural = nat; +} + +static void +gtk_clutter_embed_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum, + gint *natural) +{ + GtkClutterEmbedPrivate *priv = GTK_CLUTTER_EMBED (widget)->priv; + float min, nat; + + min = 0; + nat = 0; + + if (priv->stage != NULL && + priv->use_layout_size) + { + ClutterLayoutManager *manager = clutter_actor_get_layout_manager (priv->stage); + if (manager) + clutter_layout_manager_get_preferred_height (manager, + CLUTTER_CONTAINER (priv->stage), + (float)width, &min, &nat); + } + + min = ceilf (min); + nat = ceilf (nat); + + if (minimum) + *minimum = min; + + if (natural) + *natural = nat; +} + +static void +gtk_clutter_embed_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + gtk_clutter_embed_get_preferred_width_for_height (widget, -1, minimum, natural); +} + +static void +gtk_clutter_embed_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + gtk_clutter_embed_get_preferred_height_for_width (widget, -1, minimum, natural); +} + static void gtk_clutter_embed_size_allocate (GtkWidget *widget, GtkAllocation *allocation) @@ -696,15 +810,58 @@ gtk_clutter_embed_state_flags_changed (GtkWidget *widget, } static void +gtk_clutter_embed_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkClutterEmbed *embed = GTK_CLUTTER_EMBED (gobject); + + switch (prop_id) + { + case PROP_USE_LAYOUT_SIZE: + gtk_clutter_embed_set_use_layout_size (embed, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +gtk_clutter_embed_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkClutterEmbed *embed = GTK_CLUTTER_EMBED (gobject); + + switch (prop_id) + { + case PROP_USE_LAYOUT_SIZE: + g_value_set_boolean (value, embed->priv->use_layout_size); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void gtk_clutter_embed_class_init (GtkClutterEmbedClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); + GParamSpec *pspec; g_type_class_add_private (klass, sizeof (GtkClutterEmbedPrivate)); gobject_class->dispose = gtk_clutter_embed_dispose; + gobject_class->set_property = gtk_clutter_embed_set_property; + gobject_class->get_property = gtk_clutter_embed_get_property; widget_class->style_updated = gtk_clutter_embed_style_updated; widget_class->size_allocate = gtk_clutter_embed_size_allocate; @@ -721,11 +878,31 @@ gtk_clutter_embed_class_init (GtkClutterEmbedClass *klass) widget_class->key_release_event = gtk_clutter_embed_key_event; widget_class->event = gtk_clutter_embed_event; widget_class->state_flags_changed = gtk_clutter_embed_state_flags_changed; + widget_class->get_request_mode = gtk_clutter_embed_get_request_mode; + widget_class->get_preferred_width = gtk_clutter_embed_get_preferred_width; + widget_class->get_preferred_height = gtk_clutter_embed_get_preferred_height; + widget_class->get_preferred_width_for_height = gtk_clutter_embed_get_preferred_width_for_height; + widget_class->get_preferred_height_for_width = gtk_clutter_embed_get_preferred_height_for_width; container_class->add = gtk_clutter_embed_add; container_class->remove = gtk_clutter_embed_remove; container_class->forall = gtk_clutter_embed_forall; container_class->child_type = gtk_clutter_embed_child_type; + + + /** + * GtkClutterEmbed:use-layout-size: + * + * The #GtkWidget to be embedded into the #GtkClutterActor + * + * Since: 1.4 + */ + pspec = g_param_spec_boolean ("use-layout-size", + "Use layout size", + "Whether to use the reported size of the LayoutManager on the stage as the widget size.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_USE_LAYOUT_SIZE, pspec); } static void @@ -735,7 +912,6 @@ gtk_clutter_embed_init (GtkClutterEmbed *embed) GtkWidget *widget; embed->priv = priv = GTK_CLUTTER_EMBED_GET_PRIVATE (embed); - widget = GTK_WIDGET (embed); /* we have a real window backing our drawing */ @@ -801,3 +977,61 @@ gtk_clutter_embed_get_stage (GtkClutterEmbed *embed) return embed->priv->stage; } + +/** + * gtk_clutter_embed_set_use_layout_size: + * @embed: a #GtkClutterEmbed + * @use_layout_size: a boolean + * + * Changes the way @embed requests size. If @use_layout_size is + * %TRUE, the @embed widget will request the size that the + * LayoutManager reports as the preferred size. This means that + * a Gtk+ window will automatically get the natural and minimum + * toplevel window sizes. This is useful when the contents of the + * clutter stage is similar to a traditional UI. + * + * If @use_layout_size is %FALSE (which is the default) then @embed + * will not request any size and its up to the embedder to make sure + * there is some size (by setting a custom size on the widget or a default + * size on the toplevel. This makes more sense when using the @embed + * as a viewport into a potentially unlimited clutter space. + * + * Since: 1.4 + */ +void +gtk_clutter_embed_set_use_layout_size (GtkClutterEmbed *embed, + gboolean use_layout_size) +{ + GtkClutterEmbedPrivate *priv = embed->priv; + + g_return_if_fail (GTK_CLUTTER_IS_EMBED (embed)); + + use_layout_size = !!use_layout_size; + if (use_layout_size != priv->use_layout_size) + { + priv->use_layout_size = use_layout_size; + gtk_widget_queue_resize (GTK_WIDGET (embed)); + g_object_notify (G_OBJECT (embed), "use-layout-size"); + } +} + +/** + * gtk_clutter_embed_get_use_layout_size: + * @embed: a #GtkClutterEmbed + * + * Retrieves whether the embedding uses the layout size, see + * gtk_clutter_embed_set_use_layout_size() for details. + * + * Return value: %TRUE if reporting stage size as widget size, %FALSE otherwise. + * + * Since: 1.4 + */ +gboolean +gtk_clutter_embed_get_honor_stage_size (GtkClutterEmbed *embed) +{ + GtkClutterEmbedPrivate *priv = embed->priv; + + g_return_val_if_fail (GTK_CLUTTER_IS_EMBED (embed), FALSE); + + return priv->use_layout_size; +} diff --git a/clutter-gtk/gtk-clutter-embed.h b/clutter-gtk/gtk-clutter-embed.h index af7fc3f..a6214db 100644 --- a/clutter-gtk/gtk-clutter-embed.h +++ b/clutter-gtk/gtk-clutter-embed.h @@ -85,6 +85,9 @@ GType gtk_clutter_embed_get_type (void) G_GNUC_CONST; GtkWidget * gtk_clutter_embed_new (void); ClutterActor *gtk_clutter_embed_get_stage (GtkClutterEmbed *embed); +void gtk_clutter_embed_set_use_layout_size (GtkClutterEmbed *embed, + gboolean honor_size); +gboolean gtk_clutter_embed_get_use_layout_size (GtkClutterEmbed *embed); G_END_DECLS |